Go 語言推薦測試文件和源代碼文件放在同一目錄下,測試文件以 _test.go
結尾。比如,當前 package 有 calc.go
一個文件,我們想測試 calc.go
中的 Add
和 Mul
函數,那么應該新建 calc_test.go
作為測試文件。
example/
|--calc.go |--calc_test.go
假如 calc.go
的代碼如下:
1 package main 2
3 func Add(a int, b int) int { 4 return a + b 5 } 6
7 func Mul(a int, b int) int { 8 return a * b 9 }
那么 calc_test.go
中的測試用例可以這么寫:
1 package main 2
3 import "testing"
4
5 func TestAdd(t *testing.T) { 6 if ans := Add(1, 2); ans != 3 { 7 t.Errorf("1 + 2 expected be 3, but %d got", ans) 8 } 9
10 if ans := Add(-10, -20); ans != -30 { 11 t.Errorf("-10 + -20 expected be -30, but %d got", ans) 12 } 13 }
- 測試用例名稱一般命名為
Test
加上待測試的方法名。 - 測試用的參數有且只有一個,在這里是
t *testing.T
。
運行 go test
,該 package 下所有的測試用例都會被執行。
$ go test ok example 0.009s
或 go test -v
, -v
參數會顯示每個用例的測試結果
$ go test -v === RUN TestAdd --- PASS: TestAdd (0.00s) === RUN TestMul --- PASS: TestMul (0.00s) PASS ok example 0.007s
如果只想運行其中的一個用例,例如 TestAdd
,可以用 -run
參數指定,該參數支持通配符 *
,和部分正則表達式,例如 ^
、$
。
1 $ go test -run TestAdd -v 2 === RUN TestAdd 3 --- PASS: TestAdd (0.00s) 4 PASS 5 ok example 0.007s
遇到如下報錯的解決方法
原因:
從提示:build failed可以看出是
構建失敗,go test與其他的指定源碼文件進行編譯或運行的命令程序一樣(參考:go run
和go build
),會為指定的源碼文件生成一個虛擬代碼包——“command-line-arguments”,對於運行這次測試的命令程序來說,測試源碼文件getinfo_test.go
是屬於代碼包“command-line-arguments”的,可是它引用了其他包中的數據並不屬於代碼包“command-line-arguments”,編譯不通過,錯誤自然發生了。
解決方法:
知道了原因之后,解決的方法就出來了,執行命令時加入這個測試文件需要引用的源碼文件,在命令行后方的文件都會被加載到command-line-arguments
中進行編譯,示例如下:
單元測試覆蓋率
- cover:查看單元測試的覆蓋率
- coverprofile:指定輸出文件
示例:
生成html格式的覆蓋率報告
命令:
go tool cover -html=cover.out -o coverage.html
HTML文件內容:
go test命令的使用
go test做性能測試
除了可以做功能邏輯的測試(上面講的單元測試),go test還可以做性能測試
壓測文件的規則:
- 文件名規則和單元測試一樣
- 壓力測試函數必須遵循如下格式,其中XXX可以是任意字母數字的組合,但是首字母不能是小寫字母,注意琪參數是 testing.B,單元測試參數是 testing.T
func BenchmarkXXX(b *testing.B) { … }
- go test不會默認執行壓力測試的函數,如果要執行壓力測試需要帶上參數-bench,語法:-bench=文件路徑名,例如go test -test.bench=.
表示測試當前目錄下全部的壓力測試函數
- 壓力測試函數在壓力測試用例中,有一個屬性 testing.B.N,它表示的是進行壓力測試的次數。可以通過 b.N = 1234 來設置壓力次數
如 webbench_test.go 壓力測試函數
1 package math 2
3 import ( 4 "testing"
5 ) 6
7 func Benchmark_Division(b *testing.B) { 8 for i := 0; i < b.N; i++ { //use b.N for looping
9 Division(4, 5) 10 } 11 } 12
13 func Benchmark_TimeConsumingFunction(b *testing.B) { 14 b.StopTimer() //調用該函數停止壓力測試的時間計數 15
16 //做一些初始化的工作,例如讀取文件數據,數據庫連接之類的, 17 //這樣這些時間不影響我們測試函數本身的性能
18
19 b.StartTimer() //重新開始時間
20
21 b.N=1234 //自定義執行1234次
22
23 for i := 0; i < b.N; i++ { 24 Division(4, 5) 25 } 26 }
執行如下命令 go test -v ./webbench_test.go ./division.go -bench=".*" 只顯示壓力測試,因為兩個文件有依賴所以需要放到一起編譯執行
其中 -bench=".*" 表示 執行所有壓力測試函數
結果如下:
$ go test -v ./webbench_test.go ./division.go -bench=".*" goos: linux goarch: amd64 Benchmark_Division-8 2000000000 0.74 ns/op Benchmark_TimeConsumingFunction-8 1234 0.96 ns/op PASS ok command-line-arguments 1.558s
上面信息說明Benchmark_Division默認執行了2000000000次,
而Benchmark_TimeConsumingFunction通過設置 b.N=1234 執行不同次數;
每次的執行平均時間分別是0.74納秒和0.96納秒,總運行時間1.558秒