1
0
Files
nex/openspec/specs/mysql-testing/spec.md
lanyuanxiaoyao 5b401e29cb feat: 新增 MySQL 专项测试能力
- 新增 backend/tests/mysql/ 目录,包含 Docker Compose 配置和测试文件
- 新增 Makefile 命令: test-mysql, test-mysql-up, test-mysql-down, test-mysql-quick
- 使用 build tag 控制测试启用,默认不运行
- 测试覆盖: 迁移正确性、外键约束、UNIQUE 约束、并发写入
- 发现 statsRepo.Record 存在并发 bug(检查-然后-操作竞态条件)
2026-04-23 12:25:55 +08:00

3.5 KiB
Raw Blame History

MySQL Testing

Purpose

提供 MySQL 数据库专项测试能力,验证迁移正确性、外键约束、并发写入等数据库特定行为。

Requirements

Requirement: MySQL 测试环境可启动

系统 SHALL 提供 Docker Compose 配置以启动 MySQL 8.0 测试环境。

Scenario: 启动 MySQL 测试容器

  • WHEN 执行 make test-mysql-up
  • THEN 启动 MySQL 8.0 容器,端口 13306
  • AND 创建数据库 nex_test
  • AND 容器数据存储在内存盘tmpfs

Scenario: 销毁 MySQL 测试容器

  • WHEN 执行 make test-mysql-down
  • THEN 停止并删除容器
  • AND 所有数据被销毁

Requirement: MySQL 测试可通过 build tag 控制

MySQL 测试 SHALL 使用 // +build mysql build tag默认不运行。

Scenario: 默认测试不包含 MySQL 测试

  • WHEN 执行 go test ./...
  • THEN 不运行 tests/mysql/ 下的测试

Scenario: 启用 MySQL 测试

  • WHEN 执行 go test -tags=mysql ./tests/mysql/...
  • THEN 运行所有 MySQL 测试

Requirement: MySQL 迁移正确执行

MySQL 测试 SHALL 验证迁移脚本在 MySQL 环境下正确执行。

Scenario: 迁移创建所有表

  • WHEN 运行 MySQL 迁移
  • THEN 创建 providersmodelsusage_stats
  • AND 字段类型符合 MySQL 迁移文件定义VARCHAR、DATETIME(3)、BOOLEAN 等)
  • AND 索引 idx_models_provider_ididx_models_model_nameidx_usage_stats_provider_model_date 创建成功

Scenario: 迁移可重复执行

  • WHEN 在已迁移的数据库上再次运行迁移
  • THEN 不报错,数据库状态不变

Requirement: MySQL 外键约束生效

MySQL 测试 SHALL 验证外键约束行为符合预期。

Scenario: 外键约束阻止无效引用

  • WHEN 创建 model 时 provider_id 不存在
  • THEN 操作失败,返回外键约束错误

Scenario: 级联删除生效

  • WHEN 删除 provider
  • THEN 该 provider 的所有 models 被级联删除

Requirement: MySQL UNIQUE 约束生效

MySQL 测试 SHALL 验证 UNIQUE 约束行为符合预期。

Scenario: models 表 UNIQUE 约束

  • WHEN 尝试创建相同 (provider_id, model_name) 组合的 model
  • THEN 操作失败,返回唯一约束错误

Scenario: usage_stats 表 UNIQUE 约束

  • WHEN 尝试创建相同 (provider_id, model_name, date) 组合的 usage_stats
  • THEN 操作失败,返回唯一约束错误

Requirement: MySQL 并发写入正确

MySQL 测试 SHALL 验证并发写入不丢失数据。

Scenario: 并发记录 usage_stats

  • WHEN 10 个 goroutine 并发调用 statsRepo.Record(providerID, modelName)
  • THEN 最终 request_count 等于 10
  • AND 无数据丢失或重复

Scenario: 并发创建相同 provider

  • WHEN 10 个 goroutine 并发创建相同 ID 的 provider
  • THEN 仅 1 个成功,其他 9 个失败

Scenario: 并发创建相同 model

  • WHEN 10 个 goroutine 并发创建相同 (provider_id, model_name) 的 model
  • THEN 仅 1 个成功,其他 9 个失败

Requirement: MySQL 测试命令完整

Makefile SHALL 提供完整的 MySQL 测试命令。

Scenario: 完整测试流程

  • WHEN 执行 make test-mysql
  • THEN 启动 Docker MySQL
  • AND 等待 MySQL 就绪
  • AND 运行所有 MySQL 测试
  • AND 销毁容器

Scenario: 快速测试(容器已运行)

  • WHEN 执行 make test-mysql-quick
  • THEN 直接运行测试,不管理容器生命周期