GO程式設計(打卡)-Task12: 單元測試
阿新 • • 發佈:2020-12-24
目錄
單元測試
go test 工具
包目錄內,所有以_test.go為字尾名的原始碼檔案都是go test測試的一部分,不會被go build編譯到最終的可執行檔案中
單元測試函式 函式名字首為Test 測試程式的一些邏輯行為是否正確
基準測試函式 函式名字首為Benchmark 測試函式的效能
示例函式 函式名字首為Example 為文件提供示例文件
測試框架
testing
測試命令go test xxx
測試檔案xxx_test.go
測試函式
-
格式
每個測試函式必須匯入
testing
包, 引數t
用於報告測試失敗和附加的日誌資訊func TestName(t *testing.T){ //... }
-
示例
// split/split.go package split import "strings" func Split(s, sep string) (result []string) { i := strings.Index(s, sep) for i > -1 { result = append(result, s[:i]) s = s[i+1:] // s = s[i+len(sep):] // 這裡使用len(sep)獲取sep的長度 i = strings.Index(s, sep) } result = append(result, s) return }
// split/split_test.go package split import ( "reflect" "testing" ) func TestSplit(t *testing.T) { // 測試函式名必須以Test開頭,必須接收一個*testing.T型別引數 got := Split("a:b:c", ":") // 程式輸出的結果 want := []string{"a", "b", "c"} // 期望的結果 if !reflect.DeepEqual(want, got) { // 因為slice不能比較直接,藉助反射包中的方法比較 t.Errorf("excepted:%v, got:%v", want, got) // 測試失敗輸出錯誤提示 } }
在split路徑下執行
go test
新增測試用例
func TestMoreSplit(t *testing.T) { got := Split("abcd", "bc") want := []string{"a", "d"} if !reflect.DeepEqual(want, got) { t.Errorf("excepted:%v, got:%v", want, got) } }
執行指定測試用例
修改split函式中的程式碼
s = s[i+1:]
為s = s[i+len(sep):]
-
測試組 新增更多測試用例
func TestSplit(t *testing.T) { // 定義一個測試用例型別 type test struct { input string sep string want []string } // 定義一個儲存測試用例的切片 tests := []test{ {input: "a:b:c", sep: ":", want: []string{"a", "b", "c"}}, {input: "a:b:c", sep: ",", want: []string{"a:b:c"}}, {input: "abcd", sep: "bc", want: []string{"a", "d"}}, {input: "沙河有沙又有河", sep: "沙", want: []string{"河有", "又有河"}}, } // 遍歷切片,逐一執行測試用例 for _, tc := range tests { got := Split(tc.input, tc.sep) if !reflect.DeepEqual(got, tc.want) { t.Errorf("excepted:%#v, got:%#v", tc.want, got) } } }
-
子測試 便於定位測試用例是否通過
func TestSplit(t *testing.T) { type test struct { // 定義test結構體 input string sep string want []string } tests := map[string]test{ // 測試用例使用map儲存 "simple": {input: "a:b:c", sep: ":", want: []string{"a", "b", "c"}}, "wrong sep": {input: "a:b:c", sep: ",", want: []string{"a:b:c"}}, "more sep": {input: "abcd", sep: "bc", want: []string{"a", "d"}}, "leading sep": {input: "沙河有沙又有河", sep: "沙", want: []string{"河有", "又有河"}}, } for name, tc := range tests { t.Run(name, func(t *testing.T) { // 使用t.Run()執行子測試 got := Split(tc.input, tc.sep) if !reflect.DeepEqual(got, tc.want) { t.Errorf("excepted:%#v, got:%#v", tc.want, got) } }) } }
執行指定子測試用例
-
測試覆蓋率
測試覆蓋率是你的程式碼被測試套件覆蓋的百分比
go test -cover
檢視覆蓋率
基準函式
-
格式
基準測試必須要執行
b.N
次func BenchmarkName(b *testing.B){ // ... }
-
示例
func BenchmarkSplit(b *testing.B) { for i := 0; i < b.N; i++ { Split("沙河有沙又有河", "沙") } }
go test -bench=Split
-benchmem
引數,來獲得記憶體分配的統計資料
示例函式
-
格式
基準測試必須要執行
b.N
次func ExampleName(b *testing.B){ // ... }
-
示例
func ExampleSplit() { fmt.Println(Split("a:b:c", ":")) fmt.Println(Split("沙河有沙又有河", "沙")) // Output: // [a b c] // [ 河有 又有河] }
參考
https://github.com/datawhalechina/go-talent/blob/master/10.反射機制.md
https://www.cnblogs.com/nickchen121/p/11517443.html