go test -cover 默认仅输出百分比,生成 HTML 报告需两步:先用 -coverprofile=cover.out -covermode=count ./... 采集数据,再用 go tool cover -html=cover.out -o=coverage.html 渲染。

go test -cover 默认只输出覆盖率百分比,不生成报告
直接运行 go test -cover 只会在终端打印类似 coverage: 65.2% of statements 的单行结果,没有 HTML 或详细文件级统计。这是最常被误解的一点——很多人以为加了 -cover 就自动有报告了。
真正生成可读报告,必须配合 -coverprofile 输出覆盖率数据文件,再用 go tool cover 渲染。
-
-coverprofile=cover.out是必选项,指定覆盖率数据输出路径 - 默认只覆盖当前包;跨包(如子目录、内部测试依赖)需显式列出或使用
./... - 若测试中用了
os.Exit(0)或 panic 未被捕获,可能导致部分代码未计入统计
生成 HTML 报告的完整命令链
两步不可省:先采集数据,再渲染视图。中间文件 cover.out 是二进制格式,不能手动编辑或查看。
推荐在项目根目录执行:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
go test -coverprofile=cover.out -covermode=count ./... go tool cover -html=cover.out -o=coverage.html
-covermode=count 比默认的 set 更有用:它记录每行被执行次数,HTML 中能看清哪些分支/循环体实际跑了多少遍。
- 如果只想看某个子包,把
./...换成./storage或./handlers/auth -
coverage.html打开后,绿色=覆盖,红色=未覆盖,灰色=不可覆盖(如if false、函数签名行) - 注意:HTML 报告里的文件路径是相对 GOPATH 或 module root 的,点击跳转可能失效——别双击打开,用浏览器拖入或
file://协议访问
常见错误:cover.out 为空或覆盖率异常低
运行完 go test -coverprofile=cover.out ./... 后,cover.out 文件大小为 0 或 HTML 显示 “no statements” —— 这通常不是工具问题,而是测试没真正执行到目标代码。
- 检查测试是否 import 错误的包路径(比如用了
myproject/v2/pkg但实际代码在myproject/pkg) - 确认测试函数名以
Test开头且首字母大写,且参数是*testing.T - 如果用了
//go:build ignore或构建约束,确保测试文件没被排除(可通过go list -f '{{.GoFiles}}' ./...验证) - 某些集成测试调用
exec.Command启动新进程,主进程的覆盖率采集不会穿透到子进程,这部分逻辑天然不计入
CI 中稳定生成覆盖率并上传的注意事项
在 GitHub Actions 或 GitLab CI 里跑 go test -coverprofile,容易因并发测试、临时目录权限或模块缓存导致 cover.out 写失败或内容损坏。
- 固定用
-covermode=count,避免atomic模式在多 goroutine 下不准 - 加
-race会禁用覆盖率,二者不可共存;需要竞态检测就只能放弃覆盖率 - 上传前建议校验:
test -s cover.out(非空) +go tool cover -func=cover.out | grep "total:"(确认有 total 行) - 若用 codecov.io,它依赖
go tool cover -func的文本输出格式,务必用-covermode=count,否则覆盖率值会被识别为 0
覆盖率数字本身没意义,关键看红色块落在哪——是 error handling 被忽略?还是边界条件没测?go tool cover -func=cover.out 输出的函数级统计,比 HTML 更适合快速定位漏测函数。别只盯着 90% 这个数,先打开 coverage.html 点进去看那几个红色的 switch 分支再说。

















