鍍金池/ 教程/ GO/ go test
go install
go clean
go list
go test
go doc與godoc
go build
go fix與go tool fix
go tool pprof
go run
go env
go tool cgo
標(biāo)準(zhǔn)命令詳解
go get
go vet與go tool vet

go test

go test命令用于對Go語言編寫的程序進(jìn)行測試。這種測試是以代碼包為單位的。當(dāng)然,這還需要測試源碼文件的幫助。關(guān)于怎樣編寫并寫好Go程序測試代碼,我們會在本章的第二節(jié)加以詳述。在這里,我們只討論怎樣使用命令啟動測試。

go test命令會自動測試每一個指定的代碼包。當(dāng)然,前提是指定的代碼包中存在測試源碼文件。關(guān)于測試源碼文件方面的知識,在我的圖書《Go并發(fā)編程實(shí)戰(zhàn)》中有詳細(xì)介紹。測試源碼文件是名稱以“_test.go”為后綴的、內(nèi)含若干測試函數(shù)的源碼文件。測試函數(shù)一般是以“Test”為名稱前綴并有一個類型為“testing.T”的參數(shù)聲明的函數(shù).

現(xiàn)在,我們來測試goc2p項(xiàng)目中的幾個代碼包。在使用go test命令時指定代碼包的方式與其他命令無異——使用代碼包導(dǎo)入路徑。如果需要測試多個代碼包,則需要在它們的導(dǎo)入路徑之間加入空格以示分隔。示例如下:

hc@ubt:~$ go test basic cnet/ctcp pkgtool
ok      basic   0.012s
ok      cnet/ctcp   2.014s
ok      pkgtool 0.014s

go test命令在執(zhí)行完所有的代碼包中的測試文件之后,會以代碼包為單位打印出測試概要信息。在上面的示例中,對應(yīng)三個代碼包的三行信息的第一列都是“ok”。這說明它們都通過了測試。每行的第三列顯示運(yùn)行相應(yīng)測試所用的時間,以秒為單位。我們還可以在代碼包目錄下運(yùn)行不加任何參數(shù)的運(yùn)行go test命令。其作用和結(jié)果與上面的示例是一樣的。

另外,我們還可以指定測試源碼文件來進(jìn)行測試。這樣的話,go test命令只會執(zhí)行指定文件中的測試,像這樣:

    hc@ubt:~/golang/goc2p/src/pkgtool$ go test envir_test.go
# command-line-arguments
./envir_test.go:25: undefined: GetGoroot
./envir_test.go:40: undefined: GetAllGopath
./envir_test.go:81: undefined: GetSrcDirs
./envir_test.go:83: undefined: GetAllGopath
./envir_test.go:90: undefined: GetGoroot
FAIL    command-line-arguments [build failed]

我們看到,與指定源碼文件進(jìn)行編譯或運(yùn)行一樣,命令程序會為指定的源碼文件生成一個虛擬代碼包——“command-line-arguments”。但是,測試并沒有通過。但其原因并不是測試失敗,而是編譯失敗。對于運(yùn)行這次測試的命令程序來說,測試源碼文件envir_test.go是屬于代碼包“command-line-arguments”的。并且,這個測試源碼文件中使用了庫源碼文件envir.go中的函數(shù)。但是,它卻沒有顯示導(dǎo)入這個庫源碼文件所屬的代碼包。這顯然會引起編譯錯誤。如果想解決這個問題,我們還需要在執(zhí)行命令時加入這個測試源碼文件所測試的那個源碼文件。示例如下:

hc@ubt:~/golang/goc2p/src/pkgtool$ go test envir_test.go envir.go
ok      command-line-arguments  0.010s

現(xiàn)在,我們故意使代碼包pkgtool中的某個測試失敗?,F(xiàn)在我們再來運(yùn)行測試:

hc@ubt:~$ go test basic cnet/ctcp pkgtool
ok      basic   0.010s
ok      cnet/ctcp       2.015s
--- FAIL: TestGetSrcDirs (0.00 seconds)
        envir_test.go:85: Error: The src dir '/usr/local/go/src/pkg' is incorrect.
FAIL
FAIL    pkgtool 0.009s

我們通過以上示例中的概要信息獲知,測試源碼文件中envir_test.go的測試函數(shù)TestGetSrcDirs中的測試失敗了。在包含測試失敗的測試源碼文件名的那一行信息中,緊跟測試源碼文件名的用冒號分隔的數(shù)字是錯誤信息所處的行號,在行號后面用冒號分隔的是錯誤信息。這個錯誤信息的內(nèi)容是用戶自行編寫的。另外,概要信息的最后一行以“FAIL”為前綴。這表明針對代碼包pkgtool的測試未通過。未通過的原因在前面的信息中已有描述。

一般情況下,我們會把測試源碼文件與被測試的源碼文件放在同一個代碼包中。并且,這些源碼文件中聲明的包名也都是相同的。除此之外我們還有一種選擇,那就是測試源碼文件中聲明的包名可以是所屬包名再加“_test”后綴。我們把這種測試源碼文件叫做包外測試源碼文件。不過,包外測試源碼文件存在一個弊端,那就是在它們的測試函數(shù)中無法測試被測源碼文件中的包級私有的程序?qū)嶓w,比如包級私有的變量、函數(shù)和結(jié)構(gòu)體類型。這是因?yàn)檫@兩者的所屬代碼包是不相同的。所以,我們一般很少會編寫包外測試源碼文件。

關(guān)于標(biāo)記

go test命令的標(biāo)記處理部分是龐大且繁雜的,以至于使Go語言的開發(fā)者們不得不把這一部分的邏輯從go test命令程序主體中分離出來并建立單獨(dú)的源碼文件。因?yàn)?code>go test命令中包含了編譯動作,所以它可以接受可用于go build命令的所有標(biāo)記。另外,它還有很多特有的標(biāo)記。這些標(biāo)記的用于控制命令本身的動作,有的用于控制和設(shè)置測試的過程和環(huán)境,還有的用于生成更詳細(xì)的測試結(jié)果和統(tǒng)計(jì)信息。

可用于go test命令的幾個比較常用的標(biāo)記是-c、-i-o。這兩個就是用于控制go test命令本身的動作的標(biāo)記。詳見下表。

表0-6 go test命令的標(biāo)記說明

標(biāo)記名稱 標(biāo)記描述
-c 生成用于運(yùn)行測試的可執(zhí)行文件,但不執(zhí)行它。這個可執(zhí)行文件會被命名為“pkg.test”,其中的“pkg”即為被測試代碼包的導(dǎo)入路徑的最后一個元素的名稱。
-i 安裝/重新安裝運(yùn)行測試所需的依賴包,但不編譯和運(yùn)行測試代碼。
-o 指定用于運(yùn)行測試的可執(zhí)行文件的名稱。追加該標(biāo)記不會影響測試代碼的運(yùn)行,除非同時追加了標(biāo)記-c-i

上述這幾個標(biāo)記可以搭配使用。搭配使用的目的可以是讓go test命令既安裝依賴包又編譯測試代碼,但不運(yùn)行測試。也就是說,讓命令程序跑一遍運(yùn)行測試之前的所有流程。這可以測試一下測試過程。注意,在加入-c標(biāo)記后,命令程序會把用于運(yùn)行測試的可執(zhí)行文件存放到當(dāng)前目錄下。

除此之外,go test命令還有很多功效各異的標(biāo)記。但是由于這些標(biāo)記的復(fù)雜性,我們需要結(jié)合測試源碼文件進(jìn)行詳細(xì)的講解。所以我們在這里略過不講。如果讀者想了解相關(guān)詳情,請參看《Go并發(fā)編程實(shí)戰(zhàn)》的第5章。