gotests

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)定性 越妈。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末季俩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子梅掠,更是在濱河造成了極大的恐慌酌住,老刑警劉巖店归,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異酪我,居然都是意外死亡消痛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門都哭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秩伞,“玉大人,你說我怎么就攤上這事欺矫∩葱拢” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵穆趴,是天一觀的道長脸爱。 經常有香客問我,道長未妹,這世上最難降的妖魔是什么簿废? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮教寂,結果婚禮上捏鱼,老公的妹妹穿的比我還像新娘。我一直安慰自己酪耕,他們只是感情好导梆,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著迂烁,像睡著了一般看尼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盟步,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天藏斩,我揣著相機與錄音,去河邊找鬼却盘。 笑死狰域,一個胖子當著我的面吹牛,可吹牛的內容都是我干的黄橘。 我是一名探鬼主播兆览,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼塞关!你這毒婦竟也來了抬探?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤帆赢,失蹤者是張志新(化名)和其女友劉穎小压,沒想到半個月后线梗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡怠益,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年仪搔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溉痢。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡僻造,死狀恐怖憋他,靈堂內的尸體忽然破棺而出孩饼,到底是詐尸還是另有隱情,我是刑警寧澤竹挡,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布镀娶,位于F島的核電站,受9級特大地震影響揪罕,放射性物質發(fā)生泄漏梯码。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一好啰、第九天 我趴在偏房一處隱蔽的房頂上張望轩娶。 院中可真熱鬧,春花似錦框往、人聲如沸鳄抒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽许溅。三九已至,卻和暖如春秉版,著一層夾襖步出監(jiān)牢的瞬間贤重,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工清焕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留并蝗,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓秸妥,卻偏偏與公主長得像滚停,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子筛峭,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內容