Go 语言有自带的测试框架testing,可以用来实现单元测试(T 类型)和性能测试(B 类型),通过go test命令来执行单元测试和性能测试。
go test 执行测试用例时,是以 go 包为单位进行测试的。执行时需要指定包名,比如go test 包名,如果没有指定包名,默认会选择执行命令时所在的包。go test 在执行时,会遍历以_test.go结尾的源码文件,执行其中以Test、Benchmark、Example开头的测试函数。
注意:
测试文件与被测文件需要在同一个目录包下,测试文件必须以_test结尾。比如hello.go对应的测试文件可以命名为hello_test.go(也可以一个测试文件测试包内其他所有文件的导出方法)
测试文件的测试方法必须是Test开头,比如测试Abs方法,就可以命名为TestAbs或者Test_Abs
测试方法必须传入参数 *testing.T,可以使用该类型来记录错误或测试状态。我们可以调用 testing.T 的 Error 、Errorf 、FailNow 、Fatal 、FatalIf 方法,来说明测试不通过
代码实战:
package unittest
import "math"
// Abs returns the absolute value of x.
func Abs(x float64) float64 {
return math.Abs(x)
}
// Max returns the larger of x or y.
func Max(x, y float64) float64 {
return math.Max(x, y)
}
package unittest
import "testing"
// go test 自动搜集所有的测试文件,也就是格式为*_test.go的文件,从中提取全部测试函数并执行。
// go test -v 显示所有测试函数的运行细节
// go test -v -run ,指定要执行的测试函数。如 go test -v -run="TestAbs"
// 测试文件与被测文件在同一个目录包下,测试文件以_test结尾。比如hello.go对应的测试文件就是hello_test.go
// 测试文件的测试方法必须是Test开头,比如测试Abs方法,就可以命名为TestAbs或者Test_Abs
// 测试方法必须传入参数t *testing.T
func TestAbs(t *testing.T) {
got := Abs(-1)
if got != 1 {
t.Errorf("Abs(-1) = %f; want 1", got)
}
}
func TestAbs_2(t *testing.T) {
tests := []struct {
x float64
want float64
}{
{-0.3, 0.3},
{-2, 2},
{-3.1, 3.1},
{5, 5},
}
for _, tt := range tests {
if got := Abs(tt.x); got != tt.want {
t.Errorf("Abs() = %f, want %v", got, tt.want)
}
}
}
func TestMax(t *testing.T) {
got := Max(2, 8)
if got != 8 {
t.Errorf("Abs(2,8) = %f; want 8", got)
}
}
开始执行测试:
go test 自动搜集所有的测试文件,也就是格式为*_test.go的文件,从中提取全部测试函数并执行。
go test -v 显示所有测试函数的运行细节
go test -v -run ,指定要执行的测试函数。如 go test -v -run=“TestAbs”
强烈推荐使用单元测试工具自动生成测试代码,然后我们只需要写测试用例!!!这样我们就能节省很多时间精力,而且还不会出错。
1、安装gotests工具
go get -u github.com/cweill/gotests/...
2、查看gotests的用法
gotests --help
3、进入测试代码目录,执行 gotests 为该目录下的所有函数生成测试用例:
gotests -all -w .
#-all:所有方法生成测试用例
#-w . : 保存测试文件到当前目录
4、指定一个方法DelPHPConf生成测试用例
gotests -only DelPHPConf -w .
#-only :指定一个方法名
5、添加测试用例
生成完测试用例,你只需要添加需要测试的输入和预期的输出就可以了。我们只需要补全TODO位置的测试数据即可。
补全测试用例后,代码如下:
func TestAbs(t *testing.T) {
type args struct {
x float64
}
tests := []struct {
name string
args args
want float64
}{
{"詹姆斯", args{-12}, 12},
{"杜兰特", args{-2}, 2},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Abs(tt.args.x); got != tt.want {
t.Errorf("Abs() = %v, want %v", got, tt.want)
}
})
}
}