14.单元测试
go test工具
go语言中的测试依赖go test [-v]命令。所有以_test.go为后缀的源码文件都是go test测试的一部分,不会被go build编译到最终的可执行文件中。
| 类型 | 格式 | 作用 |
|---|---|---|
| 测试函数 | 函数名前缀为Test | 测试程序的一些逻辑行为是否正确 |
| 基准函数 | 函数名前缀为Benchmark | 测试函数的性能 |
| 示例函数 | 函数名前缀为Example | 为文档提供示例文档 |
go test命令会遍历所有的*_test.go文件符合上述命名规则的函数,然后生成一个临时的main包用于调用相应的测试函数,然后构建并运行、报告测试结果,最后清理测试中生成的零食文件
测试函数
每个测试函数必须导入testing包,测试函数的基本格式如下:
func TestName(t *testing.T){
...
}
// 必须以Test开头,例:
func TestAdd(t *testing.T){}
func TestSum(t *testing.T){}
func TestLog(t *testing.T){}
测试函数实例
// 功能函数 split.go
package main
import "strings"
// Split 将s按照sep进行分割,返回一个字符串切片
func Split(s, sep string) (ret []string) {
idx := strings.Index(s, sep)
for idx > -1 {
ret = append(ret, s[:idx])
s = s[idx+len(sep):]
idx = strings.Index(s, sep)
}
ret = append(ret, s)
return
}
// 测试函数 test_split.go
package main
import (
"reflect"
"testing"
)
func TestSplit(t *testing.T) {
got := Split("abc", "b")
want := []string{"a", "c"}
if !reflect.DeepEqual(got, want) {
t.Errorf("want:%v got:%v", want, got)
}
}
package main
import (
"reflect"
"testing"
)
func TestSplit(t *testing.T) {
// 定义测试用例结构体
type test struct {
input string
sep string
want []string
}
// 定义测试用例切片,添加测试用例
tests := map[string]test{
"用例1:字母": {input: "a:b:c", sep: ":", want: []string{"a", "b", "c"}},
"用例2:汉字": {input: "哈咯哈", sep: "咯", want: []string{"哈", "哈"}},
}
// 遍历测试用例,注意执行
for name, v := range tests {
got := Split(v.input, v.sep)
t.Run(name, func(t *testing.T) {
if !reflect.DeepEqual(got, v.want) {
t.Errorf("want:%v got:%v", v.want, got)
}
})
}
}
go test -v:显示用例执行的详细信息go test -run=Split/用例2:汉字:根据用例名字执行指定用例go test -cover:显示测试覆盖度go test -cover -coverprofile=c.out:在当前目录下生成c.out文件go tool cover -html=c.out:使用cover工具查看图形测试结果页面
性能基准测试
func BenchmarkSplit(b *testing.B){
for i:=0;i<b.N;i++{
Split("a:b:c",":")
}
}
go test -bench=Split:执行性能测试10000: 执行次数xx ns/op: 每次执行耗时
go test -bench=Split -benchmem:查看更多的数据xx B/op: 每次消耗内存xx allocs/op: 每次执行进行xx次内存申请

浙公网安备 33010602011771号