测试函数模式
基本测试函数模式
简单测试函数
func TestAdd(t *testing.T) {
result := Add(2, 3)
if result!= 5 {
t.Errorf("预期为 5,实际得到 %d", result)
}
}
表驱动测试
实现表驱动测试
func TestCalculations(t *testing.T) {
testCases := []struct {
name string
input int
expected int
}{
{"正数", 5, 25},
{"零", 0, 0},
{"负数", -3, 9},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result := Square(tc.input)
if result!= tc.expected {
t.Errorf("预期为 %d,实际得到 %d", tc.expected, result)
}
})
}
}
子测试和测试组
组织复杂测试
func TestUserOperations(t *testing.T) {
t.Run("创建用户", func(t *testing.T) {
// 用户创建测试
})
t.Run("更新用户", func(t *testing.T) {
// 用户更新测试
})
t.Run("删除用户", func(t *testing.T) {
// 用户删除测试
})
}
测试模式比较
模式 |
复杂度 |
可读性 |
灵活性 |
简单测试 |
低 |
高 |
低 |
表驱动测试 |
中等 |
中等 |
高 |
子测试 |
高 |
高 |
非常高 |
模拟和依赖注入
graph TD
A[测试函数] --> B{是否需要外部依赖}
B -->|是| C[创建模拟对象]
B -->|否| D[直接测试]
C --> E[将模拟对象注入函数]
E --> F[执行测试]
高级测试技术
参数化测试
func TestMultiply(t *testing.T) {
testCases := []struct {
a, b, expected int
}{
{2, 3, 6},
{0, 5, 0},
{-2, 4, -8},
}
for _, tc := range testCases {
result := Multiply(tc.a, tc.b)
if result!= tc.expected {
t.Errorf("Multiply(%d, %d) = %d; 期望为 %d",
tc.a, tc.b, result, tc.expected)
}
}
}
LabEx 测试建议
- 对于复杂场景,优先使用表驱动测试
- 使用子测试进行更好的测试组织
- 为了可测试性实现依赖注入
- 保持测试函数专注且简洁
测试中的错误处理
处理不同的错误场景
func TestErrorHandling(t *testing.T) {
t.Run("预期错误", func(t *testing.T) {
_, err := SomeFunction()
if err == nil {
t.Error("预期有错误,实际得到 nil")
}
})
t.Run("意外错误", func(t *testing.T) {
result, err := AnotherFunction()
if err!= nil {
t.Errorf("意外错误: %v", err)
}
// 额外的断言
})
}
通过掌握这些测试函数模式,开发者可以在 Go 语言中创建全面且可维护的测试套件。