前言
go test有非常豐富的參數,一些參數用於控制測試的編譯,另一些參數控制測試的執行。
有關測試覆蓋率、vet和pprof相關的參數先略過,我們在討論相關內容時再詳細介紹。
控制編譯的參數
-args
指示go test把-args后面的參數帶到測試中去。具體的測試函數會跟據此參數來控制測試流程。
-args后面可以附帶多個參數,所有參數都將以字符串形式傳入,每個參數做為一個string,並存放到字符串切片中。
// TestArgs 用於演示如何解析-args參數 func TestArgs(t *testing.T) { if !flag.Parsed() { flag.Parse() } argList := flag.Args() // flag.Args() 返回 -args 后面的所有參數,以切片表示,每個元素代表一個參數 for _, arg := range argList { if arg == "cloud" { t.Log("Running in cloud.") }else { t.Log("Running in other mode.") } } }
執行測試時帶入參數:
E:\OpenSource\GitHub\RainbowMango\GoExpertProgrammingSourceCode\GoExpert\src\gotest>go test -run TestArgs -v -args "cloud" TestMain setup. === RUN TestArgs --- PASS: TestArgs (0.00s) unit_test.go:28: Running in cloud. PASS TestMain tear-down. ok gotest 0.353s
通過參數-args指定傳遞給測試的參數。
-json
-json 參數用於指示go test將結果輸出轉換成json格式,以方便自動化測試解析使用。
示例如下:
E:\OpenSource\GitHub\RainbowMango\GoExpertProgrammingSourceCode\GoExpert\src\gotest>go test -run TestAdd -json {"Time":"2019-02-28T15:46:50.3756322+08:00","Action":"output","Package":"gotest","Output":"TestMain setup.\n"} {"Time":"2019-02-28T15:46:50.4228258+08:00","Action":"run","Package":"gotest","Test":"TestAdd"} {"Time":"2019-02-28T15:46:50.423809+08:00","Action":"output","Package":"gotest","Test":"TestAdd","Output":"=== RUN TestAdd\n"} {"Time":"2019-02-28T15:46:50.423809+08:00","Action":"output","Package":"gotest","Test":"TestAdd","Output":"--- PASS: TestAdd (0.00s)\n"} {"Time":"2019-02-28T15:46:50.423809+08:00","Action":"pass","Package":"gotest","Test":"TestAdd","Elapsed":0} {"Time":"2019-02-28T15:46:50.4247922+08:00","Action":"output","Package":"gotest","Output":"PASS\n"} {"Time":"2019-02-28T15:46:50.4247922+08:00","Action":"output","Package":"gotest","Output":"TestMain tear-down.\n"} {"Time":"2019-02-28T15:46:50.4257754+08:00","Action":"output","Package":"gotest","Output":"ok \tgotest\t0.465s\n"} {"Time":"2019-02-28T15:46:50.4257754+08:00","Action":"pass","Package":"gotest","Elapsed":0.465}
-o <file>
-o 參數指定生成的二進制可執行程序,並執行測試,測試結束不會刪除該程序。
沒有此參數時,go test生成的二進制可執行程序存放到臨時目錄,執行結束便刪除。
示例如下:
E:\OpenSource\GitHub\RainbowMango\GoExpertProgrammingSourceCode\GoExpert\src\gotest>go test -run TestAdd -o TestAdd TestMain setup. PASS TestMain tear-down. ok gotest 0.439s E:\OpenSource\GitHub\RainbowMango\GoExpertProgrammingSourceCode\GoExpert\src\gotest>TestAdd TestMain setup. PASS TestMain tear-down.
本例中,使用-o 參數指定生成二進制文件"TestAdd"並存放到當前目錄,測試執行結束后,仍然可以直接執行該二進制程序。
控制測試的參數
-bench regexp
go test默認不執行性能測試,使用-bench參數才可以運行,而且只運行性能測試函數。
其中正則表達式用於篩選所要執行的性能測試。如果要執行所有的性能測試,使用參數"-bench ."或"-bench=."。
此處的正則表達式不是嚴格意義上的正則,而是種包含關系。
比如有如下三個性能測試:
- func BenchmarkMakeSliceWithoutAlloc(b *testing.B)
- func BenchmarkMakeSliceWithPreAlloc(b *testing.B)
- func BenchmarkSetBytes(b *testing.B)
使用參數“-bench=Slice”,那么前兩個測試因為都包含"Slice",所以都會被執行,第三個測試則不會執行。
對於包含子測試的場景下,匹配是按層匹配的。舉一個包含子測試的例子:
func BenchmarkSub(b *testing.B) { b.Run("A=1", benchSub1) b.Run("A=2", benchSub2) b.Run("B=1", benchSub3) }
測試函數命名規則中,子測試的名字需要以父測試名字做為前綴並以"/"連接,上面的例子實際上是包含4個測試:
- Sub
- Sub/A=1
- Sub/A=2
- Sub/B=1
如果想執行三個子測試,那么使用參數“-bench Sub”。如果只想執行“Sub/A=1”,則使用參數"-bench Sub/A=1"。如果想執行"Sub/A=1"和“Sub/A=2”,則使用參數"-bench Sub/A="。
-benchtime <t>s
-benchtime指定每個性能測試的執行時間,如果不指定,則使用默認時間1s。
例如,執定每個性能測試執行2s,則參數為:"go test -bench Sub/A=1 -benchtime 2s"。
-cpu 1,2,4
-cpu 參數提供一個CPU個數的列表,提供此列表后,那么測試將按照這個列表指定的CPU數設置GOMAXPROCS並分別測試。
比如“-cpu 1,2”,那么每個測試將執行兩次,一次是用1個CPU執行,一次是用2個CPU執行。 例如,使用命令"go test -bench Sub/A=1 -cpu 1,2,3,4" 執行測試:
BenchmarkSub/A=1 1000 1256835 ns/op BenchmarkSub/A=1-2 2000 912109 ns/op BenchmarkSub/A=1-3 2000 888671 ns/op BenchmarkSub/A=1-4 2000 894531 ns/op
測試結果中測試名后面的-2、-3、-4分別代表執行時GOMAXPROCS的數值。 如果GOMAXPROCS為1,則不顯示。
-count n
-count指定每個測試執行的次數,默認執行一次。
例如,指定測試執行2次:
E:\OpenSource\GitHub\RainbowMango\GoExpertProgrammingSourceCode\GoExpert\src\gotest>go test -bench Sub/A=1 -count 2 TestMain setup. goos: windows goarch: amd64 pkg: gotest BenchmarkSub/A=1-4 2000 917968 ns/op BenchmarkSub/A=1-4 2000 882812 ns/op PASS TestMain tear-down. ok gotest 10.236s
可以看到結果中也將呈現兩次的測試結果。
如果使用-count指定執行次數的同時還指定了-cpu列表,那么測試將在每種CPU數量下執行count指定的次數。
注意,示例測試不關心-count和-cpu參數,它總是執行一次。
-failfast
默認情況下,go test將會執行所有匹配到的測試,並最后打印測試結果,無論成功或失敗。
-failfast指定如果有測試出現失敗,則立即停止測試。這在有大量的測試需要執行時,能夠更快的發現問題。
-list regexp
-list 只是列出匹配成功的測試函數,並不真正執行。而且,不會列出子函數。
例如,使用參數"-list Sub"則只會列出包含子測試的三個測試,但不會列出子測試:
E:\OpenSource\GitHub\RainbowMango\GoExpertProgrammingSourceCode\GoExpert\src\gotest>go test -list Sub TestMain setup. TestSubParallel TestSub BenchmarkSub TestMain tear-down. ok gotest 0.396s
-parallel n
指定測試的最大並發數。
當測試使用t.Parallel()方法將測試轉為並發時,將受到最大並發數的限制,默認情況下最多有GOMAXPROCS個測試並發,其他的測試只能阻塞等待。
-run regexp
跟據正則表達式執行單元測試和示例測試。正則匹配規則與-bench 類似。
-timeout d
默認情況下,測試執行超過10分鍾就會超時而退出。
例時,我們把超時時間設置為1s,由本來需要3s的測試就會因超時而退出:
E:\OpenSource\GitHub\RainbowMango\GoExpertProgrammingSourceCode\GoExpert\src\gotest>go test -timeout=1s TestMain setup. panic: test timed out after 1s
設置超時可以按秒、按分和按時:
- 按秒設置:-timeout xs或-timeout=xs
- 按分設置:-timeout xm或-timeout=xm
- 按時設置:-timeout xh或-timeout=xh
-v
默認情況下,測試結果只打印簡單的測試結果,-v 參數可以打印詳細的日志。
性能測試下,總是打印日志,因為日志有時會影響性能結果。
-benchmem
默認情況下,性能測試結果只打印運行次數、每個操作耗時。使用-benchmem則可以打印每個操作分配的字節數、每個操作分配的對象數。
// 沒有使用-benchmem BenchmarkMakeSliceWithoutAlloc-4 2000 971191 ns/op // 使用-benchmem BenchmarkMakeSliceWithoutAlloc-4 2000 914550 ns/op 4654335 B/op 30 allocs/op
此處,每個操作的含義是放到循環中的操作,如下示例所示:
func BenchmarkMakeSliceWithoutAlloc(b *testing.B) { for i := 0; i < b.N; i++ { gotest.MakeSliceWithoutAlloc() // 一次操作 } }