1. 引言
Go提供了go test
命令来进行单元测试和性能测试。测试命令的格式如下,
go test [build/test flags] [packages] [build/test flags & test binary flags]
当我们使用go test的时候,测试文件需要满足一些规则:
- 文件名必须以
_test.go
结尾 - 必须引入测试包,即
import testing
下面我们简单介绍几个test flags
,如下表所示,
命令 | 意义 | 示例 |
---|---|---|
-bench regexp | 只执行匹配正则表达式的benchmark | -bench=. // 匹配所有 |
-count n | 执行n次unit test和benchmark,默认为1次 | -count=5 |
-cover | 开启覆盖率分析 | |
-run regexp | 只执行匹配正则表达式的测试 | |
-v | 长格式输出,输出完整的测试信息 | |
-cpuprofile cpu.out | 执行结束前生成cpu profile文件 | |
-timeout d | 执行时间超过d会panic,默认10min | |
-benchmem | 为benchmark开启内存分配分析 |
2. 单元测试
单元测试中测试函数的格式如下,
func TestXxx(t *testing.T)
另外,单元测试函数需满足以下规则:
- 测试用例函数必须是
Test
开头,TestXxx()
的参数是*testing.T
- Xxx部分可以为任意的字母数字的组合,但是首字母不能是小写字母(可以下划线)
- 测试函数中通过调用
testing.T
的Error
,Errorf
,FailNow
,Fatal
,Fatalf
方法,说明测试不通过,调用Log
方法用来记录测试的信息。
最后直接在测试文件所在包中执行下面命令,即可执行包中所有的测试例,
# $ go test -v #详细显示测试结果
# $ go test file.go file_test.go #测试文件file_test.go
$ go test # 测试包中所有测试例
下面我们从具体例子来进行单元测试,首先创建我们待测试的功能模块–提供除法的功能函数,
package gotest
import (
"errors"
)
func Division(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("除数不能为0")
}
return a / b, nil
}
再次,我们创建单元测试文件如下,
package gotest
import "testing"
func TestDivision1(t *testing.T) {
if i, e := Division(6, 2); i != 3 || e != nil {
t.Error("Division test fail")
} else {
t.Log("Division test success")
}
}
func TestDivision2(t *testing.T) {
t.Log("Division test success")
}
最后我们执行单元测试命令,
$ go test sample/gotest
ok sample/gotest 0.006s
$ go test sample/gotest -v
=== RUN TestDivision1
--- PASS: TestDivision1 (0.00s)
gotest_test.go:9: Division test success
=== RUN TestDivision2
--- PASS: TestDivision2 (0.00s)
gotest_test.go:14: Division test success
PASS
ok sample/gotest 0.008s
当我们更改单元测试函数如下时,
func TestDivision2(t *testing.T) {
t.Error("Division test fail")
}
执行结果如下,
$ go test sample/gotest
--- FAIL: TestDivision2 (0.00s)
gotest_test.go:14: Division test fail
FAIL
FAIL sample/gotest 0.007s
$ go test sample/gotest -v
=== RUN TestDivision1
--- PASS: TestDivision1 (0.00s)
gotest_test.go:9: Division test success
=== RUN TestDivision2
--- FAIL: TestDivision2 (0.00s)
gotest_test.go:14: Division test fail
FAIL
exit status 1
FAIL sample/gotest 0.007s
3. 性能测试
性能测试函数的格式如下,
func BenchmarkXxx(b *testing.B)
压力测试函数规则:
- 测试用例函数必须是
Benchmark
开头,BenchmarkXxx()
的参数是*testing.B
- Xxx可以是任意字母数字的组合,但是首字母不能是小写字母
- 压力测试用例中,需在循环体内使用
testing.B.N
,
#go test -run=regexp -bench=regexp -cpuprofile=profile -count n package
go test -run=benchmark_test.go -bench=BenchmarkDivision1 -count=5 -cpuprofile=cpuprofile.file sample/gotest
针对性能测试,如下例所示,
package gotest
import (
"testing"
)
func BenchmarkDivision1(b *testing.B) {
for i := 0; i < b.N; i++ {
Division(4, 5)
}
}
func BenchmarkDivision2(b *testing.B) {
b.StopTimer() //stop time
//do some init
b.StartTimer() //start time
for i := 0; i < b.N; i++ {
Division(4, 5)
}
}
执行结果如下,
$ go test -run=benchmark_test.go -bench=. sample/gotest
goos: darwin
goarch: amd64
pkg: sample/gotest
BenchmarkDivision1-4 2000000000 0.87 ns/op
BenchmarkDivision2-4 2000000000 0.88 ns/op
PASS
ok sample/gotest 3.699s
当我们使用-cpuprofile=xxx
,会生成性能分析文件,针对profile文件的分析请查看下篇pprof文章。