Appearance
Go 表驱动测试
当测试逻辑是重复的时候,通过 subtests 使用 table 驱动的方式编写 case 代码看上去会更简洁。
| Bad | Good |
|---|---|
Go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | Go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
很明显,使用 test table 的方式在代码逻辑扩展的时候,比如新增 test case,都会显得更加的清晰。
我们遵循这样的约定:将结构体切片称为 tests。每个测试用例称为 tt。此外,我们鼓励使用 give 和 want 前缀说明每个测试用例的输入和输出值。
Go
tests := []struct{
give string
wantHost string
wantPort string
}{
// ...
}
for _, tt := range tests {
// ...
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
并行测试,比如一些专门的循环(例如,生成 goroutine 或捕获引用作为循环体的一部分的那些循环)。必须注意在循环的范围内显式地分配循环变量,以确保它们保持预期的值。
Go
tests := []struct{
give string
// ...
}{
// ...
}
for _, tt := range tests {
tt := tt // for t.Parallel
t.Run(tt.give, func(t *testing.T) {
t.Parallel()
// ...
})
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
在上面的例子中,由于下面使用了 t.Parallel(),我们必须声明一个作用域为循环迭代的 tt 变量。如果我们不这样做,大多数或所有测试都会收到一个意外的 tt 值,或者一个在运行时发生变化的值。