自動化測試,是在預設條件下運作系統或應用程式,評估運作結果,預先條件包括正常條件和異常條件。Go本身提供了一套輕量級的測試架構,相對低級,但不過還是有效的。它依賴一個
go test
測試指令,和一組按照約定方式編寫的測試函數,符合規則的測試代碼會在運作測試時被自動識别并執行。但是這些檔案是不會被普通的Go編譯器編譯,是以當将應用部署到生産環境時,它們不會被部署。
測試規則
檔案命名與放置規則
- 測試源檔案名應是
結尾的go檔案,例如:_test
;add_test.go
- 測試代碼和業務代碼是分開的,但兩者應該位于同一包下;
- 測試源檔案所在的包應該位于
目錄下;$GOPATH/src
- 測試檔案必須導入
包;"testing"
在Go中,凡是以或者
_
符号作為檔案名的首字母時,該檔案都會被建構工具忽略掉。以
.
_test.go
結尾的測試檔案,将會被編譯為單獨的包,然後将其連結到主測試二進制檔案。
go工具還會忽略名為
的目錄,使其可以儲存測試所需的輔助資料。
testdata
測試函數命名規則
測試檔案包括三種函數:測試函數、基準測試函數和例子函數。測試函數用于測試程式的一些邏輯行為是否正确的函數,在命名時應該以
Test
為字首,例如
func TestAbcde(t *testing.T)
。基準測試用于衡量一些函數的性能,是以
Benchmark
為函數名字首的函數,例如
func BenchmarkAbcde(b *testing.B)
。例子函數用來說明函數(變量,常量等)如何使用,以
Example
為函數名字首的函數,例如:
func ExamplePrintln(){
Println("The output of\nthis example.")
//Output: The output of
//this example.
}
go test指令
go test
指令會自動測試導入路徑命名的包并緩存測試結果,根據測試的結果和預先設定的是否比對,會傳回
PASS
或
FAIL
。它的用法:
go test [build/test參數] [包名] [build/test參數 &測試編譯參數]
,它有兩種不同的模式:本地目錄模式和包清單模式。僅在包清單模式下,
go test
會緩存成功的包測試結果以避免不必要的重複運作已經通過的測試。當測試的結果可以從緩存中恢複,
go test
将會重新顯示以前的輸出而不是再次運作測試二進制檔案。例如你需要對
math
目錄下的
a_test.go
檔案和
b_test.go
檔案做基準測試,那麼就可以執行
go test -bench . math a_test.go b_test.go
本地目錄模式
這種模式是在沒有包參數的情況下,調用
go test
時發生,例如:
go test
或
go test -v
。在此模式下,
go test
會編譯目前目錄中的包和測試檔案,然後運作生成的二進制檔案。這種模式下,緩存是被禁用的。測試完成後,
go test
會列印結果摘要,逐行顯示測試狀态,包名稱和已用的時間。
包清單模式
在調用
go test
時傳入顯式包參數,例如:
go test math
,
go test ./...
,或者
go test .
等。在此模式下,
go test
會編譯和測試指令行中列出的每一個包。如果一個包測試通過,
go test
隻列印成功摘要,但如果測試失敗,則會列印完整的資訊。如果你傳入參數
-bench
或
-v
标志,那麼
go test
将會列印完整的輸出,即使是通過測試的包。第一個參數是當有基準測試函數時使用,第二種就是平常的測試函數就行。
顯式禁用緩存的慣用方法是使用 -count=1
go test參數
-bench [正規表達式]:僅運作與正規表達式比對的基準,預設情況下,不運作基準測試。如果要運作所有的基準測試函數,使用
-bench .
或者
-bench=.
。
-benchtime [時間]:表示運作多長時間的基準測試,預設值為
1
秒。例如:
-benchtime 1h30s
。
-count n:運作每個測試和基準多少次,預設為
1
,如果設定了
-cpu
,則為每個
GOMAXPROCS
運作
n
次,例子函數總是運作一次。
-cover:啟用覆寫率分析,由于覆寫率通過在編譯之前注釋源代碼來工作,是以啟用覆寫率的編譯和測試失敗,可能會出現報告與原始檔案行号不對應的情況。
-covermode set,count,atomic:為正在測試的包設定覆寫率分析模式,除非啟用
-race
,否則預設為
set
,在這種情況下它是原子的。
-
,布爾值,表示這句聲明是否有效set
-
,int類型,這句聲明運作多少次count
-
,int類型,在多線程測試中使用,原子操作。atomic
-coverpkg pattern1,pattern2,pattern3:将每個測試中的覆寫率分析應用于模式比對的包,預設情況下,每個測試僅分析正在測試的包。
-cpu 1,2,4:指定應為其執行測試或基準測試的
GOMAXPROCS
的值的清單,預設值是
GOMAXPROCS
的目前值。
-failfast:表示在第一次測試失敗後不要開始新的測試。
-list [正規表達式]:隻是列出與正規表達式比對的測試、基準測試或例子,不會運作任何測試。
-parallel n:表示運作的最大測試數,預設情況下,它設定為
GOMAXPROCS
的值。
-run [正規表達式]:僅僅運作與正規表達式比對的那些測試和例子,比對時可能父項也會運作,例如:
-run = X/Y
,比對運作所有與X比對的測試的結果,即使沒有比對到子測試。
-timeout [時間]:如果測試檔案運作的時間超過設定的時間,就會出現
panic
。如果設定的時間為
,則表示
timeout
不可用。預設是
10
分鐘。
-v:會列印詳細的測試結果,即使是在測試成功的情況。
testing包
提供有關Go自動化測試的支援,它與
go test
指令一起使用。
// TB 是類型T和B的接口.
type TB interface {
Error(args ...interface{}) //Fail+Log
Errorf(format string, args ...interface{})
Fail() //标記失敗,但繼續執行該測試函數
FailNow() //失敗,立即停止目前測試函數
Failed() bool
Fatal(args ...interface{}) //FailNow+Log
Fatalf(format string, args ...interface{})
Log(args ...interface{}) //輸出資訊,僅在失敗或-v參數時輸出
Logf(format string, args ...interface{})
Name() string
Skip(args ...interface{})
SkipNow() //跳過目前測試函數
Skipf(format string, args ...interface{})
Skipped() bool
Helper()
private()
}
例子
1.在你的
$GOPATH/src
目錄下,建立一個目錄,例如:
mytest
檔案夾。
2.建立一個
main
檔案,寫入業務代碼。例如下面将0加到n的函數進行測試:
package main
func addNum(n int) (result int) {
for i := 0; i <= n; i++ {
result = result + i
}
return
}
3.建立測試檔案,檔案名以
_test.go
結尾,例如:
main_test.go
。
package main
import (
"testing"
)
func TestAddNum(t *testing.T) {
if addNum(100) != 5050 {
t.Fatal("addNum error!")
}
}
4.在指令行裡,直接輸入
go test
,運作目前包的所有測試檔案。或者運作
go test mytest
,隻測試
mytest
包的測試檔案。
本地目錄方式運作時的傳回結果:
PASS
ok mytest 0.421s
包清單模式運作的傳回結果:
ok mytest 0.138s
。
5.在
main.go
檔案中,添加基準測試函數。
package main
import (
"testing"
)
func TestAddNum(t *testing.T) {
if addNum(100) != 5050 {
t.Fatal("addNum error!")
}
}
func BenchmarkAddNum(b *testing.B) {
for i := 0; i < b.N; i++ {
if addNum(100) != 5050 {
b.Fatal("addNum")
}
}
}
6.運作基準測試,
go test -bench .
,預設情況下,
go test
不會執行性能測試函數。性能測試需要運作足夠多的次數才能計算單次執行平均時間。
goos: windows
goarch: amd64
pkg: mytest
BenchmarkAddNum-4 10000000 187 ns/op
PASS
ok mytest 2.522s
報告顯示執行addNum函數花費的平均時間是2.522s,執行了10000000次,每282ns的速度運作一次循環。因為基準測試驅動器并不知道每個基準測試函數運作所花的時間,是以它會在真正運作基準測試前先試用較小的N來運作測試,估算基準測試函數所需要的時間,然後推斷一個較大的時間保證穩定的測量結果。
循環在基準測試函數内實作,而不是放在基準測試架構内實作,這樣可以讓每個基準測試函數有機會在循環啟動前執行初始化代碼,這樣并不會顯著影響每次疊代的平均運作時間。
如果在運作基準測試之前需要一些費事的設定,則可能會重置計時器。例如:
func BenchmarkAddNum(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
if addNum(100) != 5050 {
b.Fatal("addNum")
}
}
}
參考文章:
- Package testing
- Command go