《Go语言学习笔记》-测试
整理自《go 语言学习笔记》第十一章
- 单元测试
单元测试不仅需要测试逻辑算法是否符合预期,而且还要承担监控代码质量的责任。单元测试本身就是对即将实现的算法做复合预演,包括输入条件和返回预期结果。
可将测试、版本管理工具,以及自动发布整合。单元测试可自动化进行,能持之以恒。
工具链和标准库自带单元测试框架:
1、测试代码须放在当前包以“_test.go”结尾的文件中。
2、测试函数以Test为名称前缀。
3、测试命令(go test)忽略以“_”或“.”开头的测试文件。
4、正常编译操作(go build/install)会忽略测试文件。
常用测试参数说明:
- -args 命令行参数
- -v 输出详细信息
- -parallel 并发执行,默认值为GOMAXPROCS
- -run 指定测试函数,正则表达式
- -timeout 全部测试累计时间超过将引发panic,默认值为10ms
- -count 重复测试次数,默认值为1
表驱动
可用一种类似数据表的模式来批量的输入条件并依次对比结果。这种方法将测试数据和测试逻辑分离。
func add(x, y int)int {
return x + y
}
func TestAdd(t *testing.T) {
var tests = [] struct{
x int
y int
expect int
}{
{
1, 1, 2},
{
2, 2, 4},
{
3, 2, 5},
}
for _, tt := range tests {
actual := add(tt.x, tt.y)
if actual != tt.expect{
t.Errorf("add(%d, %d): expect %d, actual %d", tt.x, tt.y, tt.expect, actual)
}
}
test main
某些情况下,须为测试用例提供初始化和清理操作,但testing并没有setup/teardown机制。
解决方法:自定义一个TestMain的函数,go test会改为执行该函数。
func TestMain(m *testing.M){
//setup
code := m.Run() //调用测试用例
//teardown
os.Exit(code) //注意 os.Exit不会执行defer
注:不能为每个测试用例写一个TestMain,要实现用例组合套件,须借助MainStart自行构建M对象(代码参考P220)
2.性能测试
性能测试函数以Benchmark为名称前缀,同样保存在“*_test.go”文件里。
测试工具默认不会执行性能测试,要使用bench参数。它通过逐步调整B.N值,反复执行测试函数直到能获得准确的测试结果。
func BenchmarkAdd(b *testing.B){
println("B.N=", b.N)
for i := 0; i < b.N; i++{
_ = add(1, 2)
}
}
go test -bench .
注:
1、仅执行性能测试,可用run=NONE忽略所有单元测试用例
2、默认以并发方式执行,但cpu 参数设定多个并发限制来观察结果
go test -bench . -cpu 1,2,4
3、默认循环次数过少,取平均值不足以准确计量性能。可用benchtime指定最小测试时间。
go test -bench . -benchtime 5s
memory
性能测试关心的不仅仅是执行时间,还包括在堆上的内存分配,内存分配和垃圾回收的相关操作也应计入消耗成本。
3、代码覆盖率
代码覆盖率是度量测试自身完整和有效性的一种手段。通过覆盖率值,我们可分析出测试代码的编写质量。检测它是否提供了足够的测试条件,是否执行了足够的函数、语句、分支和代码行等,以此量化测试本身,让白盒测试真正起到应有的质量保障作用。
注:代码覆盖率也常常用来发现死代码(dead code)
更详细的信息,可指定covermode 和 coverprofile参数。
- set :是否执行。
- count:执行次数。
- automic:执行次数,支持并发模式。
(代码覆盖率暂时并没有用过,用过再过来补充)
还没有评论,来说两句吧...