其實在很長一段時間,包括如今,我都很不喜歡寫單元測試。由於維護單元測試的成本很高。只有接口作了一點變動,那麼單元測試就必須作相同的變動,不然會致使測試不經過。html
那麼反過來,只要每次在提交代碼都去運行一次單元測試。這樣能夠很快的檢查到你對代碼更改是否影響了正常的業務邏輯,固然很大一部分是多是別人寫的那部分代碼。由於你不肯定本次的修改是否會影響到別人的那部分。因此單元測試仍是頗有必要的。git
go語言中單元測試是開箱即用的,官方提供了test
包。不用像PHP中須要單獨配置unit
。github
go test
命令是golang
單元測試的最基本使用golang
go test -v
是咱們比較經常使用的一個測試命令,用於執行測試,並打印額外的輸出。
新建一個項目用於示例微信
test │ main.go │ main_test.go
能夠看到我在main.go
的同級目錄建立了一個main_test.go
。go
語言中,單元測試的代碼必須跟須要測試的代碼在同一個包裏面。且命名必須遵循上面的那種結構規範,即:文件名_test.go
app
我在main.go
中建立兩個函數來分別獲得字符串相加的結果。函數
func JoinStrUseSprint(a,b string) string { return fmt.Sprintf("%s%s",a,b) } func JoinStrUseNor(a,b string) string { return a+b }
main_test.go
中的測試代碼工具
import "testing" func TestJoinStrUseNor(t *testing.T) { c := JoinStrUseNor("aaa","bbb") t.Log(c) } func TestJoinStrUseSprint(t *testing.T) { c := JoinStrUseSprint("aaa","bbb") t.Log(c) }
測試代碼中使用了 testing
包。並且每一個測試函數必須是以Test
開頭,有且只有一個參數t *testing.T
.t.Log()
函數爲輸出一段Log
日誌 這樣一個簡單的單元測試就完成了。單元測試
這個時候咱們運行go test
,結果以下。學習
test>go test PASS ok test 0.360s
能夠看到測試經過了。可是發現並無咱們指望的日誌輸出。若是咱們要獲得輸出的結果,咱們須要一個額外的參數,具體命令以下:
test>go test -v === RUN TestJoinStrUseNor --- PASS: TestJoinStrUseNor (0.00s) main_test.go:7: aaabbb === RUN TestJoinStrUseSprint --- PASS: TestJoinStrUseSprint (0.00s) main_test.go:12: aaabbb PASS ok test 0.480s
這個時候就能夠看到很詳細的測試流程與輸出的測試的log
。
不少時間咱們須要看單元測試的覆蓋率,這個時候咱們就須要
go test -cover
了。
咱們一樣使用上面的代碼。
test>go test -cover PASS coverage: 100.0% of statements ok test 0.440s
能夠看到單元代碼覆蓋率是100%
。這個是咱們在main
文件裏面在增長一個函數。
func JoinStrUseSprint(a,b string) string { return fmt.Sprintf("%s%s",a,b) } func JoinStrUseNor(a,b string) string { return a+b } func Run() { fmt.Println("I'm run,and I'm happy!") }
而後再執行cover
,獲得了覆蓋率爲66.7
。
test>go test -cover PASS coverage: 66.7% of statements ok test 0.398s
固然-v -cover
是能夠同事使用的。
test>go test -cover -v === RUN TestJoinStrUseNor --- PASS: TestJoinStrUseNor (0.00s) main_test.go:7: aaabbb === RUN TestJoinStrUseSprint --- PASS: TestJoinStrUseSprint (0.00s) main_test.go:12: aaabbb PASS coverage: 66.7% of statements ok test 0.429s
不少時候咱們須要將單元測試覆蓋率寫到一個文件中,這時候咱們再-cover
中增長一些額外的參數
>go test -coverprofile test.cover >go tool cover -html=test.cover -o coverage.html
-coverprofile filename
將覆蓋率的profile
寫入指定文件中。go tool cover -html=test.cover -o coverage.html
將覆蓋率的文件寫入可視化的html文件中打開converage.html
以下圖:
其實這裏能夠借用一個很好的第三方包。
go get github.com/smartystreets/goconvey
安裝完成,直接再項目目錄下執行
test>goconvey 2020/05/16 21:46:43 goconvey.go:61: Initial configuration: [host: 127.0.0.1] [port: 8080] [poll: 250ms] [cover: true] 2020/05/16 21:46:43 tester.go:19: Now configured to test 10 packages concurrently. 2020/05/16 21:46:43 goconvey.go:178: Serving HTTP at: http://127.0.0.1:8080 2020/05/16 21:46:43 integration.go:122: File system state modified, publishing current folders... 0 3179270049 2020/05/16 21:46:43 goconvey.go:118: Received request from watcher to execute tests... 2020/05/16 21:46:43 goconvey.go:105: Launching browser on 127.0.0.1:8080 2020/05/16 21:46:43 goconvey.go:111: exec: "start": executable file not found in %PATH% 2020/05/16 21:46:43 goconvey.go:113: 2020/05/16 21:46:44 executor.go:69: Executor status: 'executing' 2020/05/16 21:46:44 coordinator.go:46: Executing concurrent tests: test 2020/05/16 21:46:45 parser.go:24: [passed]: test
按照提示打開http://127.0.0.1:8080/
就會獲得一個很炫酷的覆蓋率界面
Golang
單元測試的基礎今天就暫時到這裏面,下面幾個testing
包的經常使用斷言方法.
// 輸出測試日誌 t.Logf() t.Logf() // 標記錯誤,但仍然執行後面的語句 t.Fail() // 獲取是否當前用例是執行錯誤的 t.Failed() // 錯誤輸出,等於 t.Logf 再執行 t.Fail() t.Errorf("%s", "run ErrorF") // 標記函數錯誤,並中斷後面的執行 t.FailNow() // 致命錯誤輸出,等同於調用了 t.Logf 而後調用 t.FailNow() t.Fatalf("%s", "run Fatelf")
下一篇咱們會寫到 golang
中的一些基準測試,以及一些測試的工具。
更多學習內容,同步更新到公衆號,期待與您一塊兒交流