首先所有的包都應(yīng)該有一定的必要文檔,然后同樣重要的是對包的測試。
在第 3 章中提到了 Go 的測試工具 gotest, 我們已經(jīng)在 9.8 節(jié)中使用過了。這里我們會用更多的例子進(jìn)行詳細(xì)說明。
名為 testing 的包被專門用來進(jìn)行自動(dòng)化測試,日志和錯(cuò)誤報(bào)告。并且還包含一些基準(zhǔn)測試函數(shù)的功能。
備注:gotest 是 Unix bash 腳本,所以在 Windows 下你需要配置 MINGW 環(huán)境(參見 2.5 節(jié));在 Windows 環(huán)境下把所有的 pkg/linux_amd64 替換成 pkg/windows。
對一個(gè)包做(單元)測試,需要寫一些可以頻繁(每次更新后)執(zhí)行的小塊測試單元來檢查代碼的正確性。于是我們必須寫一些 Go 源文件來測試代碼。測試程序必須屬于被測試的包,并且文件名滿足這種形式 *_test.go,所以測試代碼和包中的業(yè)務(wù)代碼是分開的。
_test 程序不會被普通的 Go 編譯器編譯,所以當(dāng)放應(yīng)用部署到生產(chǎn)環(huán)境時(shí)它們不會被部署;只有 gotest 會編譯所有的程序:普通程序和測試程序。
測試文件中必須導(dǎo)入 "testing" 包,并寫一些名字以 TestZzz 打頭的全局函數(shù),這里的 Zzz 是被測試函數(shù)的字母描述,如 TestFmtInterface,TestPayEmployees 等。
測試函數(shù)必須有這種形式的頭部:
func TestAbcde(t *testing.T)
T 是傳給測試函數(shù)的結(jié)構(gòu)類型,用來管理測試狀態(tài),支持格式化測試日志,如 t.Log,t.Error,t.ErrorF 等。在函數(shù)的結(jié)尾把輸出跟想要的結(jié)果對比,如果不等就打印一個(gè)錯(cuò)誤。成功的測試則直接返回。
用下面這些函數(shù)來通知測試失?。?/p>
1)func (t *T) Fail()
標(biāo)記測試函數(shù)為失敗,然后繼續(xù)執(zhí)行(剩下的測試)。
2)func (t *T) FailNow()
標(biāo)記測試函數(shù)為失敗并中止執(zhí)行;文件中別的測試也被略過,繼續(xù)執(zhí)行下一個(gè)文件。
3)func (t *T) Log(args ...interface{})
args 被用默認(rèn)的格式格式化并打印到錯(cuò)誤日志中。
4)func (t *T) Fatal(args ...interface{})
結(jié)合 先執(zhí)行 3),然后執(zhí)行 2)的效果。
運(yùn)行 go test 來編譯測試程序,并執(zhí)行程序中所有的 TestZZZ 函數(shù)。如果所有的測試都通過會打印出 PASS。
gotest 可以接收一個(gè)或多個(gè)函數(shù)程序作為參數(shù),并指定一些選項(xiàng)。
結(jié)合 --chatty 或 -v 選項(xiàng),每個(gè)執(zhí)行的測試函數(shù)以及測試狀態(tài)會被打印。
例如:
go test fmt_test.go --chatty
=== RUN fmt.TestFlagParser
--- PASS: fmt.TestFlagParser
=== RUN fmt.TestArrayPrinter
--- PASS: fmt.TestArrayPrinter
...
testing 包中有一些類型和函數(shù)可以用來做簡單的基準(zhǔn)測試;測試代碼中必須包含以 BenchmarkZzz 打頭的函數(shù)并接收一個(gè) *testing.B 類型的參數(shù),比如:
func BenchmarkReverse(b *testing.B) {
...
}
命令 go test –test.bench=.* 會運(yùn)行所有的基準(zhǔn)測試函數(shù);代碼中的函數(shù)會被調(diào)用 N 次(N是非常大的數(shù),如 N = 1000000),并展示 N 的值和函數(shù)執(zhí)行的平均時(shí)間,單位為 ns(納秒,ns/op)。如果是用 testing.Benchmark 調(diào)用這些函數(shù),直接運(yùn)行程序即可。
具體可以參見 14.16 節(jié)中用 goroutines 運(yùn)行基準(zhǔn)測試的例子以及練習(xí) 13.4:string_reverse_test.go