All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 15s
- 创建全局单例连接池,性能提升 6-7 倍 - 实现 NewTestTransaction/GetTestRedis/CleanTestRedisKeys - 移除旧的 SetupTestDB/TeardownTestDB API - 迁移所有测试文件到新方案(47 个文件) - 添加测试连接管理规范文档 - 更新 AGENTS.md 和 README.md 性能对比: - 旧方案:~71 秒(204 测试) - 新方案:~10.5 秒(首次初始化 + 后续复用) - 内存占用降低约 80% - 网络连接数从 204 降至 1
7.9 KiB
7.9 KiB
testing-standards Specification
Purpose
TBD - created by archiving change optimize-test-db-connection. Update Purpose after archive.
Requirements
Requirement: 全局单例数据库连接
测试套件 SHALL 使用全局单例模式管理数据库连接,避免重复创建连接。
技术约束:
- 使用
sync.Once确保连接只初始化一次 - 整个测试套件(多个测试文件)共享同一个
*gorm.DB实例 AutoMigrate只在首次连接时执行一次- 连接失败应导致测试跳过,不应 panic
Scenario: 多个测试共享连接
- GIVEN 测试套件包含 100+ 个测试用例
- WHEN 执行
go test ./... - THEN 只创建一次数据库连接
- AND 所有测试共享同一个连接池
- AND
AutoMigrate只执行一次
Scenario: 连接失败自动跳过
- GIVEN 测试数据库不可用
- WHEN 执行测试
- THEN 测试标记为 SKIP 而非 FAIL
- AND 显示跳过原因: "无法连接测试数据库"
Requirement: 全局单例 Redis 连接
测试套件 SHALL 使用全局单例模式管理 Redis 连接,避免重复创建连接。
技术约束:
- 使用
sync.Once确保连接只初始化一次 - 整个测试套件共享同一个
*redis.Client实例 - 连接失败应导致测试跳过,不应 panic
Scenario: 多个测试共享 Redis 连接
- GIVEN 测试套件包含 50+ 个需要 Redis 的测试
- WHEN 执行
go test ./... - THEN 只创建一次 Redis 连接
- AND 所有测试共享同一个 Redis 客户端
Requirement: 事务隔离
每个测试 SHALL 在独立事务中运行,并在测试结束后自动回滚,确保测试间完全隔离。
技术约束:
- 使用
db.Begin()开启事务 - 使用
t.Cleanup(func() { tx.Rollback() })注册回滚函数 - 即使测试 panic 也能确保事务回滚(Go 的 defer/Cleanup 机制保证)
- 事务隔离级别使用数据库默认值(PostgreSQL: READ COMMITTED)
Scenario: 测试数据自动回滚
- GIVEN 测试 A 创建了用户 "test_user"
- WHEN 测试 A 完成
- THEN 事务自动回滚
- AND 数据库中不存在 "test_user"
- AND 测试 B 看不到测试 A 的数据
Scenario: 测试 panic 后自动清理
- GIVEN 测试 C 在执行中触发 panic
- WHEN panic 发生
- THEN
t.Cleanup仍然执行 - AND 事务被回滚
- AND 数据库状态恢复到测试前
Requirement: Redis 键自动清理
每个测试 SHALL 使用测试名称作为 Redis 键前缀,并在测试结束后自动清理。
技术约束:
- 键前缀格式:
test:{TestName}:* - 使用
t.Cleanup()注册清理函数 - 清理逻辑:
KEYS pattern+DEL keys... - 支持嵌套测试(子测试继承父测试的前缀)
Scenario: 测试前清理已有键
- GIVEN Redis 中存在键
test:TestUserCreate:user:1(上次运行残留) - WHEN 测试
TestUserCreate开始 - THEN 清理所有匹配
test:TestUserCreate:*的键 - AND Redis 处于干净状态
Scenario: 测试后自动清理
- GIVEN 测试
TestUserLogin创建了键test:TestUserLogin:session:abc - WHEN 测试完成
- THEN
t.Cleanup自动删除所有test:TestUserLogin:*键 - AND Redis 中不残留测试数据
Requirement: 向后兼容性
新的连接管理方案 SHALL 与现有的 SetupTestDB/TeardownTestDB 方案共存,支持渐进迁移。
技术约束:
- 保留
testutils/setup.go中的旧函数 - 在旧函数上添加
// Deprecated注释 - 新旧方案可在同一测试套件中共存
- 迁移指引作为注释提供
Scenario: 旧测试正常运行
- GIVEN 测试文件使用
SetupTestDB(t) - WHEN 执行测试
- THEN 测试正常通过
- AND 不影响其他使用新方案的测试
Scenario: 新旧方案混用
- GIVEN 测试套件包含 50% 旧方案测试,50% 新方案测试
- WHEN 执行
go test ./... - THEN 所有测试正常运行
- AND 性能逐步提升(随迁移进度)
Requirement: 简洁的测试代码
测试用例 SHALL 使用简洁的 API 创建事务和清理 Redis,减少样板代码。
API 约束:
NewTestTransaction(t)返回事务,自动注册回滚CleanTestRedisKeys(t)清理 Redis,自动注册清理函数- 无需显式
defer或手动清理 - 函数名清晰表达意图
Scenario: 最小化样板代码
- GIVEN 开发者编写新测试
- WHEN 使用新 API
- THEN 只需 2 行代码完成设置:
tx := testutils.NewTestTransaction(t) testutils.CleanTestRedisKeys(t) - AND 无需关心清理逻辑
Scenario: 对比旧方案
- GIVEN 旧方案需要 4 行代码:
db, redisClient := testutils.SetupTestDB(t) defer testutils.TeardownTestDB(t, db, redisClient) - WHEN 使用新方案
- THEN 只需 2 行,且意图更清晰
Requirement: 性能优化
测试套件运行速度 SHALL 显著提升,通过减少连接创建和表结构检查次数。
性能目标:
- 连接创建次数: 从 N(测试数量) 降低到 1
- AutoMigrate 次数: 从 N 降低到 1
- 测试套件总耗时提升: ≥ 5 倍
- 内存占用降低: ≥ 70%
Scenario: 大型测试套件性能提升
- GIVEN 测试套件包含 200 个测试
- WHEN 全部迁移到新方案
- THEN 总耗时从 ~70 秒降低到 ~10 秒
- AND 性能提升约 7 倍
Scenario: 连接复用
- GIVEN 测试套件运行期间
- WHEN 监控数据库连接数
- THEN 最多保持 1 个连接(来自连接池)
- AND 无重复连接创建
Requirement: 子测试事务行为
使用 t.Run 创建子测试时,SHALL 明确子测试与父事务的关系。
技术约束:
- 父测试开启的事务,子测试默认共享
- 如需隔离,子测试必须开启独立事务
- 不支持在事务内使用
t.Parallel()(GORM 事务非线程安全)
Scenario: 子测试共享父事务
- GIVEN 父测试开启事务
tx := NewTestTransaction(t) - WHEN 子测试使用
t.Run运行 - THEN 子测试共享父事务
- AND 所有数据在父测试结束时统一回滚
Scenario: 子测试独立事务
- GIVEN 子测试需要数据隔离
- WHEN 子测试内调用
tx := NewTestTransaction(t) - THEN 子测试拥有独立事务
- AND 子测试结束时独立回滚
Requirement: Table-Driven Tests 支持
Table-Driven Tests SHALL 正确处理事务共享和回滚行为。
技术约束:
- 父测试开启事务,所有 cases 共享
- 所有 cases 的数据在测试结束时统一回滚
- 如需 case 间隔离,每个 case 开启独立事务
Scenario: Cases 共享父事务
- GIVEN Table-Driven Test 有 5 个 test cases
- WHEN 父测试开启事务
- THEN 所有 cases 在同一事务中运行
- AND Case 1 的数据对 Case 2 可见
- AND 所有数据在测试结束时统一回滚
Scenario: Cases 独立事务
- GIVEN 每个 case 需要独立数据环境
- WHEN 每个 case 内调用
NewTestTransaction(t) - THEN Cases 间完全隔离
- AND Case 1 的数据对 Case 2 不可见
Requirement: 规范文档化
测试连接管理规范 SHALL 以文档形式提供,并集成到项目开发规范中。
文档要求:
- 路径:
docs/testing/test-connection-guide.md - 包含: 原理说明、使用示例、最佳实践、常见陷阱
- 在
AGENTS.md中引用,作为唯一标准 - 包含性能对比数据和迁移指南
Scenario: 开发者查找测试规范
- GIVEN 新加入的开发者需要编写测试
- WHEN 查阅
AGENTS.md测试规范章节 - THEN 能找到
test-connection-guide.md的引用 - AND 文档包含完整的 API 说明和示例
Scenario: 迁移指南
- GIVEN 现有测试使用旧的
SetupTestDB - WHEN 查阅迁移指南
- THEN 提供逐步迁移步骤
- AND 包含前后代码对比示例