Go語言開發(十九)、GoConvey測試框架
Go語言開發(十九)、GoConvey測試框架
一、GoConvey簡介
1、GoConvey簡介
GoConvey是一款針對Golang的測試框架,可以管理和執行測試用例,同時提供了豐富的斷言函式,並支援多種Web介面特性。
官方地址:
https://github.com/smartystreets/goconvey
安裝:
go get github.com/smartystreets/goconvey
2、GoConvey的特點
GoConvey支援 go test,可直接在終端視窗和瀏覽器上使用。GoConvey特點如下:
A、直接整合go test
B、巨大的迴歸測試套件
C、可讀性強的色彩控制檯輸出
D、完全自動化的Web UI
E、測試程式碼生成器
二、GoConvey測試用例編寫
1、GoConvey標準斷言
官方文件:
https://github.com/smartystreets/goconvey/wiki
GoConvey自帶大量的標準斷言函式,可以通過So()使用。
(1)通用相等比較
So(thing1, ShouldEqual, thing2)
So(thing1, ShouldNotEqual, thing2)
So(thing1, ShouldResemble, thing2)
用於陣列、切片、map和結構體的深度比較
So(thing1, ShouldNotResemble, thing2)
So(thing1, ShouldPointTo, thing2)
So(thing1, ShouldNotPointTo, thing2)
So(thing1, ShouldBeNil)
So(thing1, ShouldNotBeNil)
So(thing1, ShouldBeTrue)
So(thing1, ShouldBeFalse)
So(thing1, ShouldBeZeroValue)
(2)數值比較
So(1, ShouldBeGreaterThan, 0)
So(1, ShouldBeGreaterThanOrEqualTo, 0)
So(1, ShouldBeLessThan, 2)
So(1, ShouldBeLessThanOrEqualTo, 2)
So(1.1, ShouldBeBetween, .8, 1.2)
So(1.1, ShouldNotBeBetween, 2, 3)
So(1.1, ShouldBeBetweenOrEqual, .9, 1.1)
So(1.1, ShouldNotBeBetweenOrEqual, 1000, 2000)
So(1.0, ShouldAlmostEqual, 0.99999999, .0001)
帶容差比較,預設容差為0.0000000001
So(1.0, ShouldNotAlmostEqual, 0.9, .0001)
(3)資料集合比較
So([]int{2, 4, 6}, ShouldContain, 4)
So([]int{2, 4, 6}, ShouldNotContain, 5)
So(4, ShouldBeIn, ...[]int{2, 4, 6})
So(4, ShouldNotBeIn, ...[]int{1, 3, 5})
So([]int{}, ShouldBeEmpty)
So([]int{1}, ShouldNotBeEmpty)
So(map[string]string{"a": "b"}, ShouldContainKey, "a")
So(map[string]string{"a": "b"}, ShouldNotContainKey, "b")
So(map[string]string{"a": "b"}, ShouldNotBeEmpty)
So(map[string]string{}, ShouldBeEmpty)
So(map[string]string{"a": "b"}, ShouldHaveLength, 1)
支援map、切片、通道、字串
(4)字串比較
So("asdf", ShouldStartWith, "as")
So("asdf", ShouldNotStartWith, "df")
So("asdf", ShouldEndWith, "df")
So("asdf", ShouldNotEndWith, "df")
So("asdf", ShouldContainSubstring, "sd")
So("asdf", ShouldNotContainSubstring, "er")
So("adsf", ShouldBeBlank)
So("asdf", ShouldNotBeBlank)
(5)異常比較
So(func(), ShouldPanic)
So(func(), ShouldNotPanic)
So(func(), ShouldPanicWith, "") // or errors.New("something")
So(func(), ShouldNotPanicWith, "") // or errors.New("something")
(6)型別檢查
So(1, ShouldHaveSameTypeAs, 0)
So(1, ShouldNotHaveSameTypeAs, "asdf")
(7)時間比較
So(time.Now(), ShouldHappenBefore, time.Now())
So(time.Now(), ShouldHappenOnOrBefore, time.Now())
So(time.Now(), ShouldHappenAfter, time.Now())
So(time.Now(), ShouldHappenOnOrAfter, time.Now())
So(time.Now(), ShouldHappenBetween, time.Now(), time.Now())
So(time.Now(), ShouldHappenOnOrBetween, time.Now(), time.Now())
So(time.Now(), ShouldNotHappenOnOrBetween, time.Now(), time.Now())
So(time.Now(), ShouldHappenWithin, duration, time.Now())
So(time.Now(), ShouldNotHappenWithin, duration, time.Now())
2、測試用例編寫
官方推薦使用匯入GoConvey的輔助包以減少冗餘的程式碼:
. "github.com/smartystreets/goconvey/convey"
GoConvey包匯入在工程程式碼中如下:
import ( "testing" . "github.com/smartystreets/goconvey/convey" )
每個單元測試的名稱需以 Test 開頭,並需要接收一個型別為 *testing.T
的引數。
每個測試用例需要使用Convey函式包裹起來,第一個引數為string型別的測試用例描述;第二個引數一般為 *testing.T
;第三個引數為不接收任何引數也不返回任何值的函式(通常以閉包的形式書寫)。
Convey語句可以無限巢狀,以體現各個測試用例之間的關係,只有最外層的 Convey 需要傳入 *testing.T
型別變數,內層巢狀的Convey不需要傳入。
func TestAdd(t *testing.T) { Convey("將兩數相加", t, func() { So(Add(1, 2), ShouldEqual, 3) }) }
GoConvey提供了Convey/So的Skip巨集,用於想忽略某些斷言操作但不想刪除或註釋的場景。
SkipConvey:表明相應的閉包函式將不被執行。
SkipSo:表明相應的斷言將不被執行。
當存在SkipConvey或SkipSo時,測試日誌中會顯式打上"skipped"形式的標記:
當測試程式碼中存在SkipConvey時,相應閉包函式中不管是否為SkipSo,都將被忽略,測試日誌中對應的符號僅為一個"⚠"
當測試程式碼Convey語句中存在SkipSo時,測試日誌中每個So對應一個"✔"或"✘",每個SkipSo對應一個"⚠",按實際順序排列
不管存在SkipConvey還是SkipSo時,測試日誌中都有字串"{n} total assertions (one or more sections skipped)",其中{n}表示測試中實際已執行的斷言語句數。
3、測試用例示例
Operator.go檔案:
package Operator import ( "errors" ) func Add(a, b int) int { return a + b } func Subtract(a, b int) int { return a - b } func Multiply(a, b int) int { return a * b } func Division(a, b int) (int, error) { if b == 0 { return 0, errors.New("Divisor is0") } return a / b, nil }
Operator_test.go檔案:
package Operator import ( "testing" . "github.com/smartystreets/goconvey/convey" ) func TestAdd(t *testing.T) { Convey("將兩數相加", t, func() { So(Add(1, 2), ShouldEqual, 3) }) } func TestSubtract(t *testing.T) { Convey("將兩數相減", t, func() { So(Subtract(1, 2), ShouldEqual, -1) }) } func TestMultiply(t *testing.T) { Convey("將兩數相乘", t, func() { So(Multiply(3, 2), ShouldEqual, 6) }) } func TestDivision(t *testing.T) { Convey("將兩數相除", t, func() { Convey("除以非 0 數", func() { num, err := Division(10, 2) So(err, ShouldBeNil) So(num, ShouldEqual, 5) }) Convey("除以 0", func() { _, err := Division(10, 0) So(err, ShouldNotBeNil) }) }) }
4、定製斷言函式
So的函式原型如下:
func So(actual interface{}, assert assertion, expected ...interface{}) type assertion func(actual interface{}, expected ...interface{}) string
當assertion的返回值為""時表示斷言成功,否則表示失敗,GoConvey框架中的相關程式碼為:
const ( success= "" needExactValues= "This assertion requires exactly %d comparison values (you provided %d)." needNonEmptyCollection = "This assertion requires at least 1 comparison value (you provided 0)." )
定製斷言函式如下:
func ShouldSummerBeComming(actual interface{}, expected ...interface{}) string { if actual == "summer" && expected[0] == "comming" { return "" } else { return "summer is not comming!" } }
單元測試如下:
func TestSummer(t *testing.T) { Convey("TestSummer", t, func() { So("summer", ShouldSummerBeComming, "comming") So("winter", ShouldSummerBeComming, "comming") }) }
根據ShouldSummerBeComming的實現,閉包中第一個So將斷言成功,第二個So將斷言失敗。
三、測試結果檢視
1、命令列測試結果檢視
GoConvey相容Go原生的單元測試,可以直接使用Go命令來執行測試。
在測試程式碼目錄下執行go test命令:
go test -v
測試執行結果如下:
=== RUNTestAdd 將兩數相加 ✔ 1 total assertion --- PASS: TestAdd (0.00s) === RUNTestSubtract 將兩數相減 ✔ 2 total assertions --- PASS: TestSubtract (0.00s) === RUNTestMultiply 將兩數相乘 ✔ 3 total assertions --- PASS: TestMultiply (0.00s) === RUNTestDivision 將兩數相除 除以非 0 數 ✔✔ 除以 0 ✔ 6 total assertions --- PASS: TestDivision (0.00s) PASS okGoExample/GoConvey 0.002s
2、Web介面測試結果檢視
檢視goconvey用法
goconvey -h
-cover:開啟覆蓋率統計功能
-depth int:掃描目錄的深度,-1:掃描無窮深度,0:掃描當前目錄
-excludedDirs string:將某些目錄排除在掃描外,多個目錄使用逗號分割
-host string:指定開啟HTTP服務的主機
-launchBrowser:觸發自動開啟瀏覽器,預設為true
-port int:指定HTTP服務的埠
-workDir string:指定工作目錄,預設為當前目錄
在測試用例原始碼目錄下執行goconvey:
goconvey -port 8081
在瀏覽器開啟:
結果如下:
