Go | 了解「測試函式」應用
💬 簡介
在 Go 語言中,測試是確保程式正確性與穩定性的重要手段。Go 提供了一套簡單而強大的測試框架,讓開發者能夠方便地進行單元測試,從而提高程式的可靠性。本文將介紹 Go 語言中的測試函式應用,並探討如何編寫測試案例來提升程式質量。
圖片來源:Gophers
🔎 測試函式基礎概念
1️⃣ 什麼是測試函式?
測試函式是用來驗證程式邏輯是否正確的函式。在 Go 語言中,測試函式通常會以 Test
為前綴,並接受一個 testing.T
類型的參數。這個 T
類型提供了多種方法來報告錯誤和測試結果。
- 範例:簡單的測試函式執行測試:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package main
import "testing"
// 加法函式
func Add(a, b int) int {
return a + b
}
// 測試加法函式
func TestAdd(t *testing.T) {
result := Add(2, 3)
if result != 5 {
t.Errorf("Add(2, 3) failed, expected 5, got %d", result)
}
}1
go test
📝 上述測試函式會測試
Add
函式是否正確地將兩個數字相加。若結果不正確,則會顯示錯誤訊息。
2️⃣ 測試檔案命名規則
為了使 Go 測試框架正確識別測試檔案,必須遵循以下命名規則:
測試檔案的命名結尾:所有的測試檔案必須以
_test.go
作為檔案名稱的結尾。例如,對應math.go
的測試檔案應該是math_test.go
。測試函式命名規則:測試函式必須以
Test
開頭,並接受一個*testing.T
作為參數。測試函式的名稱應該與測試的功能對應,如TestAdd
。範例:
- 主程式檔案:math.go
- 測試檔案:math_test.go
- 測試函式:TestAdd
3️⃣ 測試函式命名規則
Go 語言的測試函式必須以 Test 開頭,並且接受一個 *testing.T
作為參數。這是 Go 測試框架的標準規範。
- 範例:錯誤的測試函式命名
1
2
3func AddTest() { // 錯誤,應該以 Test 開頭
// 測試內容
}📝 測試函式命名必須遵循
Test
開頭的規範,否則測試不會被執行。
🛠 測試函式進階應用
1️⃣ 測試表格
當有多組測試資料需要檢查時,可以使用測試表格(Test Table)來編寫多個測試案例。這樣能夠讓測試更加簡潔、易於擴展。
- 範例:使用測試表格測試加法函式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package main
import "testing"
// 測試加法函式
func TestAdd(t *testing.T) {
tests := []struct {
a, b, expected int
}{
{2, 3, 5},
{1, 1, 2},
{5, 5, 10},
}
for _, tt := range tests {
t.Run("Add", func(t *testing.T) {
result := Add(tt.a, tt.b)
if result != tt.expected {
t.Errorf("Add(%d, %d) failed, expected %d, got %d", tt.a, tt.b, tt.expected, result)
}
})
}
}📝 這樣的測試方式可以輕鬆地擴展到更多的測試案例,而無需為每個測試編寫單獨的函式。
2️⃣ 測試覆蓋率
Go 提供了測試覆蓋率(Test Coverage)功能,可以幫助我們了解測試的覆蓋範圍。以下是如何使用測試覆蓋率的範例。
執行測試並查看測試覆蓋率:
1
go test -cover
📝
-cover
會顯示測試覆蓋率的百分比,幫助你了解測試的完整性。查看詳細的覆蓋率報告:
1
2go test -coverprofile=coverage.out
go tool cover -html=coverage.out📝 這會生成一個 HTML 格式的報告,並顯示哪些程式碼被測試過,哪些沒有被測試過。這樣可以確保你測試到程式的各個部分,從而提高程式的穩定性。
📝 測試覆蓋率報告可以讓你找到測試的盲點,並進行補充,保證程式的各個區塊都被充分測試。
3️⃣ 測試壓力測試(Benchmark)
測試不僅限於單元測試和功能測試,還可以用來進行壓力測試(Benchmark),以評估程式的效能。Go 提供了內建的基準測試工具 testing.B
,用來測量函式的執行時間和效能。
- 範例:測試加法函式的執行效能執行基準測試:
1
2
3
4
5
6
7
8
9
10package main
import "testing"
// 測試加法函式的效能
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(2, 3)
}
}1
go test -bench .
📝
b.N
是測試的次數,go test -bench .
會根據你的基準測試計算出每次執行的平均時間。基準測試幫助你了解程式效能,並能進行性能優化。
🚀 測試函式的應用場景
1️⃣ 單元測試
單元測試是測試函式最常見的應用。你可以利用測試函式來檢查每一個單獨的函式是否按預期運作,確保程式的每個部分都能夠正常運行。
- 範例:測試計算平方根函式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package main
import (
"math"
"testing"
)
func Sqrt(x float64) float64 {
return math.Sqrt(x)
}
func TestSqrt(t *testing.T) {
result := Sqrt(9)
if result != 3 {
t.Errorf("Sqrt(9) failed, expected 3, got %f", result)
}
}📝 單元測試有助於保證每個小單元(函式)能正確執行,並能在未來的程式修改中保持穩定性。
2️⃣ 整合測試
整合測試用來檢查多個模組或函式協同工作時的行為。在 Go 中,測試可以用來檢查整個系統的集成度,確保不同部分能夠順利協作。
- 範例:測試 API 請求處理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package main
import (
"net/http"
"testing"
)
func TestAPI(t *testing.T) {
resp, err := http.Get("http://example.com/api/v1/resource")
if err != nil {
t.Fatal("API 請求失敗:", err)
}
if resp.StatusCode != http.StatusOK {
t.Errorf("API 返回狀態碼錯誤,期望 %d,得到 %d", http.StatusOK, resp.StatusCode)
}
}📝 整合測試幫助我們確認不同模組間的協同效應,確保系統整體的穩定性。
⚠️ 注意事項
📌 測試輸出
當使用 t.Errorf
或 t.Fatal
時,測試框架會輸出錯誤訊息。如果測試失敗,Go 會標記測試為失敗,並顯示錯誤內容。
📌 測試邊界情況
測試應該涵蓋所有邊界情況,包括極端數值、空輸入、無效輸入等,這樣才能確保程式在所有情況下都能正常運行。
📌 執行效率
過多的測試,特別是涉及到 IO 操作的測試,可能會影響程式的執行效率。應該在測試時適當設置測試的範圍,避免過多不必要的測試運行。
🎯 總結
- 測試函式是 Go 語言中用來檢查程式邏輯是否正確的重要工具。
- 測試函式應該遵循命名規範,並能夠驗證程式的正確性。
- 使用測試表格可以提高測試的可擴展性和可維護性。
- 測試覆蓋率有助於確保程式各個部分的測試完整性。
- 單元測試和整合測試是測試函式的兩個主要應用場景。
掌握測試函式的使用,將有助於你編寫更加健壯和可靠的 Go 程式碼。
最後建議回顧一下 Go | 菜鳥教學 目錄,了解其章節內容。
註:以上參考了
Go