SuperAPI AI 工具集

golang-testing

测试与质量

查看项目

更新于 10-13 17:25

技能介绍

用途

本技能为 Go 应用提供综合测试策略指导,覆盖单元测试、集成测试、基准测试与测试组织。当你在为 Go 代码编写单元测试、创建表驱动测试、用接口 Mock 依赖、用测试容器编写集成测试、对性能关键代码做基准测试,或组织测试套件与夹具时,可参考本技能。

主要能力

表驱动测试

基本模式:在 tests 切片中定义用例结构(name、输入、expected),通过 for 循环配合 t.Run(tt.name, ...) 执行子测试,失败时用 t.Errorf 输出实际值与期望值。

带错误用例的模式:在用例结构中增加 wantErr bool 与 errString 字段。当 wantErr 为真时,若 err 为 nil 用 t.Fatalf 终止并报错,再用 strings.Contains(err.Error(), tt.errString) 校验错误信息;否则在非预期错误时 t.Fatalf,并校验返回值。

基于接口的 Mock

定义接口:例如 UserRepository(FindByID、Save)与 EmailSender(Send)。

创建 Mock 实现:为 Mock 结构体定义 FindByIDFunc、SaveFunc 等函数字段,方法实现中若函数字段非 nil 则调用它,否则返回零值。

在测试中使用:构造 Mock 并赋值函数字段,按 ID 返回预期用户或 ErrNotFound,再注入到待测服务中,用 t.Run 分别验证“存在用户”与“不存在用户”场景;错误断言使用 errors.Is(err, ErrNotFound)。

Testify 断言

引入 github.com/stretchr/testify/assert 与 require。assert 在失败后继续执行,可用于 Equal、NotNil、Len、Contains、True、NoError、ErrorIs 等;require 在失败时停止测试,常用于前置条件(如 require.NoError、require.NotNil)。

使用 Testcontainers 的集成测试

在测试开头用 testing.Short() 判断,短模式下 t.Skip 跳过集成测试。通过 postgres.Run 启动 PostgreSQL 容器(如 postgres:15-alpine),设置数据库、用户名与密码,defer 调用 Terminate;用 ConnectionString 获取连接串,sql.Open 连接并执行迁移,随后构造仓储并测试保存与查询。

测试夹具

全局 Setup/Teardown:在 TestMain 中先执行 setup(),再 m.Run() 运行测试,最后执行 teardown() 并用 os.Exit 返回退出码。

每个测试的 Setup:封装 setupTest(t *testing.T) 辅助函数,内部调用 t.Helper(),创建测试数据库、仓储与服务,返回清理函数;测试中使用 defer cleanup()。

基准测试

基础形式:在 Benchmark 函数中循环 b.N 次调用被测函数。并行基准:使用 b.RunParallel 与 pb.Next()。子基准:遍历不同规模(如 100、1000、10000),在 b.Run 中生成数据后调用 b.ResetTimer() 并循环测试。

HTTP Handler 测试

构造 Mock 服务并注入 Handler。成功场景使用 httptest.NewRequest 与 httptest.NewRecorder,调用 handler 后断言状态码,并用 json.NewDecoder 解码响应体后校验字段。失败场景在调用前替换 Mock 行为返回错误,断言对应状态码(如 404)。

测试组织

文件结构示例:/internal/user 下放置 user.go、user_test.go(单元测试)、user_integration_test.go(集成测试,构建标签)、testdata/(夹具如 users.json)。

集成测试构建标签:文件顶部写 //go:build integration,运行时使用 go test -tags=integration ./...。

覆盖率:go test -coverprofile=coverage.out ./... 生成覆盖率;go tool cover -html=coverage.out 在浏览器查看;go test -cover ./... 查看覆盖率百分比。

最佳实践

测试行为而非实现,聚焦输入与输出;每个测试单一断言,保持聚焦清晰;使用 t.Helper() 标记辅助函数以改善错误报告;对独立测试使用 t.Parallel() 并行;采用描述性命名(如 TestUserService_CreateUser_WithInvalidEmail);覆盖边界情况,包括空输入、nil 值与边界条件;保持测试快速,使用 Mock 并通过 -short 跳过慢测试;避免测试污染,每个测试应相互独立。

适用场景与限制

适用于 Go 项目的单元测试、Mock 依赖、集成测试、性能基准与测试组织。集成测试依赖 Testcontainers 与容器运行时;示例中使用 PostgreSQL 容器与 testify 库;部分内容(如具体版本兼容性、CI 配置、收费情况)资料中暂未提供。