Golang单元测试

Golang单元测试

[TOC]

一、约定的条件

  1. 包含单元测试的代码文件必须以_test.go结尾,否则测试框架并不会读区该文件作为测试代码。
  2. 单元测试文件名_test.go前面的部分建议是被测试的方法所在代码文件的文件名。
  3. 单元测试的函数名必须以Test开头,注意首字母是大写的。如果不满足则测试框架不会执行该函数。
  4. 函数名最好是Test+要测试的方法函数名,如TestAdd,表示测试的是Add这个这个函数。
  5. 测试函数的签名必须接收一个指向testing.Ttesting.B类型的指针,且无返回值。

二、简单的样例

测试文件:test/demo_test.go

代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package test

import (
"testing"
)

func Add(a, b int) int {
return a + b
}

func TestAdd(t *testing.T) {
if result := Add(1, 2); result != 3 {
t.Errorf("测试Add函数报错,参数分别是%v and %v,返回结果为%v,期望是%v", 1, 2, result, 4)
}
}

三、如果对测试函数的执行顺序有要求

将单个测试用例的首字母小写,这样这个用例就不会被测试框架调用了

我们将测试方法传递给t的Run()方法,从而实现指定顺序执行单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package test

import (
"testing"
)

func Add(a, b int) int {
return a + b
}

func testAdd1(t *testing.T) {
if result := Add(1, 2); result != 3 {
t.Errorf("测试Add函数报错,参数分别是%v and %v,返回结果为%v,期望是%v", 1, 2, result, 4)
}
}

func testAdd2(t *testing.T) {
if result := Add(3, 4); result != 7 {
t.Errorf("测试Add函数报错,参数分别是%v and %v,返回结果为%v,期望是%v", 1, 2, result, 4)
}
}

func TestAdd(t *testing.T) {
t.Run("test1", testAdd1)
t.Run("test2", testAdd2)
}

四、测试开始前的统一初始化等操作

如果我们需要在单元测试开始前进行统一的初始化操作,如:数据准备、连接数据库等,就需要用到*testing.M

在现有用例的基础上增加这个函数:

1
2
3
4
func TestMain(m *testing.M) {
fmt.Println("统一初始化...")
m.Run()
}

五、基准测试,测试性能–benchmark

  1. benchmark函数必须以Benchmark开头
  2. benchmark的测试case一般会跑b.N次,并且每次执行都是这样
  3. 实际执行时,会调整b.N的次数,直到执行时间达到稳态
  4. b.ResetTimer是重置计时器,这样可以避免for循环之前的初始化代码的干扰
  5. 被测试的代码要放到循环里
  6. b.N是基准测试框架提供的,表示循环的次数,因为需要反复调用测试的代码,才可以评估性能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package test

import (
"fmt"
"testing"
)

func Print() {
fmt.Println("hello")
}

func BenchmarkPrint(b *testing.B) {
for i := 0; i < b.N; i++ {
Print()
}
}
1
2
3
# 以这样的方式进行执行
# .表示运行所有的基准测试
go test -bench=.