自己给自己的代码写测试
- 都是以
_test为后缀名的源代码文件,都是go test测试的一部分,不会被go build编译到最终的可执行文件中 *_test.go文件中有三种类型的函数,单元测试函数、基准测试函数和示例函数- 测试函数:前缀为Test,测试程序的一些逻辑行为是否可行
- 基准函数:函数名前缀为Benchmark ,测试函数的性能
- 示例函数:前缀为Example,提供示例文档
go test命令会遍历所有的*_test.go文件中符合上述命名规则的函数,生成一个临时的main包用于调用相应的测试函数,然后构建并运行、报告测试结果,最后清理临时文件测试函数
每个测试函数必须导入testing包
其中t用于报告测试失败和附加的日志信息func TestName(t *testing.T){// ...got := ...want := ...// 引用类不能直接比较,使用reflect.DeepEqual(want,got)// 错误 t.Errorf()}
go test -v 查看详细信息
测试组和子测试
测试组:在一个函数中写多个测试样例
type test []struct{input stringsep stringwant []string}test := test{{input: "a:b:c", sep:":", want []string{a,b,c}},{},{},{},}for _,tc := range tests {got := Split(tc.input, tc.sep)if !reflect.DeepEqual(got,tc.want){// error}}
但是当测试用例比较多,没法一眼看出具体哪个测试用例失败,可以使用子测试
type test []struct{input stringsep stringwant []string}test := map[string]test{"s1":{input: "a:b:c", sep:":", want []string{a,b,c}},"s2":{},"s3":{},"s4":{},}for _,tc := range tests {got := Split(tc.input, tc.sep)if !reflect.DeepEqual(got,tc.want){// error}}
然后如果某个子测试错了,可以使用go test -v -run=Split/simple指挥运行simple对应的子测试用例
测试覆盖率
测试至少被运行一次的代码占总代码的比例 使用go test -cover,可以看到代码被测试覆盖的百分比
go还提供了一个-coverprofile,可以将覆盖率的记录信息输出到文件中。go test cover -coverprofile=c.out 或 go test cover -html=c.out
性能基准测试
基准测试就是在一定的工作负载之下检测程序性能的一种方法,它必须要执行b.N次,这样测试才有对照性
func BenchmarkName(b *testing.B){for i:=0;i<b.N;i++{}}
执行 go test -bench=Split
会显示核数,执行次数以及 op每次操作执行时间
还可以添加-benchmem参数,可以显示每次操作的内核申请情况
性能比较函数
func benchmarkFib(b *testing.B,n int){}func BenchmarkFib1(b *testing.B) {benchmarkFib(b,1)}func BenchmarkFib2(b *testing.B) {benchmarkFib(b,2)}func BenchmarkFib3(b *testing.B) {benchmarkFib(b,3)}func BenchmarkFib10(b *testing.B) {benchmarkFib(b,10)}func BenchmarkFib100(b *testing.B) {benchmarkFib(b,100)}
运行 go test -bench=.
可以使用-benchtime标志增加最小基准时间,以产生更准确的结果
重置时间
可以使用b.ResetTimer(),之前的操作不做为测试报告操作
并行测试
func (b *B) RunParallel(body func(*PB)) 会以并行的方式执行给定的基准测试
性能优化
- CPU
- MEM(Heap)
- Block
- Goroutine
go pprof
