Go test 命令列引數
前言
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() // 一次操作
}
}