測試對於互聯網應用軟件開發來講很是重要,它對軟件可靠性保證具備重要意義,經過測試可以儘量發現並改正軟件中的錯誤,提升軟件質量。html
這裏咱們主要講解Go語言如何實現單元測試和性能測試。git
go語言中自帶有一個輕量級的測試框架testing和自帶的go test命令來實現單元測試和性能測試,testing框架和其餘語言中的測試框架相似,你能夠基於這個框架寫針對相應函數的測試用例,也能夠基於該框架寫相應的壓力測試用例,那麼接下來讓咱們一一來看一下怎麼寫。github
單元測試golang
建立目錄test,在目錄下建立add.go、add_test.go兩個文件,add_test.go爲單元測試文件。windows
add_test.go框架
package test import "testing" func TestAdd(t *testing.T) { sum := Add(1, 2) if sum == 3 { t.Log("the result is ok") } else { t.Fatal("the result is wrong") } } func TestAdd1(t *testing.T) { t.Error("the result is error") }
add.go函數
package test func Add(a, b int) int { return a + b }
而後在項目目錄下運行go test -v
就能夠看到測試結果了工具
=== RUN TestAdd --- PASS: TestAdd (0.00s) add_test.go:8: the result is ok === RUN TestAdd1 --- FAIL: TestAdd1 (0.00s) add_test.go:14: the result is error FAIL exit status 1 FAIL _/D_/gopath/src/ados/test 0.419s
若是看到PASS字樣證實測試經過,FAIL字樣表示測試失敗。性能
使用testing庫的測試框架須要遵循如下幾個規則以下:單元測試
_test.go
結尾的,這樣在執行go test
的時候纔會執行到相應的代碼testing
這個包Test
開頭TestXxx()
的參數是testing.T
,咱們可使用該類型來記錄錯誤或者是測試狀態func TestXxx (t *testing.T)
,Xxx
部分能夠爲任意的字母數字的組合,可是首字母不能是小寫字母[a-z],例如Testintdiv
是錯誤的函數名。testing.T
的Error
, Errorf
, FailNow
, Fatal
, FatalIf
方法,說明測試不經過,調用Log
方法用來記錄測試的信息。性能測試或壓力測試
壓力測試用來檢測函數(方法)的性能,和編寫單元功能測試的方法相似,此處再也不贅述,但須要注意如下幾點:
壓力測試用例必須遵循以下格式,其中XXX能夠是任意字母數字的組合,可是首字母不能是小寫字母
func BenchmarkXXX(b *testing.B) { ... }
go test
不會默認執行壓力測試的函數,若是要執行壓力測試須要帶上參數-test.bench
,語法:-test.bench="test_name_regex"
,例如go test -test.bench=".*"
表示測試所有的壓力測試函數testing.B.N
,以使測試能夠正常的運行_test.go
結尾在test目錄下建立 reflect_test.go
package test import ( "reflect" "testing" ) type Student struct { Name string Age int Class string Score int } func BenchmarkReflect_New(b *testing.B) { var s *Student sv := reflect.TypeOf(Student{}) b.ResetTimer() for i := 0; i < b.N; i++ { sn := reflect.New(sv) s, _ = sn.Interface().(*Student) } _ = s } func BenchmarkDirect_New(b *testing.B) { var s *Student b.ResetTimer() for i := 0; i < b.N; i++ { s = new(Student) } _ = s } func BenchmarkReflect_Set(b *testing.B) { var s *Student sv := reflect.TypeOf(Student{}) b.ResetTimer() for i := 0; i < b.N; i++ { sn := reflect.New(sv) s = sn.Interface().(*Student) s.Name = "Jerry" s.Age = 18 s.Class = "20005" s.Score = 100 } } func BenchmarkReflect_SetFieldByName(b *testing.B) { sv := reflect.TypeOf(Student{}) b.ResetTimer() for i := 0; i < b.N; i++ { sn := reflect.New(sv).Elem() sn.FieldByName("Name").SetString("Jerry") sn.FieldByName("Age").SetInt(18) sn.FieldByName("Class").SetString("20005") sn.FieldByName("Score").SetInt(100) } } func BenchmarkReflect_SetFieldByIndex(b *testing.B) { sv := reflect.TypeOf(Student{}) b.ResetTimer() for i := 0; i < b.N; i++ { sn := reflect.New(sv).Elem() sn.Field(0).SetString("Jerry") sn.Field(1).SetInt(18) sn.Field(2).SetString("20005") sn.Field(3).SetInt(100) } } func BenchmarkDirect_Set(b *testing.B) { var s *Student b.ResetTimer() for i := 0; i < b.N; i++ { s = new(Student) s.Name = "Jerry" s.Age = 18 s.Class = "20005" s.Score = 100 } }
在test目錄下,執行:
go test reflect_test.go -test.bench=".*"
結果以下
goos: windows goarch: amd64 BenchmarkReflect_New-4 20000000 84.9 ns/op BenchmarkDirect_New-4 30000000 50.6 ns/op BenchmarkReflect_Set-4 20000000 89.9 ns/op BenchmarkReflect_SetFieldByName-4 3000000 552 ns/op BenchmarkReflect_SetFieldByIndex-4 10000000 132 ns/op BenchmarkDirect_Set-4 30000000 53.0 ns/op PASS ok command-line-arguments 10.982s
上面的結果顯示咱們沒有執行任何TestXXX
的單元測試函數,顯示的結果只執行了壓力測試函數,以第三行爲例
BenchmarkReflect_New 函數執行了20000000次,每次的執行平均時間是84.9納秒。最後一行 command-line-arguments 10.982s,表明總的執行時間爲 10.982s。
若是隻想對某個函數測試,以BenchmarkReflect_New 爲例,執行命令
go test reflect_test.go -test.bench="BenchmarkReflect_New"
結果爲:
goos: windows goarch: amd64 BenchmarkReflect_New-4 20000000 84.9 ns/op PASS ok command-line-arguments 2.490s
若是測試整個目錄下的全部測試執行:
go test -test.bench=".*"
若是想顯示內存分配的次數和大小添加 -benchmem
go test reflect_test.go -benchmem -test.bench=".*"
goos: windows goarch: amd64 BenchmarkReflect_New-4 20000000 88.3 ns/op 48 B/op 1 allocs/op BenchmarkDirect_New-4 30000000 53.8 ns/op 48 B/op 1 allocs/op BenchmarkReflect_Set-4 20000000 90.9 ns/op 48 B/op 1 allocs/op BenchmarkReflect_SetFieldByName-4 3000000 564 ns/op 80 B/op 5 allocs/op BenchmarkReflect_SetFieldByIndex-4 10000000 135 ns/op 48 B/op 1 allocs/op BenchmarkDirect_Set-4 30000000 52.4 ns/op 48 B/op 1 allocs/op PASS ok command-line-arguments 12.955s
後兩列表明分配的內存大小和次數(48 B/op 1 allocs/op)
推薦gotests
它是編寫Go測試的一個Golang命令行工具,能夠根據目標源文件的函數和方法簽名生成表驅動的測試。將自動導入測試文件中的任何新依賴項。
參考:
https://studygolang.com/stati...
https://www.cnblogs.com/yjf51...