Golang testing
概述
func TestXxx(*testing.T)
测试函数的名字,Test要以大写开始。
测试的文件名是 xxx_test.go, “_test.go”结尾,文件内是TestXxx的函数。文件放在被测试模块同一目录。
具体错误可以用testing.T的Errorf来输出。
Benchmarks
func BenchmarkXxx(*testing.B)
go test -bench 将会依序运行benchmarks的用例。example:
func BenchmarkRandInt(b *testing.B) {
for i := 0; i < b.N; i++ {
rand.Int()
}
}
b.N是动态改变的,直到运行次数足够多,能可靠计算每次耗时为止。会有如下输出:
BenchmarkRandInt-8 68453040 17.8 ns/op
如果benchmark需要平行测试性能,可以使用RunParallel函数,一般会go test -cpu flag一起用。
func BenchmarkTemplateParallel(b *testing.B) {
templ := template.Must(template.New("test").Parse("Hello, !"))
b.RunParallel(func(pb *testing.PB) {
var buf bytes.Buffer
for pb.Next() {
buf.Reset()
templ.Execute(&buf, "World")
}
})
}
Examples
func ExampleHello() {
fmt.Println("hello")
// Output: hello
}
func ExampleSalutations() {
fmt.Println("hello, and")
fmt.Println("goodbye")
// Output:
// hello, and
// goodbye
}
Output那个注释是期待输出,对比结果时,会忽然前导和尾随空白。不按顺序时用Unordered output。
func ExamplePerm() {
for _, value := range Perm(5) {
fmt.Println(value)
}
// Unordered output: 4
// 2
// 1
// 3
// 0
}
Example中如果没有output的注释则只编译,不运行。
下面的suffix需要小写开头
func Example_suffix() { ... }
func ExampleF_suffix() { ... }
func ExampleT_suffix() { ... }
func ExampleT_M_suffix() { ... }
Skipping
路过。。
func TestTimeConsuming(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
...
}
Subtests and Sub-benchmarks
T和B类型中的Run可以定义子测试和子benchmarks,不需要为sub们定义函数。This enables uses like table-driven benchmarks and creating hierarchical tests. It also provides a way to share common setup and tear-down code:(这个可以使用表驱动benchmark和层级式测试,也能提供公共setup和tear-down代码)
func TestFoo(t *testing.T) {
// <setup code>
t.Run("A=1", func(t *testing.T) { ... })
t.Run("A=2", func(t *testing.T) { ... })
t.Run("B=1", func(t *testing.T) { ... })
// <tear-down code>
}
运行测试时,可以-run和-bench flags设置运行那些测试:
go test -run '' # 运行所有测试
go test -run Foo # 运行一级测试,匹配 "Foo", 例如 "TestFooBar".
go test -run Foo/A= # 运行一级测试,匹配 "Foo", 运行二级测试,匹配 "A=".
go test -run /A=1 # 运行所有一级测试, 运行二级测试,匹配 "A=1".
子用例可以并行运行,父级仅在所有子用例运行完才完成。
func TestGroupedParallel(t *testing.T) {
for _, tc := range tests {
tc := tc // capture range variable
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
...
})
}
}
子测试间是并行的运行。
Main
有时需要在测试前或测试后有一些设置或tear-down的控制,或者控制那些代码需要在主线程运程,可以在一个文件内添加一个
func TestMain(m *testing.M)
有用的命令
运行所有当前目录和子目录的tests。
go test ./...