Go单元测试和基准测试
Go语言中自带有一个轻量级的测试框架testing
和自带的go test
命令来实现单元测试和性能测试
编写单元测试
go test
命令,会自动读取源码目录下面名为*_test.go
的文件,生成并运行测试用的可执行文件
go test
命令只能在一个相应的目录下执行所有文件,所以需要进行单元测试前,需要新建一个项目目录(此处举例为 gotest
)
division.go
: 编写需要被测试方法
// division.go文件: 里面包含一个实现的除法算法
package gotest
import (
"errors"
)
func Division(a,b float64)(float64, error){
if b == 0 {
return 0, errors.New("除数不能为零!")
}
return a/b, nil
}
// 本文代码例子来自: https://blog.csdn.net/shenlanzifa/article/details/51451814
division_test.go
编写单元测试文件
单元测试文件需要遵循以下原则:
- 文件名需要以
_test.go
结尾,这样go test
命令才能找到对应的单元测试文件 - 必须导入
testing
包 - 所有测试用例函数必须是
TestXxx
开头,遵循驼峰命名发,X处的字母必须大写 - 测试函数格式为
func TestXxx(t *testing.T){}
,类型testing.T
用来记录错误或者测试状态 - 函数中通过调用
testing.T
的Error
,Errorf
,FailNow
,Fatal
,FatalIf
方法,说明测试不通过,调用Log
方法用来记录测试的信息。 - 测试用例文件不会参与正常源码编译,不会被包含到可执行文件中
// division_test.go: 单元测试文件
package gotest
import(
"testing"
)
func TestDivision(t *testing.T){ // 参数为 *testing.T
if i,e := Division(6,2); i != 3 || e != nil {
t.Error("测试失败: 除法函数测试没有通过!") // 调用Error()表示不通过
}else{
t.Log("测试成功: 第一个测试成功!") // Log()打印日志
}
}
执行单元测试
# (1)执行: go test
PASS
ok gotest 0.005s
# (2)执行: go test -v
=== RUN TestDivision
--- PASS: TestDivision (0.00s)
test_test.go:12: 测试成功: 第一个测试成功!
PASS
ok gotest 0.004s
# (1)执行直接放回该目录下所有测试用例的成功与否
# (2)执行返回具体执行的那些测试函数及打印的日志
# go test -v -run=Division 执行指定的单元测试函数
编写基准测试
基准测试原则
- 文件名必须以
_test.go
结尾 - 压力测试函数格式
func BenchmarkXxx(b *testing.B){}
go test
不会默认执行压力测试的函数,如果要执行压力测试需要带上参数-testing.bench
,语法:-testing.bench="test_name_regex"
,例如go test -test.bench=".*"
表示测试全部的压力测试函数- 在压力测试用例中,请记得在循环体内使用
testing.B.N
,以使测试可以正常的运行
// division_test.go: x性能压力测试文件
package gotest
import(
"testing"
)
func BenchmarkDivision2(b *testing.B){
b.StopTimer()
// 做一些初始化的工作,例如读取文件数据,数据库连接之类的,
// 这样这些时间不影响我们测试函数本身的性能
b.StartTimer()
for i:=0; i < b.N; i++{ // b.N 由基准测试框架提供
Division(6,2)
}
}
执行基准测试
# go test -bench=Division
1: goos: darwin
2: goarch: amd64 # 前两行表示测试的系统环境
3: pkg: gotest # 测试的包
4: BenchmarkDivision-8 1000000000 0.263 ns/op
5: PASS
6: ok gotest 0.298s
以上第 4 行表示压力测试的函数名,执行次数,以及每次的执行时间,其中运行 10次,就是由压力测试代码中的b.N
提供, 其中为什么是这个次数由如下公式:
b.N * 每次运行时间 = 基准测试时间(默认1s,可由 -benchtime 参数修改,见下面)
-count=5
: 执行该压力测试做多少次-benchmem
: 是否在性能测试的时候输出内存情况(输出每次调用分配多少内存和每次调用分配几次)-benchtime=10s
: 性能测试运行的时间,默认是1s
[参考文章]: