GoLang 测试
单元测试
go test
使用该命令执行所有的测试go test -v
我们可以为go test命令添加-v参数,查看测试函数名称和运行时间go test -v -run="函数名"
还可以在go test命令后添加-run参数,它对应一个正则表达式,只有函数名匹配上的测试函数才会被go test命令执行
func TestSplit01(t *testing.T) {
target := []string{"xxx", "yyy"} //假的测试用例,假设为正确结果
curr := splitString("这是zzs和ywj", "和")
if !reflect.DeepEqual(target, curr) {
t.Error("比较失败了")
}
}
func TestSplit02(t *testing.T) {
target := []string{"这是zzs", "ywj"}
curr := splitString("这是zzs和ywj", "和")
if !reflect.DeepEqual(target, curr) {
t.Error("测试失败了!")
}
}
测试组和子测试
我们都知道可以通过-run=RegExp来指定运行的测试用例,还可以通过/来指定要运行的子测试用例,例如:go test -v -run=Split/simple只会运行simple对应的子测试用例
func TestSplit(t *testing.T) {
type test struct {
input string
sep string
want []string
}
tests := map[string]test{
"test1": {"这是zzs和ywj", "和", []string{"这是zzs", "ywj"}},
"test2": {"这是wy和pnb", "和", []string{"这是wy", "lzq"}}, //故意写错来测试
"test3": {"xxxoryyy", "or", []string{"xxx", "yyy"}},
}
for name, ts := range tests {
t.Run(name, func(t *testing.T) {
arr := splitString(ts.input, ts.sep)
if !reflect.DeepEqual(arr, ts.want) {
t.Error("发生错误,不匹配")
}
})
}
}
基准测试
1.基准测试事例
基准测试以Benchmark为前缀,需要一个*testing.B类型的参数b,基准测试必须要执行b.N次,这样的测试才有对照性,b.N的值是系统根据实际情况去调整的,从而保证测试的稳定性
- 基准测试并不会默认执行,需要增加-bench参数,所以我们通过执行
go test -bench=“名称”
命令执行基准测试,输出结果如下: - 我们还可以为基准测试添加-benchmem参数,来获得内存分配的统计数据
go test -bench=“名称” -benchmem
func BenchmarkSplit(b *testing.B) {
for i := 0; i < b.N; i++ {
splitString("这是zzs和ywj", "和")
}
}
2.性能比较函数
上面的基准测试只能得到给定操作的绝对耗时,但是在很多性能问题是发生在两个不同操作之间的相对耗时,比如同一个函数处理1000个元素的耗时与处理1万甚至100万个元素的耗时的差别是多少?再或者对于同一个任务究竟使用哪种算法性能最佳?我们通常需要对两个不同算法的实现使用相同的输入来进行基准比较测试。
go test -bench="." -benchmem
这个是运行全部的性能测试案例
func benchmarkFib(b *testing.B, n int) {
for i := 0; i < b.N; i++ {
Fib(n)
}
}
func BenchmarkFib1(b *testing.B) {
benchmarkFib(b, 1)
}
func BenchmarkFib10(b *testing.B) {
benchmarkFib(b, 10)
}
func BenchmarkFib40(b *testing.B) {
benchmarkFib(b, 40)
}
最终的结果只运行了两次,每次运行的平均值只有不到一秒。像这种情况下我们应该可以使用-benchtime标志增加最小基准时间,以产生更准确的结果
go test -bench="函数名" -benchtime=20s
3.重置时间
b.ResetTimer之前的处理不会放到执行时间里,也不会输出到报告中,所以可以在之前做一些不计划作为测试报告的操作。
func BenchmarkFib1(b *testing.B) {
time.Sleep(time.Second * 5) //假设需要做一些耗时的无关操作
b.ResetTimer() // 重置计时器
benchmarkFib(b, 1)
}
4.并行测试
func (b *B) RunParallel(body func(*PB))会以并行的方式执行给定的基准测试。
RunParallel会创建出多个goroutine,并将b.N分配给这些goroutine执行, 其中goroutine数量的默认值为GOMAXPROCS。用户如果想要增加非CPU受限(non-CPU-bound)基准测试的并行性, 那么可以在RunParallel之前调用SetParallelism 。RunParallel通常会与-cpu标志一同使用。
func BenchmarkSplitParallel(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
Fib(40)
}
})
}
- 还可以通过在测试命令后添加-cpu参数如
go test -bench="." -cpu 1
来指定使用的CPU数量