这是我参与「第五届青训营 」伴学笔记创作活动的第 13 天。
本文以 CC-BY-SA 4.0 发布。
Go 与测试
越来越多的语言对单元测试提供了内置的支持,
包括 Rust 的 #[test] 或是 Go 的 func TestXxx(t *testing.T)。
go test 测试流程
Go test 根据文件名来识别测试代码。
运行测试时,文件名以 _test.go 结尾的文件会被看作是测试文件
(文件名以 _ 或是以 . 开头的文件会被忽略),
一个包里的所有 *_test.go 文件会被编译成为一个单独的可执行文件。
测试文件里可以有不同种类的函数,对应不同种类的测试:
func TestXxx(t *testing.T): 函数名以Test开头,会被看作单元测试测例。func BenchmarkXxx(b *testing.B): 基本同上,会被看作性能测试测例。func FuzzXxx(f *testing.F): Fuzzing, 大体是随机生成一大堆数据来找 bug 的一个手段。func ExamplePrintln(): 通过标准输出来进行测试结果判断的测试,会被 godoc 整合至文档里。
还有一个特殊的函数:
func TestMain(m *testing.M): 在测试的主 goroutine 上运行的代码(每个包可以有最多一个), 可以用来进行各种初始化,例如打开一个基于内存的 Sqlite 然后进行迁移。
go test 的执行有两种模式:
-
当前目录模式:
go test: 运行当前目录里的测试,测试结果不会缓存起来。 -
包列表模式:
go test 包1 包2 ...: 运行指定包的测试,测试结果会进行缓存 (代码不发生变动的话,测试会直接报之前的结果,不会重新运行)。我们可以使用
./...来让 Go test 递归测试所有子目录里的包。
Go 1.18 引入了 workspace,但是测试似乎还不能直接在 workspace 根目录下运行:
go test ./... 无效。
有一个相关的 issue,
可能之后 go test 或是 go mod tidy 会更轻松一些。
Coverage
Coverage 就是测试的覆盖率。 一个 issue 总结了目前 Go 对 coverage 的支持:
go test -coverprofile=<filename> [package target(s)]: 测试对应的包,并把 coverage 结果输出到指定的<filename>文件。go tool cover -html=<covdatafile>: 查看对应的文件。
但是,例如在微服务下,我们有可能想要得到集成测试下的覆盖率结果, 但 Go 目前对此的支持并不乐观。 目前我们大概只能用七牛推出的 goc 来比较方便地得到这方面的 coverage 结果。