@@ -16,7 +16,7 @@ Go语言中自带有一个轻量级的测试框架`testing`和自带的`go test`
16
16
"errors"
17
17
)
18
18
19
- func intdiv (a, b float64) (float64, error) {
19
+ func Division (a, b float64) (float64, error) {
20
20
if b == 0 {
21
21
return 0, errors.New("除数不能为0")
22
22
}
@@ -32,13 +32,117 @@ Go语言中自带有一个轻量级的测试框架`testing`和自带的`go test`
32
32
- 所有的测试用例函数必须是`Test`开头
33
33
- 测试用例会按照源代码中写的顺序依次执行
34
34
- 测试函数`TestXxx()`的参数是`testing.T`,我们可以使用该类型来记录错误或者是测试状态
35
- - 测试格式:`func TestXxx (t *testing.T)`,`Xxx`部分可以为任意的字符串组合,但是首字母不能是小写字母[a-z],例如`Testintdiv`是错误的函数名。
36
- - `testing.T`
35
+ - 测试格式:`func TestXxx (t *testing.T)`,`Xxx`部分可以为任意的字母数字的组合,但是首字母不能是小写字母[a-z],例如`Testintdiv`是错误的函数名。
36
+ - 函数中通过调用`testing.T`的`Error`, `Errorf`, `FailNow`, `Fatal`, `FatalIf`方法,说明测试不通过,调用`Log`方法用来记录测试的信息。
37
+
38
+ 下面是我们的测试用例的代码:
39
+
40
+ package gotest
41
+
42
+ import (
43
+ "testing"
44
+ )
45
+
46
+ func Test_Division_1(t *testing.T) {
47
+ if i, e := Division(6, 2); i != 3 || e != nil { //try a unit test on function
48
+ t.Error("除法函数测试没通过") // 如果不是如预期的那么就报错
49
+ } else {
50
+ t.Log("第一个测试通过了") //记录一些你期望记录的信息
51
+ }
52
+ }
53
+
54
+ func Test_Division_2(t *testing.T) {
55
+ t.Error("就是不通过")
56
+ }
57
+
58
+ 我们在项目目录下面执行`go test`,就会显示如下信息:
59
+
60
+ --- FAIL: Test_Division_2 (0.00 seconds)
61
+ gotest_test.go:16: 就是不通过
62
+ FAIL
63
+ exit status 1
64
+ FAIL gotest 0.013s
65
+ 从这个结果显示测试没有通过,因为在第二个测试函数中我们写死了测试不通过的代码`t.Error`,那么我们的第一个函数执行的情况怎么样呢?默认情况下执行`go test`是不会显示测试通过的信息的,我们需要带上参数`go test -v`,这样就会显示如下信息:
66
+
67
+ === RUN Test_Division_1
68
+ --- PASS: Test_Division_1 (0.00 seconds)
69
+ gotest_test.go:11: 第一个测试通过了
70
+ === RUN Test_Division_2
71
+ --- FAIL: Test_Division_2 (0.00 seconds)
72
+ gotest_test.go:16: 就是不通过
73
+ FAIL
74
+ exit status 1
75
+ FAIL gotest 0.012s
76
+ 上面的输出详细的展示了这个测试的过程,我们看到测试函数1`Test_Division_1`测试通过,而测试函数2`Test_Division_2`测试失败了,最后得出结论测试不通过。接下来我们把测试函数2修改成如下代码:
77
+
78
+ func Test_Division_2(t *testing.T) {
79
+ if _, e := Division(6, 0); e == nil { //try a unit test on function
80
+ t.Error("Division did not work as expected.") // 如果不是如预期的那么就报错
81
+ } else {
82
+ t.Log("one test passed.", e) //记录一些你期望记录的信息
83
+ }
84
+ }
85
+ 然后我们执行`go test -v`,就显示如下信息,测试通过了:
86
+
87
+ === RUN Test_Division_1
88
+ --- PASS: Test_Division_1 (0.00 seconds)
89
+ gotest_test.go:11: 第一个测试通过了
90
+ === RUN Test_Division_2
91
+ --- PASS: Test_Division_2 (0.00 seconds)
92
+ gotest_test.go:20: one test passed. 除数不能为0
93
+ PASS
94
+ ok gotest 0.013s
37
95
96
+ ## 如何编写压力测试
97
+ 压力测试是用来检测我们写的函数是否有足够好的性能,和写单元功能测试类似,需要注意以下几点:
98
+
99
+ - 压力测试函数必须如下格式,其中` XXX ` 可以是任意字母数字的组合,但是首字母不能是小写字母
38
100
39
- ## 如何编写压力测试
101
+ func BenchmarkXXX(b *testing.B) { ... }
102
+
103
+ - ` go test ` 不会默认执行压力测试的函数,如果要执行压力测试需要带上参数` -test.bench ` ,语法:` -test.bench="test_name_regex" ` ,例如` go test -test.bench=".*" ` 表示测试全部的压力测试函数
104
+ - 压力测试函数中记得在循环中使用` testing.B.N ` 从而使得压力测试可以正常的运行
105
+ - 文件名也必须以` _test.go ` 结尾
106
+
107
+ 下面我们新建一个压力测试文件webbench_test.go,代码如下所示:
108
+
109
+ package gotest
110
+
111
+ import (
112
+ "testing"
113
+ )
114
+
115
+ func Benchmark_Division(b *testing.B) {
116
+ for i := 0; i < b.N; i++ { //use b.N for looping
117
+ Division(4, 5)
118
+ }
119
+ }
120
+
121
+ func Benchmark_TimeConsumingFunction(b *testing.B) {
122
+ b.StopTimer() //调用该函数停止压力测试的时间计数
123
+
124
+ //做一些初始化的工作,例如读取文件数据,数据库连接之类的,
125
+ //这样这些时间不影响我们测试函数本身的性能
126
+
127
+ b.StartTimer() //重新开始时间
128
+ for i := 0; i < b.N; i++ {
129
+ Division(4, 5)
130
+ }
131
+ }
132
+
133
+
134
+ 我们执行命令` go test -file webbench_test.go -test.bench=".*" ` ,可以看到如下结果:
135
+
136
+ PASS
137
+ Benchmark_Division 500000000 7.76 ns/op
138
+ Benchmark_TimeConsumingFunction 500000000 7.80 ns/op
139
+ ok gotest 9.364s
140
+
141
+ 上面的结果显示我们没有执行任何` TestXXX ` 的单元测试函数,显示的结果只执行了压力测试函数,第一条显示了` Benchmark_Division ` 执行了500000000次,每次的执行平均时间是7.76纳秒,第二条显示了` Benchmark_TimeConsumingFunction ` 执行了500000000,每次的平均执行时间是7.80纳秒。最后一条显示总过的执行时间。
142
+
143
+ ## 小结
144
+ 通过上面对单元测试和压力测试的编写,我们知道Go语言里面的` testing ` 包虽然轻量,但是编写测试用例和压力测试非常简单,而且使用内置的命令` go test ` 就可以非常方便的执行这些单元测试和压力测试,这样我们每次修改完函数执行一下单元测试和压力测试,可以简单的做回归测试。
40
145
41
- func BenchmarkXXX(b *testing.B) { ... }
42
146
43
147
## links
44
148
* [ 目录] ( < preface.md > )
0 commit comments