返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

12.1.1 子测试

发布于 2024-10-12 19:15:50 字数 2941 浏览 0 评论 0 收藏 0

将测试函数拆分为子测试,更符合套件(suite)模式。

  • 便于编写初始化(setup)和清理(teardown)逻辑。
  • 表驱动(table driven)时,拆分成多个并发测试。
  • 便于观察子测试时间,不用考虑外部环境影响。
func TestA(t *testing.T) {
	time.Sleep(time.Second)
}

func TestB(t *testing.T) {
	time.Sleep(time.Second)
}

func TestC(t *testing.T) {
	time.Sleep(time.Second)
}

func TestSuite(t *testing.T) {
	t.Log("setup")
	defer t.Log("teardown")

	t.Run("A", TestA)
	t.Run("B", TestB)
	t.Run("C", TestC)
}
$ go test -v -run "Suite"

=== RUN   TestSuite

    main_test.go:21: setup
    
=== RUN   TestSuite/A
=== RUN   TestSuite/B
=== RUN   TestSuite/C

=== CONT  TestSuite

    main_test.go:27: teardown
    
--- PASS: TestSuite (3.02s)
    --- PASS: TestSuite/A (1.01s)
    --- PASS: TestSuite/B (1.00s)
    --- PASS: TestSuite/C (1.00s)
    
PASS
ok  	test	3.028s
# 按名称单独执行子测试。

$ go test -v -run "Suite/[AB]"
$ go test -v -run "Suite/B"

支持子测试并行。

func TestSuite(t *testing.T) {
	tests := []int{1, 2}
    
    for v := range tests {
        
        // 避开闭包延迟。
        x := v
        
        t.Run("", func(t *testing.T) {
            t.Parallel()
            time.Sleep(time.Second * 5)
            println(x)
        })
    }
}

前文提过, Parallel 挂起当前测试,让 Run 提前退出。
上例中有 teardown 的话,会在子测试结束前执行。

func TestSuite(t *testing.T) {
	tests := []int{1, 2}

	defer t.Log("teardown")
    
    for v := range tests {
		x := v
        
		t.Run("", func(t *testing.T) {
			t.Parallel()
			time.Sleep(time.Second * 5)
			println(x)
		})
	}
}
$ go test -v -run "Suite"

=== RUN   TestSuite
=== RUN   TestSuite/#00
=== PAUSE TestSuite/#00
=== RUN   TestSuite/#01
=== PAUSE TestSuite/#01
=== CONT  TestSuite

main_test.go:31: teardown

=== CONT  TestSuite/#00
=== CONT  TestSuite/#01

1
0

--- PASS: TestSuite (0.00s)
--- PASS: TestSuite/#01 (5.01s)
--- PASS: TestSuite/#00 (5.01s)

PASS
ok  	test	5.014s

解决办法,就是在外面再套一个 Run 调用。

func TestSuite(t *testing.T) {
	tests := []int{1, 2}

    defer t.Log("teardown")
    
    // 不受影响。
    t.Run("group", func(t *testing.T) {
        for v := range tests {
            x := v
            
            // 因 Parallel 提前退出。
            t.Run("", func(t *testing.T) {
                t.Parallel()
                time.Sleep(time.Second * 5)
                println(x)
            })
        }
    })
}
$ go test -v -run "Suite"

=== RUN   TestSuite
=== RUN   TestSuite/group
=== RUN   TestSuite/group/#00
=== PAUSE TestSuite/group/#00
=== RUN   TestSuite/group/#01
=== PAUSE TestSuite/group/#01
=== CONT  TestSuite/group/#00
=== CONT  TestSuite/group/#01

0
1

=== CONT  TestSuite

    main_test.go:21: teardown
    
--- PASS: TestSuite (5.01s)
    --- PASS: TestSuite/group (0.01s)
        --- PASS: TestSuite/group/#00 (5.00s)
        --- PASS: TestSuite/group/#01 (5.00s)
        
PASS
ok  	test	5.019s

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文