go语言常见的单元测试和案例测试
1. 单元测试
go中的测试比较简单,遵循以下几点即可:
- 测试文件以
源文件名_test.go
命名 - 测试函数名称格式以
TestFuncName(t *testing.T)
命名 - 测试错误 t.Error / t.Fail / t.Errorf 记录
- 测试日志 t.Log 记录
我们来看一个例子
calc.go
package calc
func Dec(a, b int) int {
return a - b
}
calc_test.go
package calc
import "testing"
func TestDec(t *testing.T) {
a, b := 3,1
except := a - b
fact := Dec(a,b)
if except != fact {
t.Errorf("%d - %d except %d but fact %d \n",a,b,except,fact)
}
t.Log("success")
}
打印结果:
=== RUN TestDec
--- PASS: TestDec (0.00s)
calc_test.go:12: success
PASS
2. 测试表
而事实上,我们要测试某个函数通常需要覆盖性的提供多组数据,一个一个写特别麻烦,这就用到了测试表
我们改写 calc_test.go
如下:
func TestDec(t *testing.T) {
tables := []struct{
a int
b int
res int
}{
{1,2,1},
{5,4,1},
{24,4,10},
{255,171,74},
}
for _, except := range tables {
fact := Dec(except.a,except.b)
if except.res != fact {
t.Errorf("%d - %d except %d but fact %d \n",except.a,except.b,except.res,fact)
}
}
}
我故意写错了三个结果,测试打印如下:
=== RUN TestDec
--- FAIL: TestDec (0.00s)
calc_test.go:19: 1 - 2 except 1 but fact -1
calc_test.go:19: 24 - 4 except 10 but fact 20
calc_test.go:19: 255 - 171 except 74 but fact 84
FAIL
3. 代码覆盖
单元测试的另一个重要指标就是代码覆盖率,代码覆盖率可以判断测试的完备性,即考虑到了各种可能的类型
我们稍微改动一下calc.go
package calc
func Dec(a, b int) int {
res := a - b
if res < 0 {
return 0
}
return res
}
然后我们将 calc_test.go
中的测试数据更改为
tables := []struct{
a int
b int
res int
}{
{5,4,1},
{24,4,10},
}
执行 :
go test calc -cover
注意: 这里的calc
是基于GOPATH
和GOROOT
的,比如:
GOPATH : e:/gowork
calc_test.go: e:/gowork/src/study/fortest/
那么你的路径就应该写成
go test tudy/fortest -cover
否则会找不到你的测试文件
打印结果:
=== RUN TestDec
--- FAIL: TestDec (0.00s)
calc_test.go:17: 24 - 4 except 10 but fact 20
FAIL
coverage: 75.0% of statements
如果使用GoLand
IDE我们还能看到完整的代码覆盖行
如果你没有IDE,你可以生成 html 也能直观的查看
go test calc -cover -coverprofile=c.out
go tool cover -html=c.out -o coverage.html
然后在浏览器中打开 coverage.html
即可查看
4. 案例测试
平常写测试都比较懒,想用更少的代码来解决测试的问题,可以使用案例测试,不需要写
繁琐的打印语句和期待对比,这些都要go编译器自己去做
案例测试遵循以下几点:
- 测试文件以
源文件_example_test.go
命名 - 测试函数名称格式以
ExampleFuncName()
命名 - 测试结果打印 以下列格式注释:
// Output:
// 结果1
// 结果2
...
calc_example_test.go
package calc
import (
"fmt"
)
func ExampleDec() {
tables := []struct{
a int
b int
}{
{5,4},
{24,10},
}
for _, except := range tables {
fmt.Println(Dec(except.a,except.b))
}
// Output:
// 1
// 13
}
运行:
go test calc
打印结果:
=== RUN ExampleDec
--- FAIL: ExampleDec (0.00s)
got:
1
14
want:
1
13
FAIL