現代程式開發早已經離不開測試。不如說,當測試程式沒有完成就不能說開發已經完成,必須把測試與功能實作的部分作為一個整體看待。Golang原生就支援單元測試與Benchmarks,可以想見對其重視的程度。我們今天就來瞭解一下測試的功能要怎麼實現。
先來看一個簡單的例子:
package gotest
import (
"errors"
)
func Division(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("除數不可為0")
}
return a / b, nil
}
這個函數會把第一個參數除以第二個參數,眾所皆知除數不可為零。所以我們做了一個錯誤處理,當除數為零時,會回傳一個錯誤訊息。將上面的檔案存檔為gotest.go
,在測試的時候,檔名是相當重要的!
參照要測試的檔案,我們新開一個文件命名為gotest_test.go
,這邊有幾點需要注意:
_test
,這樣go test
才會知道這是測試檔案不是一般檔案。這點跟ruby專案使用rspec
作為測試框架時,檔名後必須加上_spec.rb
一樣。testing
這個內建的包。Test
開頭,後面所接的第一個英文字符一定要大寫,不然會抓不到Test
這個關鍵字。比方說TestisBlock
就是一個不合法的測試函數名稱,因為根據大小寫所抓到的第一個字是Testis
而不是Test
。testing.T
,我們可以用來記錄錯誤或是測試狀態。說了這麼多注意事項,我們來實際看一下測試的例子:
package gotest
import (
"testing"
)
func Test_Division_1(t *testing.T) {
if i, e := Division(6, 2); i != 3 || e != nil {
t.Error("除法函數沒通過")
} else {
t.Log("測試通過")
}
}
func Test_Division_2(t *testing.T) {
t.Error("沒通過")
}
這邊要特別說明一下,因為我的編輯環境vs code有安裝go套件,所以神奇的事情發生了!
你可以發現在測試函數上方有一行灰色的小字run test | debug test
,我們可以不透過命令行,直接透過UI來執行go測試,相當的便利!
如果我們執行第一個測試案例Test_Division_1
,會得到下面的輸出:
Running tool: /usr/local/bin/go test -timeout 30s -run ^Test_Division_1$
PASS
ok _/Users/Chenbater/projects/go/day20 0.004s
Success: Tests passed.
6/2
理所當然的會通過,如果我們把測試案例的數字改寫為(1, 0)
,這樣會發生什麼事呢?
Running tool: /usr/local/bin/go test -timeout 30s -run ^Test_Division_1$
--- FAIL: Test_Division_1 (0.00s)
/Users/Chenbater/projects/go/day20/gotest_test.go:9: 除法函數沒通過測試
FAIL
exit status 1
FAIL _/Users/Chenbater/projects/go/day20 0.004s
Error: Tests failed.
測試未通過,而且得到我們預先設置好的錯誤訊息。透過這樣的例子是不是有了一些基本概念了呢?
如果說同一個測試案例我們想測試很多組資料呢,如果因此複製貼上很多相同結構只有參數不同的測試函數,肯定會覺得相當愚蠢,所以我們可以用一個表格來紀錄多組測試案例,來看一下這個例子:
func Test_Division_table(t *testing.T) {
tables := []struct {
x float64
y float64
}{
{3, 1},
{6, 2},
{9, 3},
{8, 2},
}
for _, table := range tables {
if i, e := Division(table.x, table.y); i != 3 || e != nil {
t.Error("除法函數沒通過測試")
} else {
t.Log("測試通過")
}
}
}
這樣我們可以一次執行四組案例,執行後可以得到下面的結果:
Running tool: /usr/local/bin/go test -timeout 30s -run ^Test_Division_table$
--- FAIL: Test_Division_table (0.00s)
/Users/Chenbater/projects/go/day20/gotest_test.go:30: 測試通過
/Users/Chenbater/projects/go/day20/gotest_test.go:30: 測試通過
/Users/Chenbater/projects/go/day20/gotest_test.go:30: 測試通過
/Users/Chenbater/projects/go/day20/gotest_test.go:28: 除法函數沒通過測試
FAIL
exit status 1
FAIL _/Users/Chenbater/projects/go/day20 0.004s
Error: Tests failed.
如我們所預期的,最後一個案例沒有通過。