iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 24
2
Modern Web

Go into Web!系列 第 24

Day 24 | 自己測一下程式好嗎?淺入單元測試(二)

昨天說完了基礎的單元測試,今天讓我們好好的了解如何透過更好的方式來進行單元測試。

testify

從昨天的範例中可以看出,如果我們要比對結果是否正確必須要自己寫 if/else 來判斷,這樣程式並不簡潔,當然我們可以自行封裝方法,但已經有大神幫我們寫好的專屬的測試庫 - testify

安裝

透過 go get 的方式進行安裝

go get -u github.com/stretchr/testify

使用

我們這邊來改寫昨天的單元測試方法

func TestAdd(t *testing.T) {
	for i, in := range input {
		result := Add(in[0], in[1])
		t.Log("in =", in, "output should be", output[i], " actual output equal", result)
		if output[i] == result {
			t.Log("Pass")
		} else {
			t.Error("Case", i, "is failed")
		}
	}
}

首先我們匯入 testify 中的 require 模組

import "github.com/stretchr/testify/require"

接著我們將原先的 if 取代成 require.Equal 方法,testify 幫我們封裝了許多好用的方法,包括了 EqualContainsEmpty 等等,讓我們可以不用再寫 if 來判斷

func TestAdd(t *testing.T) {
	for i, in := range input {
		result := Add(in[0], in[1])
		t.Log("in =", in, "output should be", output[i], " actual output equal", result)
		require.Equal(t, output[i], result)
	}
}

Suite

什麼是 suite

suite 是由 testify 所提供的 package,他可以幫我們針對每個測試案例做 前置作業後置操作,讓我們可以更完整的掌握要測試案例的生命週期。

使用

建立 struct

首先我們定義一個 struct 名為 Suite,在這個結構裡面繼承了 suiteSuite

type Suite struct {
	suite.Suite
	finalTest   int
	finalResult int
	testInput   [][]int
	testOutput  []int
}

設定初始化

suite 有提供 SetupSuite 方法讓我們實作,因此可以在此方法內進行參數的初始化,在這邊我們先將測試的參數進行初始化。

func (s *Suite) SetupSuite() {
	s.testInput = [][]int{
		{1, 2},
		{2, 3},
		{3, 4},
	}
	s.testOutput = []int{3, 5, 7}
	s.finalTest = 0
	for _, n := range s.testOutput {
		s.finalResult += n
	}
}

設定測試方法

要使用 suite 來做單元測試,我們可以在剛才建立的 Suite struct 中實現方法,如果要測試 Add 方法的話,就實作 TestAdd

func (s *Suite) TestAdd() {
	for i, in := range s.testInput {
		result := Add(in[0], in[1])
		s.finalTest += result
		require.Equal(s.T(), s.testOutput[i], result, "should be equal")
	}
}

設定結束點

在測試案例測完的時候,可以實作 AfterTest 方法來檢查此測試用例是否有誤。

func (s *Suite) AfterTest(_, _ string) {
	require.Equal(s.T(), s.finalResult, s.finalTest, "should be equal")
}

設定起始點

透過實作 TestStart 方法來設定起始點,裡面就使用 suite.Run 的方式將 Suite struct 進行初始化。

func TestStart(t *testing.T) {
	suite.Run(t, new(Suite))
}

測試

將上述的程式集合起來程式碼如下

package cal

import (
	"github.com/stretchr/testify/require"
	"github.com/stretchr/testify/suite"
	"testing"
)

type Suite struct {
	suite.Suite
	finalTest   int
	finalResult int
	testInput   [][]int
	testOutput  []int
}

func (s *Suite) SetupSuite() {
	s.testInput = [][]int{
		{1, 2},
		{2, 3},
		{3, 4},
	}
	s.testOutput = []int{3, 5, 7}
	s.finalTest = 0
	for _, n := range s.testOutput {
		s.finalResult += n
	}
}

//AfterTest 用於測試完畢之後的檢查
func (s *Suite) AfterTest(_, _ string) {
	require.Equal(s.T(), s.finalResult, s.finalTest, "should be equal")
}
//TestStart 為測試程式進入點
func TestStart(t *testing.T) {
	suite.Run(t, new(Suite))
}

func (s *Suite) TestAdd() {
	for i, in := range s.testInput {
		result := Add(in[0], in[1])
		s.finalTest += result
		require.Equal(s.T(), s.testOutput[i], result, "should be equal")
	}
}

正確執行

依照正確執行,執行結果如下

=== RUN   TestStart
=== RUN   TestStart/TestAdd
--- PASS: TestStart (0.00s)
    --- PASS: TestStart/TestAdd (0.00s)
PASS

錯誤執行

我們可以透過修改 SetupSuite 將測試結果改成錯誤的

func (s *Suite) SetupSuite() {
	s.testInput = [][]int{
		{1, 2},
		{2, 3},
		{3, 4},
	}
	s.testOutput = []int{3, 5, 8}
	s.finalTest = 0
	for _, n := range s.testOutput {
		s.finalResult += n
	}
}

接著重新運行一次測試程式,顯示結果如下

=== RUN   TestStart
=== RUN   TestStart/TestAdd
    TestStart/TestAdd: cal_test.go:44: 
        	Error Trace:	cal_test.go:44
        	Error:      	Not equal: 
        	            	expected: 8
        	            	actual  : 7
        	Test:       	TestStart/TestAdd
        	Messages:   	should be equal
    TestStart/TestAdd: cal_test.go:33: 
        	Error Trace:	cal_test.go:33
        	            				suite.go:137
        	            				panic.go:617
        	            				testing.go:657
        	            				cal_test.go:44
        	Error:      	Not equal: 
        	            	expected: 16
        	            	actual  : 15
        	Test:       	TestStart/TestAdd
        	Messages:   	should be equal
--- FAIL: TestStart (0.00s)
    --- FAIL: TestStart/TestAdd (0.00s)


Expected :16
Actual   :15
<Click to see difference>


FAIL

從上述結果可以看到,他會顯示預期結果與實際運行結果不符,顯示相關的訊息,這樣的方式可以讓我們更好查出錯誤在哪。

小結

今天透過簡單介紹 testify 這個單元測試的 package,讓我們在撰寫單元測試可以更快速且精準。


上一篇
Day 23 | 自己測一下程式好嗎?淺入單元測試(一)
下一篇
Day 25 | 使用 Docker 封裝與運行 Go 程式(一)
系列文
Go into Web!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言