GoConvey是一款針對(duì)Golang的測(cè)試框架,可以管理和運(yùn)行測(cè)試用例,同時(shí)提供了豐富的斷言函數(shù),并支持多種Web界面特性。
官方地址:
https://github.com/smartystreets/goconvey
安裝:go get github.com/smartystreets/goconvey
GoConvey支持 go test,可直接在終端窗口和瀏覽器上使用。GoConvey特點(diǎn)如下:
A、直接集成go test
B、巨大的回歸測(cè)試套件
C、可讀性強(qiáng)的色彩控制臺(tái)輸出
D、完全自動(dòng)化的Web UI
E、測(cè)試代碼生成器
官方文檔:
https://github.com/smartystreets/goconvey/wiki
GoConvey自帶大量的標(biāo)準(zhǔn)斷言函數(shù),可以通過(guò)So()使用。
(1)通用相等比較
So(thing1, ShouldEqual, thing2)
So(thing1, ShouldNotEqual, thing2)
So(thing1, ShouldResemble, thing2)
用于數(shù)組、切片、map和結(jié)構(gòu)體的深度比較
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)數(shù)值比較
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)
帶容差比較,默認(rèn)容差為0.0000000001
So(1.0, ShouldNotAlmostEqual, 0.9, .0001)
(3)數(shù)據(jù)集合比較
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)類(lèi)型檢查
So(1, ShouldHaveSameTypeAs, 0)
So(1, ShouldNotHaveSameTypeAs, "asdf")
(7)時(shí)間比較
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())
官方推薦使用導(dǎo)入GoConvey的輔助包以減少冗余的代碼:. "github.com/smartystreets/goconvey/convey"
GoConvey包導(dǎo)入在工程代碼中如下:
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
每個(gè)單元測(cè)試的名稱需以?Test?開(kāi)頭,并需要接收一個(gè)類(lèi)型為?*testing.T?
的參數(shù)。
每個(gè)測(cè)試用例需要使用Convey函數(shù)包裹起來(lái),第一個(gè)參數(shù)為string類(lèi)型的測(cè)試用例描述;第二個(gè)參數(shù)一般為*testing.T
;第三個(gè)參數(shù)為不接收任何參數(shù)也不返回任何值的函數(shù)(通常以閉包的形式書(shū)寫(xiě))。
Convey語(yǔ)句可以無(wú)限嵌套,以體現(xiàn)各個(gè)測(cè)試用例之間的關(guān)系,只有最外層的?Convey?需要傳入*testing.T
類(lèi)型變量,內(nèi)層嵌套的Convey不需要傳入。
func TestAdd(t *testing.T) {
Convey("將兩數(shù)相加", t, func() {
So(Add(1, 2), ShouldEqual, 3)
})
}
GoConvey提供了Convey/So的Skip宏,用于想忽略某些斷言操作但不想刪除或注釋的場(chǎng)景。
SkipConvey:表明相應(yīng)的閉包函數(shù)將不被執(zhí)行。
SkipSo:表明相應(yīng)的斷言將不被執(zhí)行。
當(dāng)存在SkipConvey或SkipSo時(shí),測(cè)試日志中會(huì)顯式打上"skipped"形式的標(biāo)記:
當(dāng)測(cè)試代碼中存在SkipConvey時(shí),相應(yīng)閉包函數(shù)中不管是否為SkipSo,都將被忽略,測(cè)試日志中對(duì)應(yīng)的符號(hào)僅為一個(gè)"?"
當(dāng)測(cè)試代碼Convey語(yǔ)句中存在SkipSo時(shí),測(cè)試日志中每個(gè)So對(duì)應(yīng)一個(gè)"?"或"?",每個(gè)SkipSo對(duì)應(yīng)一個(gè)"?",按實(shí)際順序排列
不管存在SkipConvey還是SkipSo時(shí),測(cè)試日志中都有字符串"{n} total assertions (one or more sections skipped)",其中{n}表示測(cè)試中實(shí)際已運(yùn)行的斷言語(yǔ)句數(shù)。
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 is 0")
}
return a / b, nil
}
Operator_test.go文件:
package Operator
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestAdd(t *testing.T) {
Convey("將兩數(shù)相加", t, func() {
So(Add(1, 2), ShouldEqual, 3)
})
}
func TestSubtract(t *testing.T) {
Convey("將兩數(shù)相減", t, func() {
So(Subtract(1, 2), ShouldEqual, -1)
})
}
func TestMultiply(t *testing.T) {
Convey("將兩數(shù)相乘", t, func() {
So(Multiply(3, 2), ShouldEqual, 6)
})
}
func TestDivision(t *testing.T) {
Convey("將兩數(shù)相除", t, func() {
Convey("除以非 0 數(shù)", func() {
num, err := Division(10, 2)
So(err, ShouldBeNil)
So(num, ShouldEqual, 5)
})
Convey("除以 0", func() {
_, err := Division(10, 0)
So(err, ShouldNotBeNil)
})
})
}
So的函數(shù)原型如下:
func So(actual interface{}, assert assertion, expected ...interface{})
type assertion func(actual interface{}, expected ...interface{}) string
當(dāng)assertion的返回值為""時(shí)表示斷言成功,否則表示失敗,GoConvey框架中的相關(guān)代碼為:
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)."
)
定制斷言函數(shù)如下:
func ShouldSummerBeComming(actual interface{}, expected ...interface{}) string {
if actual == "summer" && expected[0] == "comming" {
return ""
} else {
return "summer is not comming!"
}
}
單元測(cè)試如下:
func TestSummer(t *testing.T) {
Convey("TestSummer", t, func() {
So("summer", ShouldSummerBeComming, "comming")
So("winter", ShouldSummerBeComming, "comming")
})
}
根據(jù)ShouldSummerBeComming的實(shí)現(xiàn),閉包中第一個(gè)So將斷言成功,第二個(gè)So將斷言失敗。
GoConvey兼容Go原生的單元測(cè)試,可以直接使用Go命令來(lái)執(zhí)行測(cè)試。
在測(cè)試代碼目錄下運(yùn)行g(shù)o test命令:go test -v?
測(cè)試執(zhí)行結(jié)果如下:
=== RUN TestAdd
將兩數(shù)相加 ?
1 total assertion
--- PASS: TestAdd (0.00s)
=== RUN TestSubtract
將兩數(shù)相減 ?
2 total assertions
--- PASS: TestSubtract (0.00s)
=== RUN TestMultiply
將兩數(shù)相乘 ?
3 total assertions
--- PASS: TestMultiply (0.00s)
=== RUN TestDivision
將兩數(shù)相除
除以非 0 數(shù) ??
除以 0 ?
6 total assertions
--- PASS: TestDivision (0.00s)
PASS
ok GoExample/GoConvey 0.002s
查看goconvey用法goconvey -h
-cover:開(kāi)啟覆蓋率統(tǒng)計(jì)功能
-depth int:掃描目錄的深度,-1:掃描無(wú)窮深度,0:掃描當(dāng)前目錄
-excludedDirs string:將某些目錄排除在掃描外,多個(gè)目錄使用逗號(hào)分割
-host string:指定開(kāi)啟HTTP服務(wù)的主機(jī)
-launchBrowser:觸發(fā)自動(dòng)開(kāi)啟瀏覽器,默認(rèn)為true
-port int:指定HTTP服務(wù)的端口
-workDir string:指定工作目錄,默認(rèn)為當(dāng)前目錄
在測(cè)試用例源碼目錄下運(yùn)行g(shù)oconvey:goconvey -port 8081
在瀏覽器打開(kāi):
http://localhost:8081
結(jié)果如下:
創(chuàng)新互聯(lián)www.cdcxhl.cn,專(zhuān)業(yè)提供香港、美國(guó)云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開(kāi)啟,新人活動(dòng)云服務(wù)器買(mǎi)多久送多久。