[Go] 單元測試與性能測試
本文會介紹 Go 的單元測試方式,會使用預設的套件來進行單元測試跟性能測試
單元測試
在寫單元測試時,有一些知識需要了解 :
- 單元測試是測試最小的程式碼單位, 通常是一個 function 或者一個 method
- 一個測試案例僅測試一個功能,不同 test case 之間不應該有相依性
- 不與外部系統互動,不會有 I/O、網路請求與資料庫操作等等
接下來會使用 Go 的內建套件 testing
搭配 mockgen
來撰寫單元測試,安裝前需要確保 GOBIN 在 PATH 中
go get github.com/golang/mock/gomock
go install github.com/golang/mock/mockgen
在下面這個範例中,我們有一個 Calculator
的 interface,裡面有一個 Add
的 method,接著有一個 ComputeSum
的 function 會呼叫 Calculator
的 Add
method
go mod init unittest
package calculator
type Calculator interface {
Add(a, b int) int
}
func ComputeSum(calc Calculator, a, b int) int {
return calc.Add(a, b)
}
首先我們需要 mock Calculator
的 interface,方便做出一些假的結果來避免去與外部作互動
接著我們可以使用 mockgen
來產生 mock 的程式碼
-source
: 要 mock 的檔案-destination
: 產生的 mock 檔案-package
: mock 檔案的 package 名稱,沒寫的話預設是mock_<source_package_name>
mockgen -source calculator.go -destination mocks/mock_calculator.go -package mocks
最後就可以來寫單元測試了,我們可以使用 testing
套件來撰寫單元測試,記得檔案名稱要以 _test.go
結尾,測試的 function 名稱要以 Test
開頭
package calculator_test
import (
"testing"
calculator "unittest"
"unittest/mocks"
"github.com/golang/mock/gomock"
)
func TestComputeSum(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockCalc := mocks.NewMockCalculator(ctrl)
a, b := 1, 2
mockCalc.EXPECT().Add(a, b).Return(a + b)
result := calculator.ComputeSum(mockCalc, a, b)
if result != 3 {
t.Errorf("ComputeSum(%d, %d) = %d; want 3", a, b, result)
}
}
接著介紹一些單元測試常用的指令 :
-
go test
: 執行所有的單元測試 -
go test -v
: 執行所有的單元測試並且顯示詳細的結果 -
go test -run <test_function_name>
: 執行特定的單元測試,可以使用正規表達式也可以只寫部分名稱 -
go test -run <file_name>
: 執行特定的檔案的單元測試 -
go test -cover
: 顯示測試覆蓋率 -
go test -coverprofile coverage.out
: 產生測試覆蓋率的檔案 -
go tool cover -html=coverage.out
: 顯示測試覆蓋率的 HTML -
start coverage.html
: 用瀏覽器開啟測試覆蓋率的 HTML (適用於 Windows,Mac 可以使用open coverage.html
)