题目
实现并测试字符串反转函数,要求使用表驱动测试和子测试
信息
- 类型:问答
- 难度:⭐⭐
考点
表驱动测试, 子测试, 测试覆盖率, testing包使用
快速回答
实现要点:
- 使用
t.Run()为每个测试用例创建子测试 - 通过结构体切片定义表驱动测试用例
- 测试函数需处理边界条件(空字符串、Unicode字符等)
- 使用
go test -cover检查测试覆盖率
示例函数实现:
func Reverse(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
## 解析
原理说明
表驱动测试通过结构体切片定义测试用例,避免重复代码。子测试使用 t.Run() 隔离每个用例:
- 独立执行:子测试失败不影响其他用例
- 精准定位:测试输出明确标识失败用例
- 并行控制:支持
t.Parallel()并行测试
代码示例
测试函数实现:
func TestReverse(t *testing.T) {
tests := []struct {
name string
input string
want string
}{
{"empty", "", ""},
{"ascii", "hello", "olleh"},
{"unicode", "こんにちは", "はちにんこ"},
{"space", "a b c", "c b a"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Reverse(tt.input); got != tt.want {
t.Errorf("Reverse() = %v, want %v", got, tt.want)
}
})
}
}最佳实践
- 用例命名:子测试名称应描述用例特征(如
unicode) - 错误输出:使用
t.Errorf包含输入/输出值 - 覆盖率:运行
go test -coverprofile=coverage.out && go tool cover -html=coverage.out可视化覆盖 - 边界测试:必须包含空字符串、单字符、特殊字符用例
常见错误
- 未处理Unicode:直接用
[]byte会导致乱码(应用[]rune) - 缺少子测试:未用
t.Run()导致所有用例合并显示 - 覆盖率不足:未测试多字节字符或空输入
- 数据污染:在子测试外修改测试数据(应使用局部变量)
扩展知识
- Golden文件:复杂输出可用
testdata/*.golden存储预期结果 - 并行测试:在子测试内调用
t.Parallel()加速长测试 - 测试Main函数:使用
TestMain(m *testing.M)全局设置/清理 - 模糊测试:Go 1.18+ 可用
f.Add()和f.Fuzz()自动生成用例