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

105 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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** 创建 `providers``models``usage_stats`
- **AND** 字段类型符合 MySQL 迁移文件定义VARCHAR、DATETIME(3)、BOOLEAN 等)
- **AND** 索引 `idx_models_provider_id``idx_models_model_name``idx_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** 直接运行测试,不管理容器生命周期