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
}
// 數(shù)組相等
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
}
執(zhí)行
gotests -all -w simple.go
執(zhí)行這個命令會自動生成simple_test.go文件 -all命令為所有的函數(shù)生成測試函數(shù)
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自動生成測試文件的工具,減少了寫測試文件的負擔娜扇,能夠大大提高程序的健壯性和穩(wěn)定性 越妈。