新聞中心
Go語言擁有一套單元測試和性能測試系統(tǒng),僅需要添加很少的代碼就可以快速測試一段需求代碼。

10年積累的成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認識你,你也不認識我。但先網(wǎng)站設(shè)計制作后付款的網(wǎng)站建設(shè)流程,更有永興免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
go test 命令,會自動讀取源碼目錄下面名為 *_test.go 的文件,生成并運行測試用的可執(zhí)行文件。輸出的信息類似下面所示的樣子:
ok archive/tar 0.011s
FAIL archive/zip 0.022s
ok compress/gzip 0.033s
...
性能測試系統(tǒng)可以給出代碼的性能數(shù)據(jù),幫助測試者分析性能問題。
提示
單元測試(unit testing),是指對軟件中的最小可測試單元進行檢查和驗證。對于單元測試中單元的含義,一般要根據(jù)實際情況去判定其具體含義,如C語言中單元指一個函數(shù), Java 里單元指一個類,圖形化的軟件中可以指一個窗口或一個菜單等??偟膩碚f,單元就是人為規(guī)定的最小的被測功能模塊。
單元測試是在軟件開發(fā)過程中要進行的最低級別的測試活動,軟件的獨立單元將在與程序的其他部分相隔離的情況下進行測試。
單元測試——測試和驗證代碼的框架
要開始一個單元測試,需要準備一個 go 源碼文件,在命名文件時需要讓文件必須以_test結(jié)尾。默認的情況下,go test命令不需要任何的參數(shù),它會自動把你源碼包下面所有 test 文件測試完畢,當(dāng)然你也可以帶上參數(shù)。
這里介紹幾個常用的參數(shù):
- -bench regexp 執(zhí)行相應(yīng)的 benchmarks,例如 -bench=.;
- -cover 開啟測試覆蓋率;
- -run regexp 只運行 regexp 匹配的函數(shù),例如 -run=Array 那么就執(zhí)行包含有 Array 開頭的函數(shù);
- -v 顯示測試的詳細命令。
單元測試源碼文件可以由多個測試用例組成,每個測試用例函數(shù)需要以Test為前綴,例如:
func TestXXX( t *testing.T )
- 測試用例文件不會參與正常源碼編譯,不會被包含到可執(zhí)行文件中。
- 測試用例文件使用
go test指令來執(zhí)行,沒有也不需要 main() 作為函數(shù)入口。所有在以_test結(jié)尾的源碼內(nèi)以Test開頭的函數(shù)會自動被執(zhí)行。 - 測試用例可以不傳入 *testing.T 參數(shù)。
helloworld 的測試代碼(具體位置是./src/chapter11/gotest/helloworld_test.go):
本套教程所有源碼下載地址:https://pan.baidu.com/s/1ORFVTOLEYYqDhRzeq0zIiQ 提取密碼:hfyf
package code11_3
import "testing"
func TestHelloWorld(t *testing.T) {
t.Log("hello world")
}代碼說明如下:
- 第 5 行,單元測試文件 (*_test.go) 里的測試入口必須以 Test 開始,參數(shù)為 *testing.T 的函數(shù)。一個單元測試文件可以有多個測試入口。
- 第 6 行,使用 testing 包的 T 結(jié)構(gòu)提供的 Log() 方法打印字符串。
1) 單元測試命令行
單元測試使用 go test 命令啟動,例如:
$ go test helloworld_test.go
ok command-line-arguments 0.003s
$ go test -v helloworld_test.go
=== RUN TestHelloWorld
--- PASS: TestHelloWorld (0.00s)
helloworld_test.go:8: hello world
PASS
ok command-line-arguments 0.004s代碼說明如下:
- 第 1 行,在 go test 后跟 helloworld_test.go 文件,表示測試這個文件里的所有測試用例。
- 第 2 行,顯示測試結(jié)果,ok 表示測試通過,command-line-arguments 是測試用例需要用到的一個包名,0.003s 表示測試花費的時間。
- 第 3 行,顯示在附加參數(shù)中添加了
-v,可以讓測試時顯示詳細的流程。 - 第 4 行,表示開始運行名叫 TestHelloWorld 的測試用例。
- 第 5 行,表示已經(jīng)運行完 TestHelloWorld 的測試用例,PASS 表示測試成功。
- 第 6 行打印字符串 hello world。
2) 運行指定單元測試用例
go test指定文件時默認執(zhí)行文件內(nèi)的所有測試用例??梢允褂?br />-run參數(shù)選擇需要的測試用例單獨執(zhí)行,參考下面的代碼。
一個文件包含多個測試用例(具體位置是./src/chapter11/gotest/select_test.go)
package code11_3
import "testing"
func TestA(t *testing.T) {
t.Log("A")
}
func TestAK(t *testing.T) {
t.Log("AK")
}
func TestB(t *testing.T) {
t.Log("B")
}
func TestC(t *testing.T) {
t.Log("C")
}這里指定 TestA 進行測試:
$ go test -v -run TestA select_test.go
=== RUN TestA
--- PASS: TestA (0.00s)
select_test.go:6: A
=== RUN TestAK
--- PASS: TestAK (0.00s)
select_test.go:10: AK
PASS
ok command-line-arguments 0.003s TestA 和 TestAK 的測試用例都被執(zhí)行,原因是-run跟隨的測試用例的名稱支持正則表達式,使用-run TestA$即可只執(zhí)行 TestA 測試用例。
3) 標(biāo)記單元測試結(jié)果
當(dāng)需要終止當(dāng)前測試用例時,可以使用 FailNow,參考下面的代碼。
測試結(jié)果標(biāo)記(具體位置是./src/chapter11/gotest/fail_test.go)
func TestFailNow(t *testing.T) {
t.FailNow()
}還有一種只標(biāo)記錯誤不終止測試的方法,代碼如下:
func TestFail(t *testing.T) {
fmt.Println("before fail")
t.Fail()
fmt.Println("after fail")
}測試結(jié)果如下:
=== RUN TestFail before fail after fail --- FAIL: TestFail (0.00s) FAIL exit status 1 FAIL command-line-arguments 0.002s
從日志中看出,第 5 行調(diào)用 Fail() 后測試結(jié)果標(biāo)記為失敗,但是第 7 行依然被程序執(zhí)行了。
4) 單元測試日志
每個測試用例可能并發(fā)執(zhí)行,使用 testing.T 提供的日志輸出可以保證日志跟隨這個測試上下文一起打印輸出。testing.T 提供了幾種日志輸出方法,詳見下表所示。
| 方 法 | 備 注 |
|---|---|
| Log | 打印日志,同時結(jié)束測試 |
| Logf | 格式化打印日志,同時結(jié)束測試 |
| Error | 打印錯誤日志,同時結(jié)束測試 |
| Errorf | 格式化打印錯誤日志,同時結(jié)束測試 |
| Fatal | 打印致命日志,同時結(jié)束測試 |
| Fatalf | 格式化打印致命日志,同時結(jié)束測試 |
開發(fā)者可以根據(jù)實際需要選擇合適的日志。
基準測試——獲得代碼內(nèi)存占用和運行效率的性能數(shù)據(jù)
基準測試可以測試一段程序的運行性能及耗費 CPU 的程度。Go語言中提供了基準測試框架,使用方法類似于單元測試,使用者無須準備高精度的計時器和各種分析工具,基準測試本身即可以打印出非常標(biāo)準的測試報告。
1) 基礎(chǔ)測試基本使用
下面通過一個例子來了解基準測試的基本使用方法。
基準測試(具體位置是./src/chapter11/gotest/benchmark_test.go)
package code11_3
import "testing"
func Benchmark_Add(b *testing.B) {
var n int
for i := 0; i < b.N; i++ {
n++
}
}這段代碼使用基準測試框架測試加法性能。第 7 行中的 b.N 由基準測試框架提供。測試代碼需要保證函數(shù)可重入性及無狀態(tài),也就是說,測試代碼不使用全局變量等帶有記憶性質(zhì)的 數(shù)據(jù)結(jié)構(gòu)。避免多次運行同一段代碼時的環(huán)境不一致,不能假設(shè) N 值范圍。
使用如下命令行開啟基準測試:
$ go test -v -bench=. benchmark_test.go goos: linux goarch: amd64 Benchmark_Add-4 20000000 0.33 ns/op PASS ok command-line-arguments 0.700s
代碼說明如下:
- 第 1 行的
-bench=.表示運行 benchmark_test.go 文件里的所有基準測試,和單元測試中的-run類似。 - 第 4 行中顯示基準測試名稱,2000000000 表示測試的次數(shù),也就是 testing.B 結(jié)構(gòu)中提供給程序使用的 N?!?.33 ns/op”表示每一個操作耗費多少時間(納秒)。
注意:Windows 下使用 go test 命令行時,-bench=.應(yīng)寫為-bench="."。
2) 基準測試原理
基準測試框架對一個測試用例的默認測試時間是 1 秒。開始測試時,當(dāng)以 Benchmark 開頭的基準測試用例函數(shù)返回時還不到 1 秒,那么 testing.B 中的 N 值將按 1、2、5、10、20、50……遞增,同時以遞增后的值重新調(diào)用基準測試用例函數(shù)。
3) 自定義測試時間
通過-benchtime參數(shù)可以自定義測試時間,例如:
$ go test -v -bench=. -benchtime=5s benchmark_test.go goos: linux goarch: amd64 Benchmark_Add-4 10000000000 0.33 ns/op PASS ok command-line-arguments 3.380s
4) 測試內(nèi)存
基準測試可以對一段代碼可能存在的內(nèi)存分配進行統(tǒng)計,下面是一段使用字符串格式化的函數(shù),內(nèi)部會進行一些分配操作。
func Benchmark_Alloc(b *testing.B) {
for i := 0; i < b.N; i++ {
fmt.Sprintf("%d", i)
}
}在命令行中添加-benchmem參數(shù)以顯示內(nèi)存分配情況,參見下面的指令:
$ go test -v -bench=Alloc -benchmem benchmark_test.go goos: linux goarch: amd64 Benchmark_Alloc-4 20000000 109 ns/op 16 B/op 2 allocs/op PASS ok command-line-arguments 2.311s
代碼說明如下:
- 第 1 行的代碼中
-bench后添加了 Alloc,指定只測試 Benchmark_Alloc() 函數(shù)。 - 第 4 行代碼的“16 B/op”表示每一次調(diào)用需要分配 16 個字節(jié),“2 allocs/op”表示每一次調(diào)用有兩次分配。
開發(fā)者根據(jù)這些信息可以迅速找到可能的分配點,進行優(yōu)化和調(diào)整。
5) 控制計時器
有些測試需要一定的啟動和初始化時間,如果從 Benchmark() 函數(shù)開始計時會很大程度上影響測試結(jié)果的精準性。testing.B 提供了一系列的方法可以方便地控制計時器,從而讓計時器只在需要的區(qū)間進行測試。我們通過下面的代碼來了解計時器的控制。
基準測試中的計時器控制(具體位置是./src/chapter11/gotest/benchmark_test.go):
func Benchmark_Add_TimerControl(b *testing.B) {
// 重置計時器
b.ResetTimer()
// 停止計時器
b.StopTimer()
// 開始計時器
b.StartTimer()
var n int
for i := 0; i < b.N; i++ {
n++
}
}從 Benchmark() 函數(shù)開始,Timer 就開始計數(shù)。StopTimer() 可以停止這個計數(shù)過程,做一些耗時的操作,通過 StartTimer() 重新開始計時。ResetTimer() 可以重置計數(shù)器的數(shù)據(jù)。
計數(shù)器內(nèi)部不僅包含耗時數(shù)據(jù),還包括內(nèi)存分配的數(shù)據(jù)。
網(wǎng)頁名稱:創(chuàng)新互聯(lián)GO教程:go test命令(Go語言測試命令)完全攻略
轉(zhuǎn)載源于:http://www.5511xx.com/article/dhejghs.html


咨詢
建站咨詢
