testing 包基本用法
testing 包提供了 Go 包的自动化测试支持。
基本测试函数
// math_test.go
package math
import "testing"
// 测试函数必须以 Test 开头
func TestAdd(t *testing.T) {
result := Add(2, 3)
if result != 5 {
t.Errorf("Add(2, 3) = %d; want 5", result)
}
}
func TestSubtract(t *testing.T) {
result := Subtract(5, 3)
if result != 2 {
t.Errorf("Subtract(5, 3) = %d; want 2", result)
}
}
表驱动测试
package math
import "testing"
func TestMultiply(t *testing.T) {
tests := []struct {
a, b int
expected int
}{
{2, 3, 6},
{0, 5, 0},
{-2, 3, -6},
{-2, -3, 6},
}
for _, tt := range tests {
result := Multiply(tt.a, tt.b)
if result != tt.expected {
t.Errorf("Multiply(%d, %d) = %d; want %d",
tt.a, tt.b, result, tt.expected)
}
}
}
子测试
package math
import "testing"
func TestDivide(t *testing.T) {
t.Run("正常除法", func(t *testing.T) {
result, err := Divide(10, 2)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if result != 5 {
t.Errorf("got %v, want 5", result)
}
})
t.Run("除以零", func(t *testing.T) {
_, err := Divide(10, 0)
if err == nil {
t.Error("expected error for division by zero")
}
})
}
基准测试
package math
import "testing"
// 基准测试函数以 Benchmark 开头
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(1, 2)
}
}
func BenchmarkFibonacci(b *testing.B) {
for i := 0; i < b.N; i++ {
Fibonacci(20)
}
}
// 比较不同实现的性能
func BenchmarkFibonacciMemo(b *testing.B) {
memo := make(map[int]int)
for i := 0; i < b.N; i++ {
fibMemo(20, memo)
}
}
示例测试
package math
import "fmt"
// 示例函数以 Example 开头
func ExampleAdd() {
result := Add(2, 3)
fmt.Println(result)
// Output: 5
}
func ExampleDivide() {
result, _ := Divide(10, 2)
fmt.Println(result)
// Output: 5
}
测试辅助函数
package math
import (
"path/filepath"
"runtime"
"testing"
)
// 获取测试数据路径
func testdataPath(t *testing.T, name string) string {
t.Helper() // 标记为辅助函数
_, file, _, ok := runtime.Caller(0)
if !ok {
t.Fatal("无法获取当前文件路径")
}
return filepath.Join(filepath.Dir(file), "testdata", name)
}
func TestWithFile(t *testing.T) {
path := testdataPath(t, "input.txt")
// 使用 path 进行测试...
}
并行测试
package math
import (
"testing"
"time"
)
func TestParallel(t *testing.T) {
tests := []struct {
name string
delay time.Duration
}{
{"fast", 100 * time.Millisecond},
{"slow", 500 * time.Millisecond},
}
for _, tt := range tests {
tt := tt // 捕获循环变量
t.Run(tt.name, func(t *testing.T) {
t.Parallel() // 标记为并行测试
time.Sleep(tt.delay)
})
}
}
跳过测试
package math
import (
"runtime"
"testing"
)
func TestWindowsOnly(t *testing.T) {
if runtime.GOOS != "windows" {
t.Skip("此测试仅在 Windows 上运行")
}
// Windows 特定测试...
}
func TestWithShortFlag(t *testing.T) {
if testing.Short() {
t.Skip("跳过长时间运行的测试")
}
// 长时间运行的测试...
}
总结
| 测试类型 | 函数前缀 | 说明 |
|---|---|---|
| 单元测试 | Test |
基本的单元测试 |
| 基准测试 | Benchmark |
性能测试 |
| 示例测试 | Example |
文档示例测试 |
| 模糊测试 | Fuzz |
模糊测试 (Go 1.18+) |
# 运行所有测试
go test
# 显示详细输出
go test -v
# 运行基准测试
go test -bench=.
# 显示覆盖率
go test -cover
# 生成覆盖率报告
go test -coverprofile=coverage.out
go tool cover -html=coverage.out