golang 标准库 testing 包为 Go 代码支持了自动化测试。使用 go test 命令来执行。

介绍

函数测试定义:

  1. func TestXxx(*testing.T)

这个 TestXxx 函数式放在一个文件尾部名 _test.go 中。

一个简单的测试:

  1. func TestAbs(t *testing.T) {
  2. got := Abs(-1)
  3. if got != 1 {
  4. t.Errorf("Abs(-1) = %d; want 1", got)
  5. }
  6. }

Benchmarks

函数定义:

  1. func BenchmarkXxx(*testing.B)

测试基准通过 go test -bench 来执行。

-cover 命令行参数,显示覆盖率信息
一个简单的基准测试:

  1. func BenchmarkHello(b *testing.B) {
  2. for i := 0; i < b.N; i++ {
  3. fmt.Sprintf("hello")
  4. }
  5. }
  6. BenchmarkHello 10000000 282 ns/op

基准函数通过执行 b.N 次。例如上面 10000000 次每个执行时间在 282 ns。

Subtests and Sub-benchmarks(子测试与子基准)

这种子测试可以实现表驱动基准测试和创建分层测试。也可以提供通用的 setup 和 teardown 方法。

  1. func TestFoo(t *testing.T) {
  2. // <setup code>
  3. t.Run("A=1", func(t *testing.T) { ... })
  4. t.Run("A=2", func(t *testing.T) { ... })
  5. t.Run("B=1", func(t *testing.T) { ... })
  6. // <tear-down code>
  7. }

Main

有时测试必须为测试代码添加额外的 setup 和 teardown 在测试之前和之后。也有时必须控制那些代码在主线程执行,去支持其他情况。代码定义:

  1. func TestMain(m *testing.M)

当执行测试时会调用 TestMain,而不是直接运行测试。这时可以在 m.Run 的前后调用 setup 和 teardown 方法。

  1. func TestMain(m *testing.M) {
  2. // call flag.Parse() here if TestMain uses flags
  3. // setup
  4. code := m.Run()
  5. // teardown
  6. os.Exit(code)
  7. }

常用的测试方法

  • Error(args …interface{}) 输出测试错误信息。
  • Log(args …interface{}) 输出测试日志信息。
  • Parallel() 并发测试。
  • Fatal(args …interface{}) 致命错误信息。
  • Skip(args …interface{}) 跳过这个测试错误。

testdata
testdata 测试文件夹下可以存放一些测试需要用到的测试数据、静态文件。

表驱动测试(Table-driven test)

表测试是通过构建数据表来运行测试的一种方法。可以结合 subtest 来覆盖各种测试情况。

  1. func TestOrderSrv_OrderSendToPay(t *testing.T) {
  2. room := Room{}
  3. db.First(&room)
  4. order := test_createOrder(t, room)
  5. type args struct {
  6. order *models.Order
  7. }
  8. tests := []struct {
  9. name string
  10. args args
  11. wantErr bool
  12. }{
  13. {
  14. name: "提交订单",
  15. args: args{
  16. order: order,
  17. },
  18. wantErr: false,
  19. },
  20. }
  21. for _, tt := range tests {
  22. t.Run(tt.name, func(t *testing.T) {
  23. s := &OrderSrv{}
  24. if err := s.OrderSendToPay(tt.args.order); (err != nil) != tt.wantErr {
  25. t.Errorf("OrderSrv.OrderSendToPay() error = %v, wantErr %v", err, tt.wantErr)
  26. }
  27. })
  28. }
  29. }

建议使用 vscode 或 golandIDE 的 Go 插件支持生成测试用例模板。