Golang 語言怎麼編寫測試代碼?
**01 **
介紹
我們使用 Golang 語言開發的項目,怎麼保證邏輯正確和性能要求呢?也就是說我們如何測試我們的 Golang 代碼呢?在 Golang 語言中,可以使用標準庫 testing 包編寫單元測試和基準測試,使用 go test
命令執行單元測試和基準測試的代碼。本文我們介紹在 Golang 語言中怎麼編寫測試代碼。
**02 **
命名規範
在 Golang 語言中編寫測試代碼,需要遵循一些命名規範,包含文件名、包名、函數(方法)名和變量名。
文件名和包名
測試文件名以 _test.go
結尾,go test
工具可以遍歷以 _test.go
結尾的文件,執行測試函數。而 go build
和 go run
會忽略以 _test.go
結尾的文件,文件名開頭一般是被測試函數所在的文件名。
包名一般和被測試文件的包名相同,這樣即可以測試被測試文件的可導出函數和不可導出函數。
函數名和方法名
測試函數(方法)名必須以 Test、Benchmark 和 Example 開頭,並且必須是可導出函數。函數名一般是被測試函數名,首字母大寫。如果我們需要給同一個函數編寫多個測試函數,可以在函數名後接上測試函數的場景,例如:TestXxxxXxxx
。
變量名
測試函數(方法)的變量名,Golang 語言和 go test
工具沒有明確的約束,但是,社區針對輸出結果有一些規範供大家參考。在編寫單元測試代碼時,一般會得到一個實際輸出結果,和一個我們預期的輸出結果做對比。針對這兩個變量,社區的變量名規範是 got/want
或 expected/actual
。
**03 **
編寫測試代碼
單元測試
所謂單元測試,顧名思義就是對單元進行測試,一般進行測試的單元是一個最小的單元,在 Golang 語言中,最小的單元就是指一個函數或方法。
單元測試的函數,函數名以 Test
開頭,例如:TestXxx
。參數必須是 *testing.T
類型,可以使用該類型的方法記錄測試信息和測試狀態。例如,一般使用 Log
和 Logf
記錄測試信息,使用 Error
、Errorf
、Fatal
和 Fatalf
方法記錄測試狀態,該類型的更多方法可以閱讀官方文檔。
被測試函數:
func Sum(a, b int) int {
return a+b
}
測試函數:
func TestSum(t *testing.T) {
a, b := 1,2
rst := Sum(a, b)
if rst == 3 {
t.Logf("expected=%d, actual=%d", 3, rst)
} else {
// t.Errorf("expected=%d, actual=%d", 3, rst)
t.Fatalf("expected=%d, actual=%d", 3, rst)
}
t.Log("done")
}
閱讀上面這段代碼,是我們編寫的 Sum 函數的單元測試,給定 a, b 兩個變量作爲 Sum 函數的輸入參數,此外,我們還可以使用表格測試發,給定一組被測試函數的輸入參數,限於篇幅,本文不準備花費篇幅介紹。
使用 go test
命令執行以上單元測試的代碼:
go test
PASS
ok learn_go/lesson27 0.555s
go test
命令遍歷所有 _test.go
結尾的文件,執行文件中所有的測試函數。此外,go test
支持一些參數,例如,-v
輸出測試函數的運行詳情;-run
指定執行的測試函數;-count
指定執行次數。
此外,使用參數 --coverprofile
統計單元測試的覆蓋率。
go test --coverprofile=func.cover
PASS
coverage: 100.0% of statements
ok learn_go/lesson27 0.499s
閱讀上面的執行結果,可以發現我們編寫的單元測試覆蓋率爲 100%。
如果我們想要查看詳細的覆蓋率統計結果,我們可以執行以下命令生成 html
文件,使用瀏覽器打開生成的 html
文件,可以查看詳細的單元測試覆蓋率統計結果。
go tool cover -html=func.cover -o func_cover.html
運行以上命令,會生成一個名爲 func_cover.html
的文件,我們可以使用瀏覽器打開它,查看詳細的單元測試覆蓋率統計結果。
基準測試
在 Golang 語言中,可以使用基準測試查看代碼的性能。基準測試的函數名以 Benchmark
開頭,例如:BenchmarkXxx
。參數必須是 *testing.B
類型,函數體中 for 循環的條件,以 b.N
作爲循環次數,它是基準測試框架提供的,它在 Golang 運行時動態調整,通過多次測試,得到性能評估結果。
示例代碼:
func BenchmarkSum(b *testing.B) {
for i := 0; i < b.N; i++ {
Sum(1, 2)
}
}
我們可以使用 go test
工具執行以上基準測試的代碼,基準測試函數不會自動執行,必須使用參數 -bench
。
go test -bench=".*"
goos: darwin
goarch: amd64
pkg: learn_go/lesson27
cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
BenchmarkSum-16 1000000000 0.2325 ns/op
PASS
ok learn_go/lesson27 0.748s
閱讀上面的執行結果,我們主要介紹一下 BenchmarkXxx-n
這一行的意思。這一行共有三列,第一列 BenchmarkSum-16
分別代表基準測試的函數名和參與基準測試的 CPU 線程數,默認是 GOMAXPROCS 的值。第二列 1000000000
表示基準測試循環執行的次數。第三列 0.2325 ns/op
表示每次循環的平均執行耗時是 0.2325
納秒,該值越小,說明代碼性能越高。
除了 b.N
之外,還有幾個關於性能測試時間計數的方法,例如:b.ResetTimer()
、b.StopTimer()
和 b.StartTimer()
,我們可以根據我們的測試場景,靈活使用。
此外,go test
工具關於基準測試的參數,除了參數 -bench
之外,還有 -benchmem
統計內存分配;-cpu
指定參與執行基準測試的 CPU 線程數;-benchtime
指定測試時間和循環次數,其中值的單位爲 s
表示指定執行多少秒,單位爲 x
表示指定循環執行次數;-timeout
指定基準測試函數執行的超時時間。
**04 **
總結
本文我們介紹怎麼編寫測試代碼,包含單元測試和基準測試。特別需要注意的是一些命名規範。
養成編寫測試代碼的習慣,不僅可以降低代碼邏輯的錯誤率,而且在多人開發中,還可以提升聯調效率和提測通過率。
參考資料:
https://pkg.go.dev/testing
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/P4elvWrbA8qcDcGLBcy-0Q