自己给自己的代码写测试

  • 都是以_test为后缀名的源代码文件,都是go test测试的一部分,不会被go build编译到最终的可执行文件中
  • *_test.go文件中有三种类型的函数,单元测试函数、基准测试函数和示例函数
    • 测试函数:前缀为Test,测试程序的一些逻辑行为是否可行
    • 基准函数:函数名前缀为Benchmark ,测试函数的性能
    • 示例函数:前缀为Example,提供示例文档
  • go test命令会遍历所有的*_test.go文件中符合上述命名规则的函数,生成一个临时的main包用于调用相应的测试函数,然后构建并运行、报告测试结果,最后清理临时文件

    测试函数

    每个测试函数必须导入testing包
    1. func TestName(t *testing.T){
    2. // ...
    3. got := ...
    4. want := ...
    5. // 引用类不能直接比较,使用reflect.DeepEqual(want,got)
    6. // 错误 t.Errorf()
    7. }
    其中t用于报告测试失败和附加的日志信息

go test -v 查看详细信息

测试组和子测试

测试组:在一个函数中写多个测试样例

  1. type test []struct{
  2. input string
  3. sep string
  4. want []string
  5. }
  6. test := test{
  7. {input: "a:b:c", sep:":", want []string{a,b,c}},
  8. {},
  9. {},
  10. {},
  11. }
  12. for _,tc := range tests {
  13. got := Split(tc.input, tc.sep)
  14. if !reflect.DeepEqual(got,tc.want){
  15. // error
  16. }
  17. }

但是当测试用例比较多,没法一眼看出具体哪个测试用例失败,可以使用子测试

  1. type test []struct{
  2. input string
  3. sep string
  4. want []string
  5. }
  6. test := map[string]test{
  7. "s1":{input: "a:b:c", sep:":", want []string{a,b,c}},
  8. "s2":{},
  9. "s3":{},
  10. "s4":{},
  11. }
  12. for _,tc := range tests {
  13. got := Split(tc.input, tc.sep)
  14. if !reflect.DeepEqual(got,tc.want){
  15. // error
  16. }
  17. }

然后如果某个子测试错了,可以使用go test -v -run=Split/simple指挥运行simple对应的子测试用例

测试覆盖率

测试至少被运行一次的代码占总代码的比例 使用go test -cover,可以看到代码被测试覆盖的百分比

go还提供了一个-coverprofile,可以将覆盖率的记录信息输出到文件中。go test cover -coverprofile=c.outgo test cover -html=c.out

性能基准测试

基准测试就是在一定的工作负载之下检测程序性能的一种方法,它必须要执行b.N次,这样测试才有对照性

  1. func BenchmarkName(b *testing.B){
  2. for i:=0;i<b.N;i++{
  3. }
  4. }

执行 go test -bench=Split
会显示核数,执行次数以及 op每次操作执行时间

还可以添加-benchmem参数,可以显示每次操作的内核申请情况

性能比较函数

  1. func benchmarkFib(b *testing.B,n int){
  2. }
  3. func BenchmarkFib1(b *testing.B) {benchmarkFib(b,1)}
  4. func BenchmarkFib2(b *testing.B) {benchmarkFib(b,2)}
  5. func BenchmarkFib3(b *testing.B) {benchmarkFib(b,3)}
  6. func BenchmarkFib10(b *testing.B) {benchmarkFib(b,10)}
  7. 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