目錄golang
概述運維
Go的單元測試ide
基礎知識函數
快速入門性能
進階單元測試
單個文件的測試測試
單個函數的測試ui
單元測試覆蓋率日誌
參考code
常言道,不會測試的程序猿不是好的產品經理!!!如今愈來愈多測試和運維的工做也須要研發來作了,本篇文章就來說講Go的單元測試。
單元測試(unit testing),是指對軟件中的最小可測試單元進行檢查和驗證。簡單說,就是將測試用例的運行結果與預期結果進行比較。
Go的單元測試Go有testing測試包,配合go test命令可以進行單元測試。
我的經常使用Fatalf,這裏就來具體說一下,其餘函數見參考的連接。
func (c *T) Logf(format string, args ...interface{})
Log 使用與 Printf 相同的格式化語法對它的參數進行格式化,而後將格式化後的文本記錄到錯誤日誌裏面。 若是輸入的格式化文本最末尾沒有出現新行,那麼將一個新行添加到格式化後的文本末尾。
1)對於測試來講,Logf 產生的格式化文本只會在測試失敗或者設置了 -test.v 標誌的狀況下被打印出來;
2)對於基準測試來講,爲了不 -test.v 標誌的值對測試的性能產生影響,Logf 產生的格式化文本總會被打印出來
func (c *T) FailNow()
將當前測試標識爲失敗並中止執行該測試,在此以後,測試過程將在下一個測試或者下一個基準測試中繼續。
FailNow 必須在運行測試函數或者基準測試函數的 goroutine 中調用,而不能在測試期間建立的 goroutine 中調用。調用 FailNow 不會致使其餘 goroutine 中止。
func (c *T) Fatalf(format string, args ...interface{})
調用 Fatalf 至關於在調用 Logf 以後調用 FailNow 。
項目結構
learnGo
└── main
├── compute.go
└── compute_test.go
compute.go
package main import "errors" func div(a,b int) (int,error) { if b != 0{ return a/b,nil } else{ return 0,errors.New("b is 0") } }
compute_test.go
package main import "testing" func TestDiv(t *testing.T) { res,_ := div(4,2) want := 2 if res != want{ t.Fatalf("期待:%d ,實際結果:%d",want,res) } }
main目錄下運行
go test -v
結果以下:
=== RUN TestDiv
--- PASS: TestDiv (0.00s)
PASS
ok learnGo/main 0.457s
以上咱們就針對main包的compute.go文件進行了單元測試。
查看更多的選項,可以使用
go help test go help testflag
咱們在main包中再添加str.go及str_test.go
str.go
package main func getSub(str string,start,end int) string { // 左閉右閉 if 0<=start&&start<end&&end<=len(str){ return str[start:end] }else{ return "" } }
str_test.go
package main import "testing" func TestGetSub(t *testing.T) { astr := "lady_killer9" // 包含開頭 res1 := getSub(astr,0,4) want1 := "lady" // 包含結尾 res2 := getSub(astr,4,len(astr)) want2 := "_killer9" // 範圍錯誤 res3 := getSub(astr,1,len(astr)+1) want3 := "" if res1 != want1{ t.Errorf("指望:%s,實際結果:%s",want1,res1) } if res2 != want2{ t.Errorf("指望:%s,實際結果:%s",want2,res2) } if res3 != want3{ t.Errorf("指望:%s,實際結果:%s",want3,res3) } }
運行 go test -v,獲得結果以下
=== RUN TestDiv
--- PASS: TestDiv (0.00s)
=== RUN TestGetSub
--- PASS: TestGetSub (0.00s)
PASS
ok learnGo/main 0.446s
go test會運行全部的單元測試,有時候咱們只想測試某個文件
若是隻是運行一個測試文件,可添加參數
go test -v 測試文件 源文件
運行go test -v str_test.go str.go, 結果以下:
=== RUN TestGetSub
--- PASS: TestGetSub (0.00s)
PASS
ok command-line-arguments 0.619s
咱們在compute.go中添加
func add(a,b int) int { return a+b }
在compute_test.go中添加
func TestAdd(t *testing.T) { a,b:=3,4 res := add(a,b) want := 7 if res != want{ t.Fatalf("期待:%d,實際結果:%d",want,res) } }
因爲對div函數未作改動,只想測試add函數,可使用參數-test.run指定測試函數
go test -v -test.run 測試函數
運行 go test -v -test.run TestAdd 結果以下:
=== RUN TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok learnGo/main 0.836s
測試應該全面,達到100%。
可使用-cover參數
go test -cover
結果以下:
PASS
coverage: 85.7% of statements
ok learnGo/main 0.505s
能夠看到,測試的並不全面,指定測試文件來查看。
go test -cover compute_test.go compute.go
ok command-line-arguments 0.314s coverage: 75.0% of statements
觀察發現,咱們缺乏了b爲0的分支,修改TestDiv函數爲
func TestDiv(t *testing.T) { res,_ := div(4,2) want := 2 if res != want{ t.Fatalf("期待:%d,實際結果:%d",want,res) } res,_ = div(3,0) want = 0 if res != want{ t.Fatalf("期待:%d,實際結果:%d",want,res) } }
測試後再看覆蓋率,結果以下
PASS
coverage: 100.0% of statements
ok learnGo/main 0.306s
做爲開發,基本的單元測試就能夠了,還能夠去了解基準測試、性能測試、壓力測試、黑盒測試等。
參考