golang分層測(cè)試之單元測(cè)試-testing使用

前言

  • 基本上每一種高級(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ī)范:
  1. 每個(gè)測(cè)試文件必須以 _test.go 結(jié)尾醋虏,并使用go test命令執(zhí)行測(cè)試模塊,否則golang無(wú)法識(shí)別出測(cè)試模塊
  2. 作為測(cè)試模塊文件哮翘,必須導(dǎo)入testing包
  3. 功能測(cè)試方法必須以 Test 開(kāi)頭颈嚼,一般是接被測(cè)方法的名字,如TestAdd饭寺,但不強(qiáng)制
  4. 測(cè)試用例會(huì)按照源代碼中寫(xiě)的順序依次執(zhí)行
  5. 測(cè)試方法TestXxx()的參數(shù)是testing.T阻课,用于收集記錄測(cè)試結(jié)果
  6. testing中的斷言需要自己編寫(xiě)叫挟,通過(guò)在方法中通過(guò)調(diào)用testing.TError, 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è)組合:
    1. 兩個(gè)正數(shù)相加
    2. 兩個(gè)負(fù)數(shù)相加
    3. 一正一負(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ù)更新毫蚓,謝謝大家
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末占键,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子元潘,更是在濱河造成了極大的恐慌畔乙,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翩概,死亡現(xiàn)場(chǎng)離奇詭異牲距,居然都是意外死亡返咱,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)牍鞠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)咖摹,“玉大人,你說(shuō)我怎么就攤上這事难述∮┣纾” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵胁后,是天一觀(guān)的道長(zhǎng)店读。 經(jīng)常有香客問(wèn)我,道長(zhǎng)攀芯,這世上最難降的妖魔是什么屯断? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮侣诺,結(jié)果婚禮上殖演,老公的妹妹穿的比我還像新娘。我一直安慰自己年鸳,他們只是感情好趴久,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著阻星,像睡著了一般朋鞍。 火紅的嫁衣襯著肌膚如雪已添。 梳的紋絲不亂的頭發(fā)上妥箕,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音更舞,去河邊找鬼畦幢。 笑死,一個(gè)胖子當(dāng)著我的面吹牛缆蝉,可吹牛的內(nèi)容都是我干的宇葱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼刊头,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼黍瞧!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起原杂,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤印颤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后穿肄,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體年局,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡际看,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了矢否。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仲闽。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖僵朗,靈堂內(nèi)的尸體忽然破棺而出赖欣,到底是詐尸還是另有隱情,我是刑警寧澤验庙,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布畏鼓,位于F島的核電站,受9級(jí)特大地震影響壶谒,放射性物質(zhì)發(fā)生泄漏云矫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一汗菜、第九天 我趴在偏房一處隱蔽的房頂上張望让禀。 院中可真熱鬧,春花似錦陨界、人聲如沸巡揍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)腮敌。三九已至,卻和暖如春俏扩,著一層夾襖步出監(jiān)牢的瞬間糜工,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工录淡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捌木,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓嫉戚,卻偏偏與公主長(zhǎng)得像刨裆,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子彬檀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355