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 命令执行结果为:
如果把want改为5,失败了:
使用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之后:
一组测试中,显然是有一个是错的
子测试
当我们的测试用例比较多时,我们就比较难确定是那一个出了问题,这时候子测试就是一个很好的解决方法:
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)
}
})
}
}
这时候就更多的测试内容了
另外我们还可以用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 命令执行基准测试,输出结果如下:
其中
BenchmarkSplit-8表示对singleNumber函数进行基准测试,数字8表示GOMAXPROCS的值,这个对于并发基准测试很重要。277438236和4.16ns/op表示每次调用singleNumber函数耗时4.16ns,这个结果是277438236次调用的平均值。
重置时间
b.ResetTime() 前面测试所花的时间清零,从零开始计时测试后面的代码