iT邦幫忙

2023 iThome 鐵人賽

DAY 26
0
自我挑戰組

Go in 3o系列 第 26

[Day26] Go in 30 - Debug - 單元測試(unit test)

  • 分享至 

  • xImage
  •  

一、本篇提要

最後要來看Go程式撰寫簡單的單元測試,並使用 go test 來替我們測試函式與套件。
這次我們會沿用之前的shape程式範例,並稍作改寫。

二、撰寫單元測試

step1. 之前的shape套件

目錄結構:

https://ithelp.ithome.com.tw/upload/images/20231005/20162693YxgZ3IxZrT.png

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 應該是一個介面,它描述了所有可以計算面積的幾何形狀應有的方法。

step2. 撰寫測試檔

Go 測試檔名稱不重要,但結尾比必須要加上 " _test ",例如 : shape_test.go,而且這個檔案中必須宣告至少一個測試函式 :

func Test<名稱>(t *testing.T)

同樣的函式名稱也不重要,但必須以Test開頭,例如: TestGetName。
此函式會接收一個型別為 testing.T 的指標變 t (來自 testing 套件)。

現在我們在shape子目錄下建立測試檔 shape_test.go,並撰寫兩個測試函式。
目錄結構 :
https://ithelp.ithome.com.tw/upload/images/20231005/20162693Sxs3bGzTQm.png

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 檔名" 的寫法。

https://ithelp.ithome.com.tw/upload/images/20231005/20162693M5itRnr2yp.png

接下來,為了模擬測試失敗的情境,我們故意更改 shape 套件中 Rectangle 結構的 name() 返回名稱為 "矩形",並且使 Triangle 結構的 area() 函數有錯誤的計算公式。然後再執行測試。

https://ithelp.ithome.com.tw/upload/images/20231005/20162693z5mcMGRjJ4.png

那麼以上就是簡單的unit test,當然不只這些,可以參考 [testing 套件] (https://golang.org/pkg/testing/)對於 testing.T 型別提供一系列方法,讓你決定如何完成單元測試 。


上一篇
[Day25] Go in 30 - Debug
下一篇
[Day27] Go in 30 - 時間處理
系列文
Go in 3o30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言