前言
- 基本上每一種高級(jí)計(jì)算機(jī)語(yǔ)言都有自己的代碼邏輯測(cè)試的方式,也就是單元測(cè)試旦部,其對(duì)于高級(jí)計(jì)算機(jī)語(yǔ)言的重要程度祈搜,大家在學(xué)習(xí)其他計(jì)算機(jī)語(yǔ)言的時(shí)候都有所了解,golang的單元測(cè)試士八,自身提供的testing package能夠滿(mǎn)足基本的測(cè)試需求容燕,當(dāng)然還有豐富API的第三方開(kāi)源庫(kù),比如 gocheck婚度,golang單元測(cè)試會(huì)分幾篇文章來(lái)講解蘸秘,這次主要講一下go語(yǔ)言使用testing做單元測(cè)試的一些方法
testing框架使用
- Go語(yǔ)言通過(guò)內(nèi)置庫(kù)testing包提供自動(dòng)化測(cè)試功能。包內(nèi)測(cè)試只要運(yùn)行命令 go test蝗茁,就能自動(dòng)運(yùn)行符合規(guī)則的測(cè)試函數(shù)
示例代碼
package hello
import "testing"
func TestHelloWorld(t *testing.T) {
t.Log("hello world")
}
- 說(shuō)下golang編寫(xiě)測(cè)試代碼的規(guī)范:
- 每個(gè)測(cè)試文件必須以 _test.go 結(jié)尾醋虏,并使用go test命令執(zhí)行測(cè)試模塊,否則golang無(wú)法識(shí)別出測(cè)試模塊
- 作為測(cè)試模塊文件哮翘,必須導(dǎo)入testing包
- 功能測(cè)試方法必須以 Test 開(kāi)頭颈嚼,一般是接被測(cè)方法的名字,如TestAdd饭寺,但不強(qiáng)制
- 測(cè)試用例會(huì)按照源代碼中寫(xiě)的順序依次執(zhí)行
- 測(cè)試方法TestXxx()的參數(shù)是
testing.T
阻课,用于收集記錄測(cè)試結(jié)果 - testing中的斷言需要自己編寫(xiě)叫挟,通過(guò)在方法中通過(guò)調(diào)用
testing.T
的Error
,Errorf
,FailNow
,Fatal
,FatalIf
方法來(lái)進(jìn)識(shí)別測(cè)試通過(guò)與否,調(diào)用Log
方法用來(lái)記錄測(cè)試的信息
命令行
- 單元測(cè)試使用 go test 命令啟動(dòng)
go test [-c] [-i] [build flags] [packages] [flags for test binary]
- 例如:
$ go test -v helloworld_test.go
=== RUN TestHelloWorld
--- PASS: TestHelloWorld (0.00s)
helloworld_test.go:8: hello world
PASS
ok command-line-arguments 0.004s
- 下面是go test的一些常用傳參方式
go test //默認(rèn)執(zhí)行當(dāng)前目錄下以xxx_test.go的測(cè)試文件
go test -v //可以看到詳細(xì)的輸出信息柑肴。
go test -v xxx_test.go //指定測(cè)試單個(gè)文件霞揉,但是該文件中如果調(diào)用了其它文件中的模塊會(huì)報(bào)錯(cuò)
go test -v xxx_test.go xxx.go //指定測(cè)試單個(gè)文件和被測(cè)文件
go test -v -test.run Testxxx //指定某個(gè)測(cè)試函數(shù)運(yùn)行,注意點(diǎn)是函數(shù)會(huì)用Testxxx去匹配所有包含Testxxx字符串作方法名的方法
go test -v -cover //顯示覆蓋的聲明程度
- 當(dāng)然還有其他例如用來(lái)做壓力測(cè)試的bench參數(shù),這個(gè)在后續(xù)的文章中講解
實(shí)戰(zhàn)應(yīng)用
- 廢話(huà)少說(shuō)晰骑,我們直接用demo代碼來(lái)講解
待測(cè)模塊 demo.go
//demo by terrychow
package main
import "fmt"
func Add(x,y int) int
{
return x+y
}
func main(){
z:=Add(1,2)
fmt.Print(z)
}
- 待測(cè)模塊demo.go是一個(gè)簡(jiǎn)單的加法方式Add适秩,這個(gè)也是本次測(cè)試的待測(cè)方法
- 由于待測(cè)模塊demo.go為文件名,測(cè)試模塊文件名必須以 _test 結(jié)尾硕舆,可命名為demo_test.go秽荞,不強(qiáng)制于被測(cè)文件前置同名,即可為other_test.go抚官,測(cè)試模塊文件路徑可隨意
測(cè)試模塊 demo_test.go
//demo_test by terrychow
package main
import "testing"
func TestAdd(t *testing.T) {
s:=Add(1,2)
if s!=3{
t.Error("Expected 3, got ", s)
}
}
- 依照測(cè)試代碼規(guī)范扬跋,我們編寫(xiě)出測(cè)試代碼模塊,然后使用go test命令來(lái)執(zhí)行
go test demo_test.go demo.go -v -cover
- 輸出為
=== RUN TestAdd
--- PASS: TestAdd (0.00s)
PASS
coverage: 33.3% of statements
ok command-line-arguments 0.613s coverage: 33.3% of statements
- 調(diào)整一下代碼斷言值
//demo_test by terrychow
package main
import "testing"
func TestAdd(t *testing.T) {
s:=Add(1,2)
if s!=4{//此處修改了錯(cuò)誤的返回
t.Error("Expected 4, got ", s)
}
}
- 輸出FAIL信息
=== RUN TestAdd
--- FAIL: TestAdd (0.00s)
demo_test.go:8: Expected 4, got 3
FAIL
coverage: 33.3% of statements
FAIL command-line-arguments 0.668s
- 一個(gè)基于golang內(nèi)置的測(cè)試框testing的單元測(cè)試已經(jīng)實(shí)現(xiàn)了
進(jìn)階玩法
- 有時(shí)候我們針對(duì)一個(gè)方法的測(cè)試凌节,會(huì)結(jié)合如路徑覆蓋钦听、條件覆蓋和語(yǔ)句覆蓋等測(cè)試思路來(lái)進(jìn)行對(duì)測(cè)試數(shù)據(jù)的組合測(cè)試,利用不同的數(shù)據(jù)組合驗(yàn)證覆蓋方式倍奢,于是就有了組合測(cè)試的方式朴上,針對(duì)Add方法,我們假設(shè)組合:
- 兩個(gè)正數(shù)相加
- 兩個(gè)負(fù)數(shù)相加
- 一正一負(fù)相加
示例代碼
//demo by terrychow
package main
import "testing"
func TestGroupAdd(t *testing.T){
var testdata=[] struct{
arg1 int
arg2 int
sum int
}{
{1,1,2},
{-1,-1,-2},
{-1,1,0},
}
for _, test:=range testdata{
sum:=Add(test.arg1,test.arg2)
if sum!=test.sum{
t.Errorf("arg1 %v and arg2 %v not except sum %v",test.arg1,test.arg2,test.sum)
}
}
}
- 輸出結(jié)果為
=== RUN TestGroupAdd
--- PASS: TestGroupAdd (0.00s)
PASS
coverage: 33.3% of statements
ok command-line-arguments 0.583s coverage: 33.3% of statements
- 假設(shè)其中一個(gè)為錯(cuò)誤的數(shù)據(jù)卒煞,如
package main
import "testing"
func TestGroupAdd(t *testing.T){
var testdata=[] struct{
arg1 int
arg2 int
sum int
}{
{1,1,2},
{-1,-1,-1},//此處的sum為錯(cuò)誤值
{-1,1,0},
}
for _, test:=range testdata{
sum:=Add(test.arg1,test.arg2)
if sum!=test.sum{
t.Errorf("arg1 %v and arg2 %v not except sum %v",test.arg1,test.arg2,test.sum)
}
}
}
- 輸出FAIL信息
=== RUN TestGroupAdd
--- FAIL: TestGroupAdd (0.00s)
demo1_test.go:17: arg1 -1 and arg2 -1 not except sum -1
FAIL
coverage: 33.3% of statements
FAIL command-line-arguments 0.688s
- 會(huì)有對(duì)應(yīng)的錯(cuò)誤信息返回痪宰,說(shuō)明錯(cuò)在哪一行
小結(jié)
- testing作為go語(yǔ)言?xún)?nèi)置的測(cè)試庫(kù),其當(dāng)然還不僅僅是做單元測(cè)試畔裕,之后講解的API和UI自動(dòng)化測(cè)試衣撬,以及后面的壓力、性能測(cè)試也會(huì)使用到testing扮饶,足見(jiàn)其核心作用
- 但testing也是有其限制性具练,沒(méi)有良好的測(cè)試斷言以及測(cè)試報(bào)告,靠使用者不斷地寫(xiě)if else來(lái)判斷顯然麻煩甜无,這也是下一篇文章要講解go最常用單元測(cè)試框架gocheck扛点,下回內(nèi)容更精彩,請(qǐng)繼續(xù)關(guān)注后續(xù)更新毫蚓,謝謝大家