iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 20
1
Software Development

啥物碗Golang? 30天就Go系列 第 20

Testing 測試

現代程式開發早已經離不開測試。不如說,當測試程式沒有完成就不能說開發已經完成,必須把測試與功能實作的部分作為一個整體看待。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套件,所以神奇的事情發生了!
go testing on vs code
你可以發現在測試函數上方有一行灰色的小字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.

測試未通過,而且得到我們預先設置好的錯誤訊息。透過這樣的例子是不是有了一些基本概念了呢?

Test table

如果說同一個測試案例我們想測試很多組資料呢,如果因此複製貼上很多相同結構只有參數不同的測試函數,肯定會覺得相當愚蠢,所以我們可以用一個表格來紀錄多組測試案例,來看一下這個例子:

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.

如我們所預期的,最後一個案例沒有通過。

Reference


上一篇
Error Handling 錯誤處理
下一篇
Benchmarks 壓力測試
系列文
啥物碗Golang? 30天就Go30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言