最後要來看Go程式撰寫簡單的單元測試,並使用 go test 來替我們測試函式與套件。
這次我們會沿用之前的shape程式範例,並稍作改寫。
目錄結構:
shape 套件 :
package shape
type Shape interface {
area() float64
name() string
}
type Triangle struct {
Base float64
Height float64
}
type Rectangle struct {
Length float64
Width float64
}
type Square struct {
Side float64
}
func GetName(shape Shape) string {
return shape.name()
}
func GetArea(shape Shape) float64 {
return shape.area()
}
func (t Triangle) area() float64 {
return (t.Base * t.Height) / 2
}
func (t Triangle) name() string {
return "三角形"
}
func (t Rectangle) area() float64 {
return t.Length * t.Width
}
func (t Rectangle) name() string {
return "長方形"
}
func (t Square) area() float64 {
return t.Side * t.Side
}
func (t Square) name() string {
return "正方形"
}
main的部分也改寫為 :
package main
import (
"fmt"
"project01/shape"
)
func main() {
triangle := shape.Triangle{Base: 15.5, Height: 20.1}
rectangle := shape.Rectangle{Length: 20, Width: 10}
square := shape.Square{Side: 10}
shapes := [...]shape.Shape{triangle, rectangle, square}
for _, item := range shapes {
fmt.Printf("%s的面積: %.2f\n", shape.GetName(item), shape.GetArea(item))
}
}
創建形狀陣列:
shapes := [...]shape.Shape{triangle, rectangle, square}
我們定義了一個形狀的陣列,其中 shape.Shape 應該是一個介面,它描述了所有可以計算面積的幾何形狀應有的方法。
Go 測試檔名稱不重要,但結尾比必須要加上 " _test ",例如 : shape_test.go,而且這個檔案中必須宣告至少一個測試函式 :
func Test<名稱>(t *testing.T)
同樣的函式名稱也不重要,但必須以Test開頭,例如: TestGetName。
此函式會接收一個型別為 testing.T 的指標變 t (來自 testing 套件)。
現在我們在shape子目錄下建立測試檔 shape_test.go,並撰寫兩個測試函式。
目錄結構 :
package shape // 由於測試對象是shape,故宣告為同一套件
import "testing"
//測試 shape 套件 GetName() 函式
func TestGetName(t *testing.T) {
// 測試用結構
triangle := Triangle{Base: 15.5, Height: 20.1}
rectangle := Rectangle{Length: 20, Width: 10}
square := Square{Side: 10}
if name := GetName(triangle); name != "三角形" {
t.Errorf("%T 形狀錯誤: %v", triangle, name)
}
if name := GetName(rectangle); name != "長方形" {
t.Errorf("%T 形狀錯誤: %v", rectangle, name)
}
if name := GetName(square); name != "正方形" {
t.Errorf("%T 形狀錯誤: %v", square, name)
}
}
//測試 shape 套件 GetArea() 函式
func TestGetArea(t *testing.T) {
// 測試用結構,我們寫在func內宣告在pakage層級,為的是不去影響shape套件本身
triangle := Triangle{Base: 15.5, Height: 20.1}
rectangle := Rectangle{Length: 20, Width: 10}
square := Square{Side: 10}
if value := GetArea(triangle); value != 155.775 {
t.Errorf("%T 面積錯誤: %v", triangle, value)
}
if value := GetArea(rectangle); value != 200 {
t.Errorf("%T 面積錯誤: %v", rectangle, value)
}
if value := GetArea(square); value != 100 {
t.Errorf("%T 面積錯誤: %v", square, value)
}
}
測試函式會使用這些結構來測試 shape 套件的公開函式的回傳值,以確認結果是否與已知的正確結果相符。
接下來,我們可以使用 go test 進行測試。
go test 會自動尋找目錄中Go測試檔並執行它,如果只想執行特定測試檔,可以用"go test 檔名" 的寫法。
接下來,為了模擬測試失敗的情境,我們故意更改 shape 套件中 Rectangle 結構的 name() 返回名稱為 "矩形",並且使 Triangle 結構的 area() 函數有錯誤的計算公式。然後再執行測試。
那麼以上就是簡單的unit test,當然不只這些,可以參考 [testing 套件] (https://golang.org/pkg/testing/)對於 testing.T 型別提供一系列方法,讓你決定如何完成單元測試 。