
关于
Go 测试模式,包括表驱动测试、子测试、基准测试、模糊测试和测试覆盖率。遵循 TDD 方法论和惯用 Go 实践。
name: golang-testing description: Go 测试模式,包括表驱动测试、子测试、基准测试、模糊测试和测试覆盖率。遵循 TDD 方法论和惯用 Go 实践。 origin: ECC
Go 测试模式
全面的 Go 测试模式,用于编写可靠、可维护的测试,遵循 TDD 方法论。
何时激活
- 编写新的 Go 函数或方法
- 为现有代码添加测试覆盖
- 为性能关键代码创建基准测试
- 为输入验证实现模糊测试
- 在 Go 项目中遵循 TDD 工作流
Go 的 TDD 工作流
红-绿-重构循环
RED → 先编写一个失败的测试
GREEN → 编写最少代码使测试通过
REFACTOR → 在保持测试通过的同时改进代码
REPEAT → 继续下一个需求
Go 中的逐步 TDD
// 步骤 1:定义接口/签名
// calculator.go
package calculator
func Add(a, b int) int {
panic("not implemented") // 占位符
}
// 步骤 2:编写失败的测试(红色)
// calculator_test.go
package calculator
import "testing"
func TestAdd(t *testing.T) {
got := Add(2, 3)
want := 5
if got != want {
t.Errorf("Add(2, 3) = %d; want %d", got, want)
}
}
// 步骤 3:运行测试 - 验证失败
// $ go test
// --- FAIL: TestAdd (0.00s)
// panic: not implemented
// 步骤 4:实现最少代码(绿色)
func Add(a, b int) int {
return a + b
}
// 步骤 5:运行测试 - 验证通过
// $ go test
// PASS
// 步骤 6:如需重构,验证测试仍然通过
表驱动测试
Go 测试的标准模式。用最少的代码实现全面覆盖。
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive numbers", 2, 3, 5},
{"negative numbers", -1, -2, -3},
{"zero values", 0, 0, 0},
{"mixed signs", -1, 1, 0},
{"large numbers", 1000000, 2000000, 3000000},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Add(tt.a, tt.b)
if got != tt.expected {
t.Errorf("Add(%d, %d) = %d; want %d",
tt.a, tt.b, got, tt.expected)
}
})
}
}
带错误用例的表驱动测试
func TestParseConfig(t *testing.T) {
tests := []struct {
name string
input string
want *Config
wantErr bool
}{
{
name: "valid config",
input: `{"host": "localhost", "port": 8080}`,
want: &Config{Host: "localhost", Port: 8080},
},
{
name: "invalid JSON",
input: `{invalid}`,
wantErr: true,
},
{
name: "empty input",
input: "",
wantErr: true,
},
{
name: "minimal config",
input: `{}`,
want: &Config{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseConfig(tt.input)
if tt.wantErr {
if err == nil {
t.Error("expected error, got nil")
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("got %+v; want %+v", got, tt.want)
}
})
}
}
子测试和子基准测试
组织相关测试
func TestUser(t *testing.T) {
db := setupTestDB(t)
t.Run("Create", func(t *testing.T) {
user := &User{Name: "Alice"}
err := db.CreateUser(user)
if err != nil {
t.Fatalf("CreateUser failed: %v", err)
}
if user.ID == "" {
t.Error("expected user ID to be set")
}
})
t.Run("Get", func(t *testing.T) {
user, err := db.GetUser("alice-id")
if err != nil {
t.Fatalf("GetUser failed: %v", err)
}
if user.Name != "Alice" {
t.Errorf("got name %q; want %q", user.Name, "Alice")
}
})
t.Run("Update", func(t *testing.T) {
// ...
})
t.Run("Delete", func(t *testing.T) {
// ...
})
}
并行子测试
func TestParallel(t *testing.T) {
tests := []struct {
name string
input string
}{
{"case1", "input1"},
{"case2", "input2"},
{"case3", "input3"},
}
for _, tt := range tests {
tt := tt // 捕获范围变量
t.Run(tt.name, func(t *testing.T) {
t.Parallel() // 并行运行子测试
result := Process(tt.input)
_ = result
})
}
}
测试辅助函数
兼容工具
Claude CodeCursor
标签
测试

