中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

做網(wǎng)站上傳電子書最新的新聞 今天

做網(wǎng)站上傳電子書,最新的新聞 今天,萊西網(wǎng)站建設(shè),北京展臺設(shè)計制作文章目錄 引入一、單元測試基本介紹1.1 什么是單元測試?1.2 如何寫好單元測試1.3 單元測試的優(yōu)點(diǎn)1.4 單元測試的設(shè)計原則 二、Go語言測試2.1 Go單元測試概要2.2 Go單元測試基本規(guī)范2.3 一個簡單例子2.3.1 使用Goland 生成測試文件2.3.2 運(yùn)行單元測試2.3.3 完善測試用…

文章目錄

    • 引入
    • 一、單元測試基本介紹
      • 1.1 什么是單元測試?
      • 1.2 如何寫好單元測試
      • 1.3 單元測試的優(yōu)點(diǎn)
      • 1.4 單元測試的設(shè)計原則
    • 二、Go語言測試
      • 2.1 Go單元測試概要
      • 2.2 Go單元測試基本規(guī)范
      • 2.3 一個簡單例子
        • 2.3.1 使用Goland 生成測試文件
        • 2.3.2 運(yùn)行單元測試
        • 2.3.3 完善測試用例
        • 2.3.5 回歸測試
      • 2.4 Goland 直接運(yùn)行單元測試
      • 2.5 Go Test 命令參數(shù)
      • 2.6 運(yùn)行一個文件中的單個測試
      • 2.7 測試覆蓋率
      • 2.8 公共的幫助函數(shù)(helpers)
    • 三、`testing.T`的擁有的方法
    • 四、Table Driven 模式
      • 4.1 介紹
      • 4.2 Go 組織測試的方式
      • 4.3 舉個例子
      • 4.4 運(yùn)行 Table Driven 下的單個測試
    • 五、`testify/assert` 斷言工具包
      • 5.1 介紹
      • 5.2 安裝
      • 5.3 使用
    • 六、單元測試代碼模板
    • 七、參考文檔

引入

正常的業(yè)務(wù)開發(fā)之后的測試流程,都是先單元測試,后集成測試。

  • 單元測試:針對每一個方法進(jìn)行的測試,單獨(dú)驗(yàn)證每一個方法的正確性。
  • 集成測試:多個組件合并在一起的測試,驗(yàn)證各個方法、組件之間配合無誤。

所以一般項目都是開發(fā)人員要先搞單元測試,單元測試初步驗(yàn)證之后,再集成測試。

單元測試驗(yàn)證了各個方法的基本邏輯之后,集成測試就比較少問題了。

一、單元測試基本介紹

1.1 什么是單元測試?

單元測試(Unit Tests, UT) 是一個優(yōu)秀項目不可或缺的一部分,是對軟件中的最小可測試部分進(jìn)行檢查和驗(yàn)證。在面向?qū)ο缶幊讨?#xff0c;最小測試單元通常是一個方法或函數(shù)。單元測試通常由開發(fā)者編寫,用于驗(yàn)證代碼的一個很小的、很具體的功能是否正確。單元測試是自動化測試的一部分,可以頻繁地運(yùn)行以檢測代碼的更改是否引入了新的錯誤。

特別是在一些頻繁變動和多人合作開發(fā)的項目中尤為重要。你或多或少都會有因?yàn)樽约旱奶峤?#xff0c;導(dǎo)致應(yīng)用掛掉或服務(wù)宕機(jī)的經(jīng)歷。如果這個時候你的修改導(dǎo)致測試用例失敗,你再重新審視自己的修改,發(fā)現(xiàn)之前的修改還有一些特殊場景沒有包含,恭喜你減少了一次上庫失誤。也會有這樣的情況,項目很大,啟動環(huán)境很復(fù)雜,你優(yōu)化了一個函數(shù)的性能,或是添加了某個新的特性,如果部署在正式環(huán)境上之后再進(jìn)行測試,成本太高。對于這種場景,幾個小小的測試用例或許就能夠覆蓋大部分的測試場景。而且在開發(fā)過程中,效率最高的莫過于所見即所得了,單元測試也能夠幫助你做到這一點(diǎn),試想一下,假如你一口氣寫完一千行代碼,debug 的過程也不會輕松,如果在這個過程中,對于一些邏輯較為復(fù)雜的函數(shù),同時添加一些測試用例,即時確保正確性,最后集成的時候,會是另外一番體驗(yàn)。

1.2 如何寫好單元測試

首先,學(xué)會寫測試用例。比如如何測試單個函數(shù)/方法;比如如何做基準(zhǔn)測試;比如如何寫出簡潔精煉的測試代碼;再比如遇到數(shù)據(jù)庫訪問等的方法調(diào)用時,如何 mock。

然后,寫可測試的代碼。高內(nèi)聚,低耦合是軟件工程的原則,同樣,對測試而言,函數(shù)/方法寫法不同,測試難度也是不一樣的。職責(zé)單一,參數(shù)類型簡單,與其他函數(shù)耦合度低的函數(shù)往往更容易測試。我們經(jīng)常會說,“這種代碼沒法測試”,這種時候,就得思考函數(shù)的寫法可不可以改得更好一些。為了代碼可測試而重構(gòu)是值得的。

1.3 單元測試的優(yōu)點(diǎn)

單元測試講究的是快速測試、快速修復(fù)。

  • 測試該環(huán)節(jié)中的業(yè)務(wù)問題,比如說在寫測試的時候,發(fā)現(xiàn)業(yè)務(wù)流程設(shè)計得不合理。
  • 測試該環(huán)節(jié)中的技術(shù)問題,比如說nil之類的問題。

單元測試,從理論上來說,你不能依賴任何第三方組件。也就是說,你不能使用MySQL或者Redis

如圖,要快速啟動測試,快速發(fā)現(xiàn)BUG,快速修復(fù),快速重測。

1.4 單元測試的設(shè)計原則

  1. 每個測試單元必須完全獨(dú)立、能單獨(dú)運(yùn)行。
  2. 一個測試單元應(yīng)只關(guān)注一個功能函數(shù),證明它是正確的;
  3. 測試代碼要能夠快速執(zhí)行。
  4. 不能為了單元測試而修改已完成的代碼在編寫代碼后執(zhí)行針對本次的單元測試,并執(zhí)行之前的單元測試用例。
  5. 以保證你后來編寫的代碼不會破壞任何事情;
  6. 單元測試函數(shù)使用長的而且具有描述性的名字,例如都以test_開頭,然后加上具體的函數(shù)名字或者功能描述;例如:func_test.go。
  7. 測試代碼必須具有可讀性。

二、Go語言測試

2.1 Go單元測試概要

Go 語言的單元測試默認(rèn)采用官方自帶的測試框架,通過引入 testing 包以及 執(zhí)行 go test 命令來實(shí)現(xiàn)單元測試功能。

在源代碼包目錄內(nèi),所有以 _test.go 為后綴名的源文件會被 go test 認(rèn)定為單元測試的文件,這些單元測試的文件不會包含在 go build 的源代碼構(gòu)建中,而是單獨(dú)通過 go test 來編譯并執(zhí)行。

2.2 Go單元測試基本規(guī)范

Go 單元測試的基本規(guī)范如下:

  • 每個測試函數(shù)都必須導(dǎo)入 testing 包。測試函數(shù)的命名類似func TestName(t *testing.T),入?yún)⒈仨毷?*testing.T
  • 測試函數(shù)的函數(shù)名必須以大寫的 Test 開頭,后面緊跟的函數(shù)名,要么是大寫開關(guān),要么就是下劃線,比如 func TestName(t *testing.T) 或者 func Test_name(t *testing.T) 都是 ok 的, 但是 func Testname(t *testing.T)不會被檢測到
  • 通常情況下,需要將測試文件和源代碼放在同一個包內(nèi)。一般測試文件的命名,都是 {source_filename}_test.go,比如我們的源代碼文件是allen.go ,那么就會在 allen.go 的相同目錄下,再建立一個 allen_test.go 的單元測試文件去測試 allen.go 文件里的相關(guān)方法。

當(dāng)運(yùn)行 go test 命令時,go test 會遍歷所有的 *_test.go 中符合上述命名規(guī)則的函數(shù),然后生成一個臨時的 main 包用于調(diào)用相應(yīng)的測試函數(shù),然后構(gòu)建并運(yùn)行、報告測試結(jié)果,最后清理測試中生成的臨時文件。

2.3 一個簡單例子

2.3.1 使用Goland 生成測試文件

我們來創(chuàng)建一個示例,創(chuàng)建名為 add.go的文件

package mainfunc Add(a int, b int) int {return a + b
}
func Mul(a int, b int) int {return a * b
}

這里借助Goland給 ADD 函數(shù)生成并且編寫測試用例,只需要右鍵點(diǎn)擊函數(shù),轉(zhuǎn)到Generate -> Test for file function(生成函數(shù)測試)。

Goland 為我們生成了add_test.go單測文件

package mainimport "testing"func TestAdd(t *testing.T) {type args struct {a intb int}tests := []struct {name stringargs argswant int}{// TODO: Add test cases.}for _, tt := range tests {t.Run(tt.name, func(t *testing.T) {if got := Add(tt.args.a, tt.args.b); got != tt.want {t.Errorf("Add() = %v, want %v", got, tt.want)}})}
}
2.3.2 運(yùn)行單元測試

運(yùn)行 go test,該 package 下所有的測試用例都會被執(zhí)行。

go test .                                                
ok      gotest  1.060s

go test -v-v 參數(shù)會顯示每個用例的測試結(jié)果,另外 -cover 參數(shù)可以查看覆蓋率。

go test -v                                               
=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok      gotest  1.208s
2.3.3 完善測試用例

接著我們來完善上面的測試用例,代碼如下:

package mainimport "testing"func TestAdd(t *testing.T) {type args struct {a intb int}tests := []struct {name stringargs argswant int}{{name: "Adding positive numbers",args: args{a: 2, b: 3},want: 5,},{name: "Adding negative numbers",args: args{a: -2, b: -3},want: -5,},{name: "Adding positive and negative numbers",args: args{a: 2, b: -3},want: -1,},{name: "Adding zero",args: args{a: 2, b: 0},want: 2,},}for _, tt := range tests {t.Run(tt.name, func(t *testing.T) {if got := Add(tt.args.a, tt.args.b); got != tt.want {t.Errorf("Add() = %v, want %v", got, tt.want)}})}
}
2.3.5 回歸測試

我們修改了代碼之后僅僅執(zhí)行那些失敗的測試用例或新引入的測試用例是錯誤且危險的,正確的做法應(yīng)該是完整運(yùn)行所有的測試用例,保證不會因?yàn)樾薷拇a而引入新的問題。

go test -v
=== RUN   TestAdd
=== RUN   TestAdd/Adding_positive_numbers
=== RUN   TestAdd/Adding_negative_numbers
=== RUN   TestAdd/Adding_positive_and_negative_numbers
=== RUN   TestAdd/Adding_zero
--- PASS: TestAdd (0.00s)--- PASS: TestAdd/Adding_positive_numbers (0.00s)--- PASS: TestAdd/Adding_negative_numbers (0.00s)--- PASS: TestAdd/Adding_positive_and_negative_numbers (0.00s)--- PASS: TestAdd/Adding_zero (0.00s)
=== RUN   TestMul
=== RUN   TestMul/結(jié)果為0
=== RUN   TestMul/結(jié)果為-1
=== RUN   TestMul/結(jié)果為1
--- PASS: TestMul (0.00s)--- PASS: TestMul/結(jié)果為0 (0.00s)--- PASS: TestMul/結(jié)果為-1 (0.00s)--- PASS: TestMul/結(jié)果為1 (0.00s)
PASS
ok      gotest  0.912s

測試結(jié)果表明我們的單元測試全部通過。

2.4 Goland 直接運(yùn)行單元測試

如果你的測試方法簽名沒錯的話,就能看到這個綠色圖標(biāo),點(diǎn)擊就能看到很多選項。

最主要的是:

  • Run:運(yùn)行模式,直接運(yùn)行整個測試。
  • Debug:Debug模式,你可以打斷點(diǎn)。
  • Run xxx with Coverage:運(yùn)行并且輸出測試覆蓋率。
  • 其它Profile都是性能分析,很少用。

除非你要看測試覆蓋率,不然都用Debug。

2.5 Go Test 命令參數(shù)

go test 是 Go 語言的測試工具,你可以使用它來運(yùn)行 Go 程序的測試函數(shù)。

你可以在命令行中使用以下參數(shù)來調(diào)用 go test 命令:

  • -run:指定要運(yùn)行的測試函數(shù)的名稱的正則表達(dá)式。例如,使用 go test -run TestAdd 可以運(yùn)行名稱為 TestSum 的測試函數(shù)。
  • -bench:指定要運(yùn)行的基準(zhǔn)測試的名稱的正則表達(dá)式。例如,使用 go test -bench . 可以運(yùn)行所有基準(zhǔn)測試。
  • -count:指定要運(yùn)行測試函數(shù)或基準(zhǔn)測試的次數(shù)。例如,使用 go test -count 2 可以運(yùn)行測試函數(shù)或基準(zhǔn)測試兩次。
  • -v:輸出測試函數(shù)或基準(zhǔn)測試的詳細(xì)輸出。
  • -timeout:設(shè)置測試函數(shù)或基準(zhǔn)測試的超時時間。例如,使用 go test -timeout 1s 可以將超時時間設(shè)置為 1 秒。

以下是一個go Test命令表格:

參數(shù)說明
-bench regexp僅運(yùn)行與正則表達(dá)式匹配的基準(zhǔn)測試。默認(rèn)不運(yùn)行任何基準(zhǔn)測試。使用 -bench .-bench= 來運(yùn)行所有基準(zhǔn)測試。
-benchtime t運(yùn)行每個基準(zhǔn)測試足夠多的迭代,以達(dá)到指定的時間 t(例如 -benchtime 1h30s)。默認(rèn)為1秒(1s)。特殊語法 Nx 表示運(yùn)行基準(zhǔn)測試 N 次(例如 -benchtime 100x)。
-count n運(yùn)行每個測試、基準(zhǔn)測試和模糊測試 n 次(默認(rèn)為1次)。如果設(shè)置了 -cpu,則為每個 GOMAXPROCS 值運(yùn)行 n 次。示例總是運(yùn)行一次。-count 不適用于通過 -fuzz 匹配的模糊測試。
-cover啟用覆蓋率分析。
-covermode set,count,atomic設(shè)置覆蓋率分析的 mode。默認(rèn)為 “set”,如果啟用了 -race,則為 “atomic”。
-coverpkg pattern1,pattern2,pattern3對匹配模式的包應(yīng)用覆蓋率分析。默認(rèn)情況下,每個測試僅分析正在測試的包。
-cpu 1,2,4指定一系列的 GOMAXPROCS 值,在這些值上執(zhí)行測試、基準(zhǔn)測試或模糊測試。默認(rèn)為當(dāng)前的 GOMAXPROCS 值。-cpu 不適用于通過 -fuzz 匹配的模糊測試。
-failfast在第一個測試失敗后不啟動新的測試。
-fullpath在錯誤消息中顯示完整的文件名。
-fuzz regexp運(yùn)行與正則表達(dá)式匹配的模糊測試。當(dāng)指定時,命令行參數(shù)必須精確匹配主模塊中的一個包,并且正則表達(dá)式必須精確匹配該包中的一個模糊測試。
-fuzztime t在模糊測試期間運(yùn)行足夠多的模糊目標(biāo)迭代,以達(dá)到指定的時間 t(例如 -fuzztime 1h30s)。默認(rèn)為永遠(yuǎn)運(yùn)行。特殊語法 Nx 表示運(yùn)行模糊目標(biāo) N 次(例如 -fuzztime 1000x)。
-fuzzminimizetime t在每次最小化嘗試期間運(yùn)行足夠多的模糊目標(biāo)迭代,以達(dá)到指定的時間 t(例如 -fuzzminimizetime 30s)。默認(rèn)為60秒。特殊語法 Nx 表示運(yùn)行模糊目標(biāo) N 次(例如 -fuzzminimizetime 100x)。
-json以 JSON 格式記錄詳細(xì)輸出和測試結(jié)果。這以機(jī)器可讀的格式呈現(xiàn) -v 標(biāo)志的相同信息。
-list regexp列出與正則表達(dá)式匹配的測試、基準(zhǔn)測試、模糊測試或示例。不會運(yùn)行任何測試、基準(zhǔn)測試、模糊測試或示例。
-parallel n允許并行執(zhí)行調(diào)用 t.Parallel 的測試函數(shù),以及運(yùn)行種子語料庫時的模糊目標(biāo)。此標(biāo)志的值是同時運(yùn)行的最大測試數(shù)。
-run regexp僅運(yùn)行與正則表達(dá)式匹配的測試、示例和模糊測試。
-short告訴長時間運(yùn)行的測試縮短其運(yùn)行時間。默認(rèn)情況下是關(guān)閉的,但在 all.bash 中設(shè)置,以便在安裝 Go 樹時可以運(yùn)行健全性檢查,但不花費(fèi)時間運(yùn)行詳盡的測試。
-shuffle off,on,N隨機(jī)化測試和基準(zhǔn)測試的執(zhí)行順序。默認(rèn)情況下是關(guān)閉的。如果 -shuffle 設(shè)置為 on,則使用系統(tǒng)時鐘種子隨機(jī)化器。如果 -shuffle 設(shè)置為整數(shù) N,則 N 將用作種子值。在這兩種情況下,種子將報告以便復(fù)現(xiàn)。
-skip regexp僅運(yùn)行與正則表達(dá)式不匹配的測試、示例、模糊測試和基準(zhǔn)測試。
-timeout d如果測試二進(jìn)制文件運(yùn)行時間超過持續(xù)時間 d,則發(fā)生 panic。如果 d 為0,則禁用超時。默認(rèn)為10分鐘(10m)。
-v詳細(xì)輸出:記錄所有運(yùn)行的測試。即使測試成功,也打印所有來自 LogLogf 調(diào)用的文本。
-vet list配置在 “go test” 期間對 “go vet” 的調(diào)用,以使用由逗號分隔的 vet 檢查列表。如果列表為空,“go test” 使用被認(rèn)為總是值得解決的精選檢查列表運(yùn)行 “go vet”。如果列表為

更多可以參考 Go 語言的官方文檔或使用 go help test 命令查看幫助信息

2.6 運(yùn)行一個文件中的單個測試

如果只想運(yùn)行其中的一個用例,例如 TestAdd,可以用 -run 參數(shù)指定,該參數(shù)支持通配符 *,和部分正則表達(dá)式,例如 ^、$。

go test -run TestAdd -v
=== RUN   TestAdd
=== RUN   TestAdd/Adding_positive_numbers
=== RUN   TestAdd/Adding_negative_numbers
=== RUN   TestAdd/Adding_positive_and_negative_numbers
=== RUN   TestAdd/Adding_zero
--- PASS: TestAdd (0.00s)--- PASS: TestAdd/Adding_positive_numbers (0.00s)--- PASS: TestAdd/Adding_negative_numbers (0.00s)--- PASS: TestAdd/Adding_positive_and_negative_numbers (0.00s)--- PASS: TestAdd/Adding_zero (0.00s)
PASS
ok      gotest  1.008s

2.7 測試覆蓋率

測試覆蓋率是指代碼被測試套件覆蓋的百分比。通常我們使用的都是語句的覆蓋率,也就是在測試中至少被運(yùn)行一次的代碼占總代碼的比例。在公司內(nèi)部一般會要求測試覆蓋率達(dá)到80%左右。

Go提供內(nèi)置功能來檢查你的代碼覆蓋率,即使用go test -cover來查看測試覆蓋率。

go test -cover
PASS
coverage: 100.0% of statements
ok      gotest  1.381s

還可以使用 -coverprofile 標(biāo)志將覆蓋率數(shù)據(jù)輸出到一個文件中,然后使用 go tool cover 命令來查看更詳細(xì)的覆蓋率報告。

2.8 公共的幫助函數(shù)(helpers)

對一些重復(fù)的邏輯,抽取出來作為公共的幫助函數(shù)(helpers),可以增加測試代碼的可讀性和可維護(hù)性。 借助幫助函數(shù),可以讓測試用例的主邏輯看起來更清晰。

例如,我們可以將創(chuàng)建多次使用的邏輯抽取出來:

type addCase struct{ A, B, want int }func createAddTestCase(t *testing.T, c *addCase) {// t.Helper()if ans := Add(c.A, c.B); ans != c.want {t.Fatalf("%d * %d expected %d, but %d got",c.A, c.B, c.want, ans)}}func TestAdd2(t *testing.T) {createAddTestCase(t, &addCase{1, 1, 2})createAddTestCase(t, &addCase{2, -3, -1})createAddTestCase(t, &addCase{0, -1, 0}) // wrong case
}

在這里,我們故意創(chuàng)建了一個錯誤的測試用例,運(yùn)行 go test,用例失敗,會報告錯誤發(fā)生的文件和行號信息:

go test
--- FAIL: TestAdd2 (0.00s)add_test.go:109: 0 * -1 expected 0, but -1 got
FAIL
exit status 1
FAIL    gotest  1.090s

可以看到,錯誤發(fā)生在第11行,也就是幫助函數(shù) createAddTestCase 內(nèi)部。116, 117, 118行都調(diào)用了該方法,我們第一時間并不能夠確定是哪一行發(fā)生了錯誤。有些幫助函數(shù)還可能在不同的函數(shù)中被調(diào)用,報錯信息都在同一處,不方便問題定位。因此,Go 語言在 1.9 版本中引入了 t.Helper(),用于標(biāo)注該函數(shù)是幫助函數(shù),報錯時將輸出幫助函數(shù)調(diào)用者的信息,而不是幫助函數(shù)的內(nèi)部信息。

修改 createAddTestCaseV1,調(diào)用 t.Helper()

type addCaseV1 struct {name stringA, B intwant int
}func createAddTestCaseV1(c *addCaseV1, t *testing.T) {t.Helper()t.Run(c.name, func(t *testing.T) {if ans := Add(c.A, c.B); ans != c.want {t.Fatalf("%s: %d + %d expected %d, but %d got",c.name, c.A, c.B, c.want, ans)}})
}func TestAddV1(t *testing.T) {createAddTestCaseV1(&addCaseV1{"case 1", 1, 1, 2}, t)createAddTestCaseV1(&addCaseV1{"case 2", 2, -3, -1}, t)createAddTestCaseV1(&addCaseV1{"case 3", 0, -1, 0}, t)
}

運(yùn)行 go test,報錯信息如下,可以非常清晰地知道,錯誤發(fā)生在第 131 行。

go test
--- FAIL: TestAddV1 (0.00s)--- FAIL: TestAddV1/case_3 (0.00s)add_test.go:131: case 3: 0 + -1 expected 0, but -1 got
FAIL
exit status 1
FAIL    gotest  0.434s

關(guān)于 helper 函數(shù)的 2 個建議:

  • 不要返回錯誤, 幫助函數(shù)內(nèi)部直接使用 t.Errort.Fatal 即可,在用例主邏輯中不會因?yàn)樘嗟腻e誤處理代碼,影響可讀性。
  • 調(diào)用 t.Helper() 讓報錯信息更準(zhǔn)確,有助于定位。

當(dāng)然,如果你是用Goland 編輯器的話,可以不使用t.Helper(),自動會幫你打印出錯誤詳細(xì)信息

三、testing.T的擁有的方法

以下是提供的 *testing.T 類型的方法及其用途的注釋:

// T 是 Go 語言測試框架中的一個結(jié)構(gòu)體類型,它提供了用于編寫測試的方法。
// 它通常通過測試函數(shù)的參數(shù)傳遞給測試函數(shù)。// Cleanup 注冊一個函數(shù),該函數(shù)將在測試結(jié)束時執(zhí)行,用于清理測試過程中創(chuàng)建的資源。
func (c *T) Cleanup(func())// Error 記錄一個錯誤信息,但不會立即停止測試的執(zhí)行。
func (c *T) Error(args ...interface{})// Errorf 根據(jù) format 和 args 記錄一個格式化的錯誤信息,但不會立即停止測試的執(zhí)行。
func (c *T) Errorf(format string, args ...interface{})// Fail 標(biāo)記測試函數(shù)為失敗,但不會停止當(dāng)前測試的執(zhí)行。
func (c *T) Fail()// FailNow 標(biāo)記測試函數(shù)為失敗,并立即停止當(dāng)前測試的執(zhí)行。
func (c *T) FailNow()// Failed 檢查測試是否失敗。
func (c *T) Failed() bool// Fatal 記錄一個錯誤信息,并立即停止測試的執(zhí)行。
func (c *T) Fatal(args ...interface{})// Fatalf 記錄一個格式化的錯誤信息,并立即停止測試的執(zhí)行。
func (c *T) Fatalf(format string, args ...interface{})// Helper 標(biāo)記當(dāng)前函數(shù)為輔助函數(shù),當(dāng)測試失敗時,輔助函數(shù)的文件名和行號將不會顯示在錯誤消息中。
func (c *T) Helper()// Log 記錄一些信息,這些信息只有在啟用詳細(xì)日志(-v標(biāo)志)時才會顯示。
func (c *T) Log(args ...interface{})// Logf 記錄一些格式化的信息,這些信息只有在啟用詳細(xì)日志(-v標(biāo)志)時才會顯示。
func (c *T) Logf(format string, args ...interface{})// Name 返回當(dāng)前測試或基準(zhǔn)測試的名稱。
func (c *T) Name() string// Skip 標(biāo)記測試為跳過,并記錄一個錯誤信息。
func (c *T) Skip(args ...interface{})// SkipNow 標(biāo)記測試為跳過,并立即停止當(dāng)前測試的執(zhí)行。
func (c *T) SkipNow()// Skipf 標(biāo)記測試為跳過,并記錄一個格式化的錯誤信息。
func (c *T) Skipf(format string, args ...interface{})// Skipped 檢查測試是否被跳過。
func (c *T) Skipped() bool// TempDir 返回一個臨時目錄的路徑,該目錄在測試結(jié)束時會被自動刪除。
func (c *T) TempDir() string

四、Table Driven 模式

4.1 介紹

Table Driven 模式是一種軟件設(shè)計模式,它通過將測試數(shù)據(jù)存儲在一個表格(通常是結(jié)構(gòu)化的數(shù)據(jù)結(jié)構(gòu),如數(shù)組、切片、映射或結(jié)構(gòu)體)中,然后在一個單獨(dú)的函數(shù)或方法中遍歷這個表格來執(zhí)行測試。這種模式使得測試代碼更加模塊化、可讀性和可維護(hù)性更高。

在 Go 語言中,Table Driven 模式通常通過定義一個結(jié)構(gòu)體來組織測試數(shù)據(jù),然后使用一個循環(huán)來遍歷這個結(jié)構(gòu)體,為每個測試用例執(zhí)行相同的測試邏輯。這種方法可以很容易地添加新的測試用例,并且可以使測試代碼更加簡潔和易于維護(hù)。

4.2 Go 組織測試的方式

Go里面,慣常的組織測試的方式,都是用Table Driven。

Table Driven的形式如下圖。主要分成三個部分:

  • 測試用例的定義:即每一個測試用例需要有什么。
  • 具體的測試用例:你設(shè)計的每一個測試用例都在這里。
  • 執(zhí)行測試用例:這里面還包括了對測試結(jié)果進(jìn)行斷言。

注意,你要優(yōu)先使用Table Driven,但是不用強(qiáng)求。

你把測試用例定義看做是列名,每一個測試用例就是一行數(shù)據(jù),就能理解Table Driven這個含義了。

4.3 舉個例子

func TestMul(t *testing.T) {type args struct {a intb int}tests := []struct {name stringargs argswant int}{{name: "結(jié)果為0",args: args{a: 2, b: 0},want: 0,},{name: "結(jié)果為-1",args: args{a: -1, b: 1},want: -1,},{name: "結(jié)果為1",args: args{a: -1, b: -1},want: 1,},}for _, tt := range tests {t.Run(tt.name, func(t *testing.T) {if got := Mul(tt.args.a, tt.args.b); got != tt.want {t.Errorf("Mul() = %v, want %v", got, tt.want)}})}
}

4.4 運(yùn)行 Table Driven 下的單個測試

當(dāng)你使用前面 Table Driven 的模式時,可以單個運(yùn)行測試用例。

五、testify/assert 斷言工具包

5.1 介紹

testify/assert 是一個流行的Go語言斷言庫,它提供了一組豐富的斷言函數(shù),用于簡化測試代碼的編寫。這個庫提供了一種更聲明式的方式來編寫測試,使得測試意圖更加明確,代碼更加簡潔。

使用 testify/assert 時,您不再需要編寫大量的 if 語句和 Error 方法調(diào)用來檢查條件和記錄錯誤。相反,您可以使用像 assert.Equalassert.Nil、assert.True 這樣的斷言函數(shù)來驗(yàn)證測試的期望結(jié)果。

5.2 安裝

go get github.com/stretchr/testify

5.3 使用

斷言包提供了一些有用的方法,可以幫助您在Go語言中編寫更好的測試代碼。

  • 打印友好、易于閱讀的失敗描述
  • 允許編寫可讀性強(qiáng)的代碼
  • 可以為每個斷言添加可選的注釋信息
    看看它的實(shí)際應(yīng)用:
package yours
import ("testing""github.com/stretchr/testify/assert"
)
func TestSomething(t *testing.T) {// 斷言相等assert.Equal(t, 123, 123, "它們應(yīng)該相等")// 斷言不等assert.NotEqual(t, 123, 456, "它們不應(yīng)該相等")// 斷言為nil(適用于錯誤處理)assert.Nil(t, object)// 斷言不為nil(當(dāng)你期望得到某個結(jié)果時使用)if assert.NotNil(t, object) {// 現(xiàn)在我們知道object不是nil,我們可以安全地進(jìn)行// 進(jìn)一步的斷言而不會引起任何錯誤assert.Equal(t, "Something", object.Value)}
}

每個斷言函數(shù)都接受 testing.T 對象作為第一個參數(shù)。這就是它如何通過正常的Go測試能力輸出錯誤信息的方式。

每個斷言函數(shù)都返回一個布爾值,指示斷言是否成功。這對于在特定條件下繼續(xù)進(jìn)行進(jìn)一步的斷言非常有用。

當(dāng)我們有多個斷言語句時,還可以使用assert := assert.New(t)創(chuàng)建一個assert對象,它擁有前面所有的斷言方法,只是不需要再傳入Testing.T參數(shù)了。

package yours
import ("testing""github.com/stretchr/testify/assert"
)
func TestSomething(t *testing.T) {assert := assert.New(t)// 斷言相等assert.Equal(123, 123, "它們應(yīng)該相等")// 斷言不等assert.NotEqual(123, 456, "它們不應(yīng)該相等")// 斷言為nil(適用于錯誤處理)assert.Nil(object)// 斷言不為nil(當(dāng)你期望得到某個結(jié)果時使用)if assert.NotNil(object) {// 現(xiàn)在我們知道object不是nil,我們可以安全地進(jìn)行// 進(jìn)一步的斷言而不會引起任何錯誤assert.Equal("Something", object.Value)}
}

在上面的示例中,assert.New(t) 創(chuàng)建了一個新的 assert 實(shí)例,然后您可以使用這個實(shí)例的方法來進(jìn)行斷言。如果斷言失敗,testify/assert 會自動標(biāo)記測試為失敗,并記錄一個詳細(xì)的錯誤消息。

六、單元測試代碼模板

func Test_Function(t *testing.T) {testCases := []struct {name string //測試用例的名稱args any    //測試用例的輸入?yún)?shù)want string //期望的返回值}{// 測試用例,測試用例表格{},{},}for _, tc := range testCases {t.Run(tc.name, func(t *testing.T) {//具體的測試代碼})}
}

七、參考文檔

  • Go Test 單元測試簡明教程
  • Go單元測試入門
http://www.risenshineclean.com/news/58102.html

相關(guān)文章:

  • 做啥網(wǎng)站長春網(wǎng)站優(yōu)化頁面
  • wordpress自定義提醒用法百度搜索怎么優(yōu)化
  • 醫(yī)院網(wǎng)站開發(fā)違法嗎小程序免費(fèi)制作平臺
  • php手機(jī)網(wǎng)站開發(fā)龍崗seo網(wǎng)絡(luò)推廣
  • 九江疫情最新情況seo關(guān)鍵詞優(yōu)化系統(tǒng)
  • 手機(jī)端訪問 php網(wǎng)站成都專業(yè)的整站優(yōu)化
  • 深圳一百訊網(wǎng)站建設(shè)山東百度推廣總代理
  • 洞口網(wǎng)站開發(fā)公司系統(tǒng)優(yōu)化大師官方下載
  • java開源代碼網(wǎng)站seo優(yōu)
  • 做商城類的網(wǎng)站需要做些什么線下推廣渠道有哪些方式
  • 萊蕪在線論壇萊蕪話題王作泉抖音seo關(guān)鍵詞優(yōu)化
  • 網(wǎng)站開發(fā)api和微端互聯(lián)網(wǎng)營銷師培訓(xùn)教程
  • 主題營銷活動創(chuàng)意網(wǎng)站收錄優(yōu)化
  • 電子商務(wù)網(wǎng)站建設(shè)也管理高端網(wǎng)站建設(shè)企業(yè)
  • 云南網(wǎng)站建設(shè)網(wǎng)絡(luò)推廣合作協(xié)議范本
  • 國內(nèi)做的較好的網(wǎng)站制作網(wǎng)站公司
  • 西安專業(yè)做網(wǎng)站大概需要多少錢
  • 企健網(wǎng)網(wǎng)址搜索引擎優(yōu)化的簡稱
  • 長沙營銷型網(wǎng)站建設(shè)如何營銷推廣
  • 梅河口城鄉(xiāng)建設(shè)網(wǎng)站seo蜘蛛屯
  • 專業(yè)網(wǎng)站開發(fā)服務(wù)線上推廣宣傳方式有哪些
  • 做3d動畫網(wǎng)站seo的主要工作是什么
  • 做二手房又做網(wǎng)站的如何制作一個網(wǎng)頁
  • 正規(guī)網(wǎng)站模板設(shè)計百度指數(shù)數(shù)據(jù)分析
  • wordpress 快訊功能seo免費(fèi)自學(xué)的網(wǎng)站
  • 膠州建設(shè)信息網(wǎng)站百度搜索app免費(fèi)下載
  • 龍巖紀(jì)檢委網(wǎng)站中國制造網(wǎng)網(wǎng)站類型
  • 網(wǎng)站的域名分為哪些網(wǎng)頁在線生成
  • 網(wǎng)站上傳后優(yōu)化大師apk
  • 溫州網(wǎng)站建設(shè)風(fēng)格網(wǎng)絡(luò)熱詞英語