写这篇文章前,我主要思考了几个问题:
(1)如果说main可以用dlv工具来debug,那么package怎么验证写的函数的准确性?
(2)难道每次都要build && run,然后tail log调试吗?
(3)如何使用go test的基准测试?
(4)如何统计单元测试的覆盖率?
因此,对于package的function,我们用unit test来验证其准确性。
本文举个栗子分别实现:test 、benchmark(基准测试)、coverage(覆盖率测试)
所谓单元测试(Unit Testing - UT):是指对软件中的最小可测试单元进行检查和验证。
在命名文件时需要让文件必须以_test
结尾。默认的情况下,go test
命令不需要任何的参数,它会自动把源码包下面所有 test 文件测试完毕。
-bench regexp 执行相应的 benchmarks,例如 -bench=.;
-cover 开启测试覆盖率;
-run regexp 只运行 regexp 匹配的函数,例如 -run=Array 那么就执行包含有 Array 开头的函数;
-v 显示测试的详细命令。
(1)源文件:field.go
package utils
import (
"fmt"
)
type MyStruct struct {
name string
}
func GetFieldValue(x *MyStruct) string {
value := x.name
return value
}
func SetFieldValue(x *MyStruct, value string) {
fmt.Println("SetFieldValue()")
x.name = value
}
func Hello(name string) string {
return "Hello" + name
}
(2)测试文件:field_test.go
package utils
import "testing"
func TestMytest(t *testing.T) {
var st MyStruct
SetFieldValue(&st, "hello")
val := GetFieldValue(&st)
if val != "hello" {
t.Error("Set Field")
}
}
func TestABC(t *testing.T) {
t.Log("Test ABC")
}
func BenchmarkGetFieldValue(b *testing.B) {
var st MyStruct
SetFieldValue(&st, "hello")
for i := 0; i < b.N; i++ {
GetFieldValue(&st)
}
}
(3)进行单元测试: go test -v
[homework@xxxxxxxx utils]$ go test -v
=== RUN TestMytest
SetFieldValue()
--- PASS: TestMytest (0.00s)
=== RUN TestABC
--- PASS: TestABC (0.00s)
field_test.go:16: Test ABC
PASS
ok wenhan/utils 0.003s
ps:如果只想针对一个函数进行测试,怎么办?
[homework@xxxxxxxx utils]$ go test -v -run TestMytest
=== RUN TestMytest
SetFieldValue()
--- PASS: TestMytest (0.00s)
PASS
ok wenhan/utils 0.002s
(4)benchmark(基准测试):获得代码内存占用和运行效率的性能数据
测试用例需要以Benchmark开头的函数,参数用:b *testing.B
[homework@xxxxxxxx utils]$ go test -v -bench=.
=== RUN TestMytest
SetFieldValue()
--- PASS: TestMytest (0.00s)
=== RUN TestABC
--- PASS: TestABC (0.00s)
field_test.go:16: Test ABC
SetFieldValue()
goos: linux
goarch: amd64
pkg: wenhan/utils
BenchmarkGetFieldValue-2 SetFieldValue()
SetFieldValue()
SetFieldValue()
SetFieldValue()
SetFieldValue()
1000000000 0.437 ns/op
PASS
ok wenhan/utils 0.493s
说明:表示执行了10亿次操作,平均每次0.473ns(纳秒)
(5)go test -cover (测试覆盖率)
[homework@xxxxxxxx utils]$ go test -cover
SetFieldValue()
PASS
coverage: 80.0% of statements
ok wenhan/utils 0.002s
说明:覆盖率为80%
生成覆盖率的详细文件
[homework@xxxxxxxx utils]$ go test -coverprofile=covprofile
SetFieldValue()
PASS
coverage: 80.0% of statements
ok wenhan/utils 0.003s
[homework@xxxxxxxx utils]$ cat covprofile
mode: set #生成的中间文件covprofile中覆盖率统计模式为set
wenhan/utils/field.go:11.40,14.2 2 1
wenhan/utils/field.go:16.47,19.2 2 1
wenhan/utils/field.go:21.32,23.2 1 0
## 生成HTML文件
[homework@xxxxxxxx utils]$ go tool cover -html=covprofile -o coverage.html
[homework@xxxxxxxx utils]$ ll
total 16K
-rw-rw-r-- 1 homework homework 2.5K Apr 6 15:13 coverage.html
-rw-rw-r-- 1 homework homework 121 Apr 6 15:12 covprofile
-rw-rw-r-- 1 homework homework 305 Apr 6 15:09 field.go
-rw-rw-r-- 1 homework homework 385 Apr 6 14:56 field_test.go
浏览器打开:coverage.html,其中会提示not covered的函数为Hello
OK,这篇关于Go UT的文章就写到这里,Done!