Go語(yǔ)言工程實(shí)踐單元測(cè)試基準(zhǔn)測(cè)試示例詳解
背景
測(cè)試的出現(xiàn)是為了避免項(xiàng)目中出現(xiàn)重大事故
測(cè)試是避免事故的最后一道屏障
測(cè)試
單元測(cè)試的覆蓋率在一定程度上而言,決定了代碼的質(zhì)量
單元測(cè)試
通過(guò)測(cè)試單元的輸出與期望值進(jìn)行校對(duì)從而驗(yàn)證代碼的正確性,從而保證新舊代碼的互不影響與程序的正常運(yùn)行。
進(jìn)而單元測(cè)試較于編譯更易于在較短的周期內(nèi)發(fā)現(xiàn)和定位代碼中的錯(cuò)誤使損失最小化從而提升效率。所以寫(xiě)單元測(cè)試是很有必要的。
Golang單元測(cè)試對(duì)文件名和方法名,參數(shù)都有很嚴(yán)格的要求。
- 文件名必須以
xx_test.go
命名 - 方法必須是
Test[^a-z]
開(kāi)頭 - 方法參數(shù)必須
t *testing.T
- 初始化邏輯放到TestMain中
- 使用
go test
執(zhí)行單元測(cè)試
演示
通過(guò)第三方包assert演示單元測(cè)試
判斷函數(shù)測(cè)試值與期望值是否一致
import( "github.com/stretchr/testify/assert" "testing" ) func TestHelloTom(t *testing.T) { output := HelloTom() expectOutput := "Tom" assert.Equal(t, expectOutput, output) } func HelloTom() string { return "Tom" }
覆蓋率
覆蓋率出現(xiàn)的目的:
- 衡量代碼是否經(jīng)過(guò)了足夠的測(cè)試
- 評(píng)價(jià)項(xiàng)目的測(cè)試水準(zhǔn)
- 評(píng)估項(xiàng)目是否達(dá)到了高水準(zhǔn)測(cè)試等級(jí)
通過(guò)go test命令測(cè)試函數(shù)的覆蓋率
// judgment.go func JudgePassLine(score int16) bool { if score >= 60 { return true } else { return false } } // judgment_test.go func TestJudgePassLineTrue(t *testing.T) { isPass := JudgeePassLine(70) assert.Equal(t, true, isPass) } func TestJudgePassLineFalse(t *testing.T) { isPass := JudgeePassLine(50) assert.Equal(t, false, isPass) } /* 通過(guò)go test 命令測(cè)試覆蓋率 go test judgment_test.go judgment.go --cover */
一般覆蓋率:50%~60%
,較高覆蓋率:80%+
測(cè)試分支相互獨(dú)立、全面覆蓋
對(duì)于上述案例代碼而言
應(yīng)出現(xiàn)成績(jī)大于等于60 和小于60的測(cè)試用力
測(cè)試單元粒度足夠小,函數(shù)單一職責(zé)
依賴(lài)
- 冪等:重復(fù)運(yùn)行同一個(gè)case,結(jié)果與之前一致
- 穩(wěn)定:指單元測(cè)試相互隔離,可以獨(dú)立運(yùn)行
文件處理
當(dāng)測(cè)試文件被修改后,可能會(huì)導(dǎo)致測(cè)試失敗或錯(cuò)誤率增高
從而出現(xiàn)了Mock函數(shù)
func ReadFirstLine() string { open, err := os.Open("log") // 打開(kāi)一個(gè)文件 defer open.Close() if err != nil { return "" } scanner := bufio.NewScanner(open) // 對(duì)每行進(jìn)行遍歷 for scanner.Scan() { return scanner.Text() } return "" } func ProcessFirstLine() string { line := ReadFirstLine() destLine := strings.ReplaceAll(line, "11", "00") // 替換11為00 return destLine } func TestProcessFirstLine(t *testing.T) { // 執(zhí)行單元測(cè)試 firstLine := ProcessFirstLine() assert.Equal(t, "line00", firstLine) }
Mock
monkey: github.com/bouk/monkey 這是一個(gè)開(kāi)源的mock測(cè)試庫(kù),可以對(duì)method或者實(shí)例的方法進(jìn)行mock
Monkey Patch的作用域在Runtime, 運(yùn)行時(shí)通過(guò)Go的unsafe包能夠?qū)?nèi)存中函數(shù)的地址替換為運(yùn)行時(shí)函數(shù)的地址,將待打樁函數(shù)或方法的實(shí)現(xiàn)跳轉(zhuǎn)。
Mock函數(shù)不僅可以為一個(gè)函數(shù)打樁 也可以為一個(gè)方法打樁
// 用函數(shù)A去替換函數(shù)B,B就是原函數(shù),A就是打樁函數(shù) func Patch(target, replacement interface{}) *PatchGuard { // target就是原函數(shù),replacement就是打樁函數(shù) t := reflect.ValueOf(target) r := reflect.ValueOf(replacement) patchValue(t, r) return &PatchGuard{t, r} } func Unpatch(target interface{}) bool { // 保證了在測(cè)試結(jié)束之后需要把這個(gè)包卸載掉 return unpatchValue(reflect.ValueOf(target)) } func TestProcessFirstLineWithMock(t *testing.T) { monkey.Patch(ReadFirstLine, func() string { return "line110" }) defer monkey.Unpatch(ReadFirstLine) line := ProcessFirstLine() assert.Equal(t, "line000", line) } // 通過(guò)patch對(duì)ReadFirstLine進(jìn)行打樁mock,默認(rèn)返回line110,通過(guò)defer卸載mock // 這樣整個(gè)測(cè)試函數(shù)就擺脫了本地文件的束縛和依賴(lài)
基準(zhǔn)測(cè)試
基準(zhǔn)測(cè)試是指測(cè)試一段程序的性能及耗費(fèi)CPU的程度;
在實(shí)際的項(xiàng)目開(kāi)發(fā)中,經(jīng)常會(huì)遇到代碼性能瓶頸,為了定位問(wèn)題,經(jīng)常要對(duì)代碼做性能分;
這時(shí)就用到了基準(zhǔn)測(cè)試,其使用方法與單元測(cè)試類(lèi)似。
- 優(yōu)化代碼,需要對(duì)當(dāng)前代碼分析
- 內(nèi)置的測(cè)試框架提供了基準(zhǔn)測(cè)試的能力
小結(jié)
對(duì)于今日課程而言,我將其劃分成測(cè)試的重要性與分類(lèi)。 當(dāng)前課程余下部分為項(xiàng)目實(shí)戰(zhàn),該部分內(nèi)容選擇了放置于項(xiàng)目筆記。 如果筆記中有錯(cuò)誤的地方也希望掘友們可以及時(shí)的提出糾正,更多關(guān)于Go語(yǔ)言單元測(cè)試基準(zhǔn)測(cè)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于golang uint8、int8與byte的區(qū)別說(shuō)明
這篇文章主要介紹了基于golang uint8、int8與byte的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03go語(yǔ)言中的json與map相互轉(zhuǎn)換實(shí)現(xiàn)
本文主要介紹了go語(yǔ)言中的json與map相互轉(zhuǎn)換實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08Golang?依賴(lài)注入經(jīng)典解決方案uber/fx理論解析
這篇文章主要為大家介紹了Golang依賴(lài)注入經(jīng)典解決方案uber/fx理論解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05Go語(yǔ)言操作mysql數(shù)據(jù)庫(kù)簡(jiǎn)單例子
這篇文章主要介紹了Go語(yǔ)言操作mysql數(shù)據(jù)庫(kù)簡(jiǎn)單例子,本文包含插入數(shù)據(jù)和查詢(xún)代碼實(shí)例,需要的朋友可以參考下2014-10-10