Go单元测试
go 程序中一般使用官方的go test 做测试,面对一些复杂情况和紧急需求写单元测试就变得有些仓促,今天介绍一款利器gotests来写单元测试
安装
go get -u github.com/cweill/gotests/...
以一个不同类型比较相等的列子做个测试,下面是一个simple.go文件
package simple
import "reflect"
type Point struct {
X int
Y int
}
type Circular struct {
Point
Peri float32
}
type PointCollect struct {
Points []Point
}
// 数组相等
func TArrayEqual(a, b [10]int) bool {
if a == b {
return true
}
return false
}
// 切片相等
func TSliceEqual(a, b []int) bool {
if reflect.DeepEqual(a, b) {
return true
}
return false
}
// 字典相等
func TMapEqual(a, b map[string]string) bool {
if reflect.DeepEqual(a, b) {
return true
}
return false
}
// 结构体相等
func TPointEqual(a, b Point) bool {
if a == b {
return true
}
return false
}
// 结构体相等
func TCircularEqual(a, b Circular) bool {
if a == b {
return true
}
return false
}
// 切片结构体相等
func TPointCollect(a, b PointCollect) bool {
if reflect.DeepEqual(a, b) {
return true
}
return false
}
执行
gotests -all -w simple.go
执行这个命令会自动生成simple_test.go文件 -all命令为所有的函数生成测试函数
func TestTArrayEqual(t *testing.T) {
type args struct {
a [10]int
b [10]int
}
tests := []struct {
name string
args args
want bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := TArrayEqual(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("TArrayEqual() = %v, want %v", got, tt.want)
}
})
}
}
...
只需要填写对应的test cases 就可以了
package simple
import "testing"
func TestTArrayEqual(t *testing.T) {
type args struct {
a [10]int
b [10]int
}
tests := []struct {
name string
args args
want bool
}{
// TODO: Add test cases.
{
name: "good case",
args: args{
a: [10]int{1, 2, 3, 4},
b: [10]int{1, 2, 3, 4},
},
want: true,
},
{
name: "bad case",
args: args{
a: [10]int{1, 2, 3},
b: [10]int{1, 2, 3, 4},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := TArrayEqual(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("TArrayEqual() = %v, want %v", got, tt.want)
}
})
}
}
func TestTSliceEqual(t *testing.T) {
type args struct {
a []int
b []int
}
tests := []struct {
name string
args args
want bool
}{
// TODO: Add test cases.
{
name: "good case",
args: args{
a: []int{1, 2, 3},
b: []int{1, 2, 3},
},
want: true,
},
{
name: "bad case",
args: args{
a: []int{1, 2, 3, 4},
b: []int{1, 2, 3},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := TSliceEqual(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("TSliceEqual() = %v, want %v", got, tt.want)
}
})
}
}
func TestTMapEqual(t *testing.T) {
type args struct {
a map[string]string
b map[string]string
}
tests := []struct {
name string
args args
want bool
}{
// TODO: Add test cases.
{
name: "good case",
args: args{
a: map[string]string{"a":"1", "b":"2", "c":"3"},
b: map[string]string{"a":"1", "b":"2", "c":"3"},
},
want: true,
},
{
name: "bad case",
args: args{
a: map[string]string{"a":"1", "b":"2", "c":"3"},
b: map[string]string{"d":"4", "e":"5", "f":"6"},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := TMapEqual(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("TMapEqual() = %v, want %v", got, tt.want)
}
})
}
}
func TestTPointEqual(t *testing.T) {
type args struct {
a Point
b Point
}
tests := []struct {
name string
args args
want bool
}{
// TODO: Add test cases.
{
name: "good case",
args: args{
a: Point{X: 1, Y: 2},
b: Point{X: 1, Y: 2},
},
want: true,
},
{
name: "bad case",
args: args{
a: Point{X: 1, Y: 1},
b: Point{X: 1, Y: 2},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := TPointEqual(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("TPointEqual() = %v, want %v", got, tt.want)
}
})
}
}
func TestTCircularEqual(t *testing.T) {
type args struct {
a Circular
b Circular
}
tests := []struct {
name string
args args
want bool
}{
// TODO: Add test cases.
{
name: "good case",
args: args{
a: Circular{
Point: Point{X: 1, Y: 1},
Peri: 1.5,
},
b: Circular{
Point: Point{X: 1, Y: 1},
Peri: 1.5,
},
},
want: true,
},
{
name: "good case",
args: args{
a: Circular{
Point: Point{X: 1, Y: 1},
Peri: 1.5,
},
b: Circular{
Point: Point{X: 1, Y: 1},
Peri: 2.5,
},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := TCircularEqual(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("TCircularEqual() = %v, want %v", got, tt.want)
}
})
}
}
func TestTPointCollect(t *testing.T) {
type args struct {
a PointCollect
b PointCollect
}
tests := []struct {
name string
args args
want bool
}{
// TODO: Add test cases.
{
name: "good case",
args: args{
a: PointCollect{[]Point{{
X: 1,
Y: 1,
}, {
X: 1,
Y: 2,
}}},
b: PointCollect{[]Point{{
X: 1,
Y: 1,
}, {
X: 1,
Y: 2,
}}},
},
want: true,
},
{
name: "bad case",
args: args{
a: PointCollect{[]Point{{
X: 1,
Y: 1,
}, {
X: 1,
Y: 2,
}}},
b: PointCollect{[]Point{{
X: 2,
Y: 2,
}, {
X: 2,
Y: 4,
}}},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := TPointCollect(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("TPointCollect() = %v, want %v", got, tt.want)
}
})
}
}
测试
go test -v
=== RUN TestTArrayEqual
=== RUN TestTArrayEqual/good_case
=== RUN TestTArrayEqual/bad_case
--- PASS: TestTArrayEqual (0.00s)
--- PASS: TestTArrayEqual/good_case (0.00s)
--- PASS: TestTArrayEqual/bad_case (0.00s)
=== RUN TestTSliceEqual
=== RUN TestTSliceEqual/good_case
=== RUN TestTSliceEqual/bad_case
--- PASS: TestTSliceEqual (0.00s)
--- PASS: TestTSliceEqual/good_case (0.00s)
--- PASS: TestTSliceEqual/bad_case (0.00s)
=== RUN TestTMapEqual
=== RUN TestTMapEqual/good_case
=== RUN TestTMapEqual/bad_case
--- PASS: TestTMapEqual (0.00s)
--- PASS: TestTMapEqual/good_case (0.00s)
--- PASS: TestTMapEqual/bad_case (0.00s)
=== RUN TestTPointEqual
=== RUN TestTPointEqual/good_case
=== RUN TestTPointEqual/bad_case
--- PASS: TestTPointEqual (0.00s)
--- PASS: TestTPointEqual/good_case (0.00s)
--- PASS: TestTPointEqual/bad_case (0.00s)
=== RUN TestTCircularEqual
=== RUN TestTCircularEqual/good_case
=== RUN TestTCircularEqual/good_case#01
--- PASS: TestTCircularEqual (0.00s)
--- PASS: TestTCircularEqual/good_case (0.00s)
--- PASS: TestTCircularEqual/good_case#01 (0.00s)
=== RUN TestTPointCollect
=== RUN TestTPointCollect/good_case
=== RUN TestTPointCollect/bad_case
--- PASS: TestTPointCollect (0.00s)
--- PASS: TestTPointCollect/good_case (0.00s)
--- PASS: TestTPointCollect/bad_case (0.00s)
PASS
看到写的测试已经全部通过了
总结
写单元测试是很多程序员不喜欢面对了,今天介绍的gotests自动生成测试文件的工具,减少了写测试文件的负担,能够大大提高程序的健壮性和稳定性 。
网友评论