Go单元测试

161 阅读2分钟

go test

使用go test按照其规定进行测试就行了

规定: 以 _test.go 为后缀,其不会被go build编译到可执行文件中;有三种类型函数:单元测试函数,基准测试函数和示例函数

测试函数

格式:

func TestName(t *testing.T){
    // ...
}

函数名都以Test开头,其中t用于报告测试失败和附加的日志信息。如比较常用的有:

t.Fail,t.Error,t.Errorf等等

示例

一个返回数组中只出现一次的数字的函数

func singleNumber(nums []int) int {
   var target int
   for _, v := range nums {
      target ^= v
   }
   return target
}

在其同级目录(目录名最好为英文)下,我们可以创建singleNumber_test.go来进行编写测试函数:

    func TestSingleNumber(t *testing.T) { // Test开头
   got := singleNumber([]int{4, 1, 2, 1, 2}) // 测试用例得到结果
   want := 4 // 想要的结果
   if got != want { 对比结果
      t.Errorf("want:%v,got:%v", want, got)
   }
}

在当前路径下使用go test 命令执行结果为:

image.png

如果把want改为5,失败了:

image.png

使用go test -v 可以显示更多信息

测试组

一条一条测试也许会太麻烦了,这里我们就可以用一组进行测试

func TestSingleNumber1(t *testing.T) {
   type test struct {
      input []int
      want  int
   }
   tests := []test{
      {input: []int{4, 1, 2, 1, 2}, want: 4},
      {input: []int{5, 7, 5, 7, 2}, want: 2},
      {input: []int{4, 1, 4, 1, 2}, want: 3},
      {input: []int{3, 1, 2, 3, 2}, want: 1},
   }
   for _, tc := range tests {
      got := singleNumber(tc.input)
      if got != tc.want {
         t.Errorf("want:%v,got:%v", tc.want, got)
      }
   }
}

执行go test -v之后:

image.png 一组测试中,显然是有一个是错的

子测试

当我们的测试用例比较多时,我们就比较难确定是那一个出了问题,这时候子测试就是一个很好的解决方法:

func TestSingleNumber2(t *testing.T) {
   type test struct {
      input []int
      want  int
   }
   tests := map[string]test{
      "1": {input: []int{4, 1, 2, 1, 2}, want: 4},
      "2": {input: []int{5, 7, 5, 7, 2}, want: 2},
      "3": {input: []int{4, 1, 4, 1, 2}, want: 3},
      "4": {input: []int{3, 1, 2, 3, 2}, want: 1},
   }
   for name, tc := range tests {
      t.Run(name, func(t *testing.T) {
         got := singleNumber(tc.input)
         if got != tc.want {
            t.Errorf("name:%s want:%v,got:%v", name, tc.want, got)
         }
      })
   }
}

这时候就更多的测试内容了

image.png 另外我们还可以用go test -cover来查看测试覆盖率

基准测试

格式:

func BenchmarkName(b *testing.B){
    // ...
}

示例

func BenchmarkSingleNumber(b *testing.B) {
   for i := 0; i < b.N; i++ {
      singleNumber([]int{4, 1, 2, 1, 2})
   }
}

基准测试并不会默认执行,需要增加 -bench 参数,所以我们通过执行 go test -bench=SingleNumber 命令执行基准测试,输出结果如下:

image.png 其中BenchmarkSplit-8表示对singleNumber函数进行基准测试,数字8表示GOMAXPROCS的值,这个对于并发基准测试很重要。2774382364.16ns/op表示每次调用singleNumber函数耗时4.16ns,这个结果是277438236次调用的平均值。

重置时间

b.ResetTime() 前面测试所花的时间清零,从零开始计时测试后面的代码