Go的自动化测试
自動化測試,是在預設條件下運行系統或應用程序,評估運行結果,預先條件包括正常條件和異常條件。Go本身提供了一套輕量級的測試框架,相對低級,但不過還是有效的。它依賴一個go test測試命令,和一組按照約定方式編寫的測試函數,符合規則的測試代碼會在運行測試時被自動識別并執行。但是這些文件是不會被普通的Go編譯器編譯,所以當將應用部署到生產環境時,它們不會被部署。
測試規則
文件命名與放置規則
在Go中,凡是以_或者.符號作為文件名的首字母時,該文件都會被構建工具忽略掉。以_test.go結尾的測試文件,將會被編譯為單獨的包,然后將其鏈接到主測試二進制文件。
go工具還會忽略名為testdata的目錄,使其可以保存測試所需的輔助數據。
測試函數命名規則
測試文件包括三種函數:測試函數、基準測試函數和例子函數。測試函數用于測試程序的一些邏輯行為是否正確的函數,在命名時應該以Test為前綴,例如func TestAbcde(t *testing.T)。基準測試用于衡量一些函數的性能,是以Benchmark為函數名前綴的函數,例如func BenchmarkAbcde(b *testing.B)。例子函數用來說明函數(變量,常量等)如何使用,以Example為函數名前綴的函數,例如:
func ExamplePrintln(){Println("The output of\nthis example.")//Output: The output of//this example. }- 1
- 2
- 3
- 4
- 5
go test命令
go test命令會自動測試導入路徑命名的包并緩存測試結果,根據測試的結果和預先設定的是否匹配,會返回PASS或FAIL。它的用法:go test [build/test參數] [包名] [build/test參數 &測試編譯參數],它有兩種不同的模式:本地目錄模式和包列表模式。僅在包列表模式下,go test會緩存成功的包測試結果以避免不必要的重復運行已經通過的測試。當測試的結果可以從緩存中恢復,go test將會重新顯示以前的輸出而不是再次運行測試二進制文件。例如你需要對math目錄下的a_test.go文件和b_test.go文件做基準測試,那么就可以執行go test -bench . math a_test.go b_test.go
本地目錄模式
這種模式是在沒有包參數的情況下,調用go test時發生,例如:go test或go test -v。在此模式下,go test會編譯當前目錄中的包和測試文件,然后運行生成的二進制文件。這種模式下,緩存是被禁用的。測試完成后,go test會打印結果摘要,逐行顯示測試狀態,包名稱和已用的時間。
包列表模式
在調用go test時傳入顯式包參數,例如:go test math,go test ./...,或者go test .等。在此模式下,go test會編譯和測試命令行中列出的每一個包。如果一個包測試通過,go test只打印成功摘要,但如果測試失敗,則會打印完整的信息。如果你傳入參數-bench或-v標志,那么go test將會打印完整的輸出,即使是通過測試的包。第一個參數是當有基準測試函數時使用,第二種就是平常的測試函數就行。
顯式禁用緩存的慣用方法是使用-count=1
go test參數
-bench [正則表達式]:僅運行與正則表達式匹配的基準,默認情況下,不運行基準測試。如果要運行所有的基準測試函數,使用-bench .或者-bench=.。
-benchtime [時間]:表示運行多長時間的基準測試,默認值為1秒。例如:-benchtime 1h30s。
-count n:運行每個測試和基準多少次,默認為1,如果設置了-cpu,則為每個GOMAXPROCS運行n次,例子函數總是運行一次。
-cover:啟用覆蓋率分析,由于覆蓋率通過在編譯之前注釋源代碼來工作,因此啟用覆蓋率的編譯和測試失敗,可能會出現報告與原始文件行號不對應的情況。
-covermode set,count,atomic:為正在測試的包設置覆蓋率分析模式,除非啟用-race,否則默認為set,在這種情況下它是原子的。
- set,布爾值,表示這句聲明是否有效
- count,int類型,這句聲明運行多少次
- atomic,int類型,在多線程測試中使用,原子操作。
-coverpkg pattern1,pattern2,pattern3:將每個測試中的覆蓋率分析應用于模式匹配的包,默認情況下,每個測試僅分析正在測試的包。
-cpu 1,2,4:指定應為其執行測試或基準測試的GOMAXPROCS的值的列表,默認值是GOMAXPROCS的當前值。
-failfast:表示在第一次測試失敗后不要開始新的測試。
-list [正則表達式]:只是列出與正則表達式匹配的測試、基準測試或例子,不會運行任何測試。
-parallel n:表示運行的最大測試數,默認情況下,它設置為GOMAXPROCS的值。
-run [正則表達式]:僅僅運行與正則表達式匹配的那些測試和例子,匹配時可能父項也會運行,例如:-run = X/Y,匹配運行所有與X匹配的測試的結果,即使沒有匹配到子測試。
-timeout [時間]:如果測試文件運行的時間超過設置的時間,就會出現panic。如果設置的時間為0,則表示timeout不可用。默認是10分鐘。
-v:會打印詳細的測試結果,即使是在測試成功的情況。
testing包
提供有關Go自動化測試的支持,它與go test命令一起使用。
// TB 是類型T和B的接口. type TB interface {Error(args ...interface{}) //Fail+LogErrorf(format string, args ...interface{})Fail() //標記失敗,但繼續執行該測試函數FailNow() //失敗,立即停止當前測試函數Failed() boolFatal(args ...interface{}) //FailNow+LogFatalf(format string, args ...interface{})Log(args ...interface{}) //輸出信息,僅在失敗或-v參數時輸出Logf(format string, args ...interface{})Name() stringSkip(args ...interface{})SkipNow() //跳過當前測試函數Skipf(format string, args ...interface{})Skipped() boolHelper()private() }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
例子
1.在你的$GOPATH/src目錄下,創建一個目錄,例如:mytest文件夾。
2.創建一個main文件,寫入業務代碼。例如下面將0加到n的函數進行測試:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
3.創建測試文件,文件名以_test.go結尾,例如:main_test.go。
package main import ("testing" ) func TestAddNum(t *testing.T) {if addNum(100) != 5050 {t.Fatal("addNum error!")} }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
4.在命令行里,直接輸入go test,運行當前包的所有測試文件。或者運行go test mytest,只測試mytest包的測試文件。
本地目錄方式運行時的返回結果:
- 1
- 2
包列表模式運行的返回結果:ok mytest 0.138s。
5.在main.go文件中,添加基準測試函數。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
6.運行基準測試,go test -bench .,默認情況下,go test不會執行性能測試函數。性能測試需要運行足夠多的次數才能計算單次執行平均時間。
goos: windows goarch: amd64 pkg: mytest BenchmarkAddNum-4 10000000 187 ns/op PASS ok mytest 2.522s- 1
- 2
- 3
- 4
- 5
- 6
報告顯示執行addNum函數花費的平均時間是2.522s,執行了10000000次,每282ns的速度運行一次循環。因為基準測試驅動器并不知道每個基準測試函數運行所花的時間,因此它會在真正運行基準測試前先試用較小的N來運行測試,估算基準測試函數所需要的時間,然后推斷一個較大的時間保證穩定的測量結果。
循環在基準測試函數內實現,而不是放在基準測試框架內實現,這樣可以讓每個基準測試函數有機會在循環啟動前執行初始化代碼,這樣并不會顯著影響每次迭代的平均運行時間。
如果在運行基準測試之前需要一些費事的設置,則可能會重置計時器。例如:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
參考文章:
總結
- 上一篇: Go语言初探gRPC服务
- 下一篇: TCP keepalive的详解(解惑)