Go test 少為人知的特性

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。大多數的 Go 程式員都知道和喜歡用 `go test`,這個測試載入器來自於 Go 官方的 `gc` 工具鏈。(想要執行測試代碼)這個命令可能是最簡單的了,而且還能做得很漂亮。大家都知道,運行 `go test` 命令將執行目前的目錄下的包的測試代碼,它會尋找 `*_test.go` 檔案,並在這些檔案中,尋找符合 `TestXxx(*testing.T){}` 命名的函數和參數(即,接收 `*testing.T` 參數的函數,命名為 `TestXxx`,`Xxx` 可以是任何不以小寫字元開頭的名字)。這個測試代碼不會影響正常的編譯過程,只在執行 `go test` 時被使用。但這裡還有很多隱藏的東西。## 黑箱測試包(The black box test package)通常情況下,在 Go 語言中,測試和要被測試的代碼在同一個包中(被測系統),這樣才能訪問內部實現細節的代碼。為了支援黑箱測試,`go test` 支援使用以 "_test" 尾碼命名,並可被編譯成獨立的包的形式。如:```go// in example.gopackage examplevar start intfunc Add(n int) int {start += nreturn start}// in example_test.gopackage example_testimport ("testing". "bitbucket.org/splice/blog/example")func TestAdd(t *testing.T) {got := Add(1)if got != 1 {t.Errorf("got %d, want 1", got)}}```你可以在代碼中看到臭名昭著的 [點匯入](https://golang.org/ref/spec#Import_declarations) 。但當對一個包做黑箱測試時,在當前包的範圍內匯入(被匯入包中)可被匯出的符號來說,這是它的一個有實際意義的例子。測試代碼[在通常的情況下應該盡量避免進入被測試的環境中](https://code.google.com/p/go-wiki/wiki/CodeReviewComments#Import_Dot)。就像在點匯入的連結符號章節中所解釋的一樣,黑箱測試模式也能被用來打破迴圈匯入的問題(在被測試的包 “a” 被 “b” 匯入,並且 “a“ 的測試也需要匯入 ”b“ 時 - 測試可以被移動到 “a_test“ 包,然後可以(同時)匯入 “a” 和 “b”,這樣就沒有迴圈匯入的問題)。## 跳過測試(Skipping tests)一些測試可能要求要有特定的上下文環境。例如,一些測試可能需要調用一個外部的命令,使用一個特殊的檔案,或者需要一個可以被設定的環境變數。當條件無法滿足時,(如果)不想讓那些測試失敗,可以簡單地跳過那些測試:```gofunc TestSomeProtectedResource(t *testing.T) {if os.Getenv("SOME_ACCESS_TOKEN") == "" {t.Skip("skipping test; $SOME_ACCESS_TOKEN not set")}// ... the actual test}```如果 `go test -v` 被調用(注意那個冗餘(”-v“)標誌),輸出將會提醒已跳過的測試:```=== RUN TestSomeProtectedResource--- SKIP: TestSomeProtectedResource (0.00 seconds)example_test.go:17: skipping test; $SOME_ACCESS_TOKEN not set```通常是用 `-short` 命令列標誌來實現這個跳過的特性,如果標誌被設定的話,反映到代碼中,`testing.Short()` 將簡單地返回 true(就像是 `-v` 標誌一樣,如果它被設定,通過判斷 `testing.Verbose()` ,你可以列印出額外的調試日誌)。當測試需要運行較長時間時,而你又很著急的話,你可以執行 `go test -short`,(如果)提供這個包的開發人員又剛好實現了這個功能,已耗用時間長的測試將會被跳過。這就是從源碼安裝時,(通常情況下)Go 測試被執行的樣子,這裡有 stdlib 庫中已耗用時間較長的測試被跳過的例子:```gofunc TestCountMallocs(t *testing.T) {if testing.Short() {t.Skip("skipping malloc count in short mode")}// rest of test...}```跳過只是一個可選項,`-short` 標誌只是一個標示,具體還依賴於開發人員,他們可以選擇(這種標示生效時是否)啟動並執行測試,來避免一些運行比較慢的斷言被執行。這裡還有 `-timeout` 標誌,它能夠被用來強制退出限定時間內沒有運行完的測試。例如,運行這個命令 `go test -timeout 1s` 以執行下面的測試:```gofunc TestWillTimeout(t *testing.T) {time.Sleep(2 * time.Second)// pass if timeout > 2s}```會有如下輸出(截斷):```=== RUN TestWillTimeoutpanic: test timed out after 1s```如果想執行特定的測試函數,而不是執行全部的測試集,只需要運行 `go test -run TestNameRegexp`。### 並存執行測試(Parallelizing tests)預設情況下,指定包的測試是按照順序執行的,但也可以通過在測試的函數內部使用 `t.Parallel()` 來標誌某些測試也可以被安全的並發執行(和預設的一樣,假設參數名為 `t`)。在並存執行的情況下,只有當那些被標記為並行的測試才會被並存執行,所以只有一個測試函數時是沒意義的。它應該在測試函數體中第一個被調用(在任何需要跳過的條件之後),因為它會重設測試時間:```gofunc TestParallel(t *testing.T) {t.Parallel()// actual test...}```在並發情況下,同時啟動並執行測試的數量預設取決於 `GOMAXPROCS`。它可以通過 `-parallel n` 被指定(`go test -parallel 4`)另外一個可以實現並行的方法,儘管不是函數級粒度,但卻是包級粒度,就是類似這樣執行 `go test p1 p2 p3`(也就是說,同時調用多個測試包)。在這種情況下,包會被先編譯,並同時被執行。當然,這對於總的時間來說是有好處的,但它也可能會導致錯誤變得具有不可預測性,比如一些資源被多個包同時使用時(例如,一些測試需要訪問資料庫,並刪除一些行,而這些行又剛好被其他的測試包使用的話)。為了保持可控性,`-p` 標誌可以用來指定編譯和測試的並發數。當倉庫中有多個測試包,並且每個包在不同的子目錄中,一個可以執行所有包的命令是 `go test ./...`,這包含目前的目錄和所有子目錄。沒有帶 `-p` 標誌執行時,總的已耗用時間應該接近於已耗用時間最長的包的時間(加上編譯時間)。運行 `go test -p 1 ./...`,使編譯和測試載入器只能在一個包中執行時,總的時間應該接近於所有獨立的包測試的時間加上編譯的時間的總和。你可以自己試試,執行 `go test -p 3 ./...`,看一下對已耗用時間的影響。還有,另外一個可以並行化的地方(你應該測試一下)是在包的代碼裡面。多虧了 Go 非常棒的並行原語,實際上,除非 GOMAXPROCS 通過環境變數或者在代碼中顯式設定為 GOMAXPROCS=1,否則,包中一個goroutines 都沒有用是不太常見的。想要使用 2 個 CPU,可以執行 `GOMAXPROCS=2 go test`,想要使用 4 個 CPU,可以執行 `GOMAXPROCS=4 go test`,但還有更好的方法:`go test -cpu=1,2,4` 將會執行 3 次,其中 GOMAXPROCS 值分別為 1,2,和 4。`-cpu` 標誌,搭配資料競爭的探測標誌 `-race`,簡直進入天堂(或者下地獄,取決於它具體怎麼運行)。競爭探測是一個很神奇的工具,在以高並發為主的開發中不得不使用這個工具(來防止死結問題),但對它的討論已經超過了本文的範圍。如果你對此感興趣,可以閱讀 Go 官方部落格的 [這篇文章](http://blog.golang.org/race-detector)。## 更多的內容`go test` 工具支援以與測試函數相似的方式運行基準測試和可斷言樣本(!)。`godoc` 工具甚至能夠理解例子中的文法並將其包含在產生的文檔中。不得不提的還有程式碼涵蓋範圍和效能測試,測試載入器也支援這兩個功能。對於感興趣並想要深入瞭解的,可以訪問 [The cover story](http://blog.golang.org/cover) 和 [Profiling Go programs](http://blog.golang.org/profiling-go-programs),它們都在 Go 部落格中。在你寫自己的測試代碼前,建議看一下標準庫中的 `testing/iotest`,`testing/quick` 和 `net/http/httptest` 軟體包。

via: https://splice.com/blog/lesser-known-features-go-test/

作者:MARTIN ANGERS 譯者:gogeof 校對:polaris1119

本文由 GCTT 原創編譯,Go語言中文網 榮譽推出

本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽

1472 次點擊  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.