Go提供了go test来执行测试,这个命令会在当前package中寻找符合*_test.go的文件,并在文件中寻找符合TestXxx(*testing.T) {}BenchmarkXxx(b *testing.B){}ExampleXxxx(){}函数执行测试,如果想要执行当前package中的所有测试,可以执行go test ./... ,这个命令会搜索当前目录以及子目录中的所有符合条件的测试文件,详细测试规则看go help testfunc

Go测试是并行还是串行

默认情况下go test 在不同的package之间是并行执行测试,在每个package内部是串行执行测试。如果想要在 package 内部开启并行测试,需要在测试函数中显式执行 t.Parallel() 告诉 go test 这个函数可以与其他测试并行执行,一旦开启并行测试,一定要确保测试函数之间的资源竞争的问题已经得到正确的解决,否则可能会有意想不到的问题。

Go提供了可以限制 package 之间并行测试的命令:

  1. go test -parallel 1 -p 1

-parallel 1 表示允许同时执行并行测试的函数数目是 1,默认是 GOMAXPROCS,-p 1 表示允许并行测试的 test binary 同时只有一个,默认是 CPU的核数。Go 执行测试的时候是把每个 package 都 build 成 binary 之后再去执行,这个数目就是设置在被 go test 同时执行的 package 的 binary 有几个。

还有一种可以让多个 package 并行测试的办法是测试的时候指定多个 package:

  1. go test p1 p2 p3

通过这种方式执行测试时,三个包是并行执行的。
所以如果想要让你的测试执行速度加快,其中一种办法就是把测试放到不同的 package 中,如果某个 package 中测试文件很多,可以把这些文件单独成包:

  1. graphql/test
  2. ├── mutation
  3. └── mutation_test.go
  4. └── query
  5. └── query_test.go

如果你的并行测试依赖于 database 这样的外部系统,确保你使用的 database 在每个 test package 之间是相互独立的,比如上述 mutation_test.go 和 query_test.go 使用了相同的表结构的不同数据库。

Go test flags

上面限制 Go 并行测试的其实都是 Go 提供的 test flag,详细见 https://golang.org/cmd/go/#hdr-Testing_flags , 其中有几个对日常测试很重要的 flag 这里单独来讲讲。

-v

表示输出测试的详细信息,有助于本地开发调试,对应的代码 testing.Verbose()

-short

表示只想执行运行时间比较短的测试,这个 flag 一般会结合 testing.Skip() ,可以让开发这选择跳过执行时间较长的测试:

  1. func TestCountMallocs(t *testing.T) {
  2. if testing.Short() {
  3. t.Skip("skipping malloc count in short mode")
  4. }
  5. // rest of test...
  6. }

-timeout

指定测试执行的超时时间,如果测试时间很长,可以通过这个 flag 强制测试停止

-run

指定想要执行的测试函数名称,通过正则匹配要执行的测试函数名称

-parallel

指定在同一个package 内并行执行的测试函数数目,默认是 GOMAXPROCS

-p

指定同时执行 build 和 test 的包的数目,默认是 CPU 核数,可以指定 -p 1 限制对包的测试一个一个串行执行。

-cpu

指定需要在哪些CPU上执行测试 go test -cpu=1,2,4 ,默认情况下测试都只会在一个 CPU 上执行,如果想要在多个 CPU 上都执行一遍测试,可以通过环境变量指定 GOMAXPROCS ,GOMAXPROCS=2 go test 表示在 2 个 CPU 上执行测试,也就是测试会执行 2 次。

-args

指定测试的命令参数,一般这个 flag 放在 go test 命令的最后

使用不同测试包名打破引用循环

正常开发中如果a引用了b包,b引用了a包,然后在测试b的单元单测会出现循环引用问题。这个官方的代码中已经有了解决方法,是把b的单元测试包改为 b_test,这样就完美的解决了这个问题。当然b_test不能被其他包引用,部分版本出现过包找不到的空指针问题,因为b_test和包的文件名不一致。暂时我还没有碰到这个问题,后续遇到再来贴具体的示例

参考

https://sanyuesha.com/2019/08/21/go-test/
https://deepzz.com/post/the-command-flag-of-go-test.html
https://splice.com/blog/lesser-known-features-go-test/

待阅读补充

https://studygolang.com/articles/21220 测试框架的使用