go標準命令詳解0.7 go test
go test
命令用於對Go語言編寫的程式進行測試。這種測試是以程式碼包為單位的。當然,這還需要測試原始碼檔案的幫助。關於怎樣編寫並寫好Go程式測試程式碼,我們會在本章的第二節加以詳述。在這裡,我們只討論怎樣使用命令啟動測試。
go test
命令會自動測試每一個指定的程式碼包。當然,前提是指定的程式碼包中存在測試原始碼檔案。關於測試原始碼檔案方面的知識,我們已經在第二章的第二節中介紹過。測試原始碼檔案是名稱以“_test.go”為字尾的、內含若干測試函式的原始碼檔案。測試函式一般是以“Test”為名稱字首並有一個型別為“testing.T”的引數宣告的函式.
現在,我們來測試goc2p專案中的幾個程式碼包。在使用go test
hc@ubt:~$ go test basic cnet/ctcp pkgtool
ok basic 0.010s
ok cnet/ctcp 2.018s
ok pkgtool 0.009s
go test
命令在執行完所有的程式碼包中的測試檔案之後,會以程式碼包為單位打印出測試概要資訊。在上面的示例中,對應三個程式碼包的三行資訊的第一列都是“ok”。這說明它們都通過了測試。每行的第三列顯示執行相應測試所用的時間,以秒為單位。我們還可以在程式碼包目錄下執行不加任何引數的執行go test
另外,我們還可以指定測試原始碼檔案來進行測試。這樣的話,go test
命令只會執行指定檔案中的測試,像這樣:
hc@ubt:~/golang/goc2p/src/pkgtool$ go test envir_test.go
# command-line-arguments
./envir_test.go:20: undefined: GetGoroot
./envir_test.go:34: undefined: GetAllGopath
./envir_test.go:74: undefined: GetSrcDirs
./envir_test.go:76: undefined: GetAllGopath
./envir_test.go:83: undefined: GetGoroot
FAIL command-line-arguments [build failed]
我們看到,與指定原始碼檔案進行編譯或執行一樣,命令程式會為指定的原始碼檔案生成一個虛擬程式碼包——“command-line-arguments”。但是,測試並沒有通過。但其原因並不是測試失敗,而是編譯失敗。對於執行這次測試的命令程式來說,測試原始碼檔案envir_test.go是屬於程式碼包“command-line-arguments”的。並且,這個測試原始碼檔案中使用了庫原始碼檔案envir.go中的函式。可以,它卻沒有顯示匯入這個庫原始碼檔案所屬的程式碼包,這當然會引起編譯錯誤。如果想解決這個問題,我們還需要在執行命令時加入這個測試原始碼檔案所測試的那個原始碼檔案。示例如下:
hc@ubt:~/golang/goc2p/src/pkgtool$ go test envir_test.go envir.go
ok command-line-arguments 0.008s
現在,我們故意使程式碼包pkgtool
中的某個測試失敗。現在我們再來執行測試:
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的測試函式TestGetSrcDirs
中的測試失敗了。在包含測試失敗的測試原始碼檔名的那一行資訊中,緊跟測試原始碼檔名的用冒號分隔的數字是錯誤資訊所處的行號,在行號後面用冒號分隔的是錯誤資訊。這個錯誤資訊的內容是使用者自行編寫的。另外,概要資訊的最後一行以“FAIL”為字首。這表明針對程式碼包pkgtool的測試未通過。未通過的原因在前面的資訊中已有描述。
一般情況下,我們會把測試原始碼檔案與被測試的原始碼檔案放在同一個程式碼包中。並且,這些原始碼檔案中宣告的包名也都是相同的。除此之外我們還有一種選擇,那就是測試原始碼檔案中宣告的包名可以是所屬包名再加“_test”字尾。我們把這種測試原始碼檔案叫做包外測試原始碼檔案。不過,包外測試原始碼檔案存在一個弊端,那就是在它們的測試函式中無法測試被測原始碼檔案中的包級私有的程式實體,比如包級私有的變數、函式和結構體型別。這是因為這兩者的所屬程式碼包是不相同的。所以,我們一般很少會編寫包外測試原始碼檔案。
關於標記
go test
命令的標記處理部分是龐大且繁雜的,以至於使Go語言的開發者們不得不把這一部分的邏輯從go test
命令程式主體中分離出來並建立單獨的原始碼檔案。因為go test
命令中包含了編譯動作,所以它可以接受可用於go build
命令的所有標記。另外,它還有很多特有的標記。這些標記的用於控制命令本身的動作,有的用於控制和設定測試的過程和環境,還有的用於生成更詳細的測試結果和統計資訊。
可用於go test
命令的兩個比較常用的標記是-i
和標記-c
。這兩個就是用於控制go test
命令本身的動作的標記。詳見下表。
表0-6 go test
命令的標記說明
| 標記名稱 | 標記描述 |
| -c | 生成用於執行測試的可執行檔案,但不執行它。 |
| -i | 安裝/重新安裝執行測試所需的依賴包但不編譯和執行測試程式碼。 |
上述這兩個標記可以搭配使用。搭配使用的目的就是讓go test
命令既安裝依賴包又編譯測試程式碼,但不執行測試。也就是說,讓命令程式跑一遍執行測試之前的所有流程。這可以測試一下測試過程。需要注意的是,在加入-c
標記後,命令程式在編譯測試程式碼並生成用於執行測試的一系列檔案之後會把臨時工作目錄及其下的所有內容一併刪除。如果想在命令執行結束後再去檢視這些內容的話,我們還需要加入-work
標記。
除此之外,go test
命令還有很多功效各異的標記。但是由於這些標記的複雜性,我們需要結合測試原始碼檔案進行詳細的講解。所以我們把這些內容放在了本章的第二節中。