1
0

Merge branch 'dev-testcase-analysis'

This commit is contained in:
2026-04-22 13:23:32 +08:00
32 changed files with 3374 additions and 729 deletions

View File

@@ -31,6 +31,57 @@
- **THEN** SHALL 测试请求转换、响应转换、流式转换
- **THEN** SHALL 验证转换的准确性和完整性
#### Scenario: config 加载管道集成测试
- **WHEN** 运行 config 加载管道的集成测试
- **THEN** SHALL 验证 LoadConfigFromPath 正确加载默认值
- **THEN** SHALL 验证环境变量(`NEX_` 前缀)覆盖默认值
- **THEN** SHALL 验证 YAML 配置文件正确读取
- **THEN** SHALL 验证优先级链CLI 参数 > 环境变量 > YAML 文件 > 默认值
- **THEN** SHALL 验证首次启动自动创建配置文件
- **THEN** SHALL 验证 SaveConfig 后重新 LoadConfig 数据一致
#### Scenario: handler 错误分支测试
- **WHEN** 运行 handler 层的单元测试
- **THEN** SHALL 覆盖 ModelHandler.CreateModel 的所有错误分支ErrProviderNotFound(400)、ErrDuplicateModel(409)、通用错误(500)
- **THEN** SHALL 覆盖 ProviderHandler.UpdateProvider 的所有错误分支ErrRecordNotFound(404)、ErrImmutableField(400)、通用错误(500)
- **THEN** SHALL 验证每个错误分支返回正确的 HTTP 状态码和错误响应格式
#### Scenario: service 聚合逻辑测试
- **WHEN** 运行 service 层的单元测试
- **THEN** SHALL 覆盖 StatsService.Aggregate 的所有分组模式byProvider、byModel、byDate
- **THEN** SHALL 验证 aggregateByModel 正确拼接和拆分 providerID/modelName key
- **THEN** SHALL 验证 aggregateByDate 正确格式化日期并聚合
- **THEN** SHALL 覆盖空结果集、同名模型不同 provider 等边界场景
#### Scenario: provider service 工具方法测试
- **WHEN** 运行 provider service 的单元测试
- **THEN** SHALL 验证 isUniqueConstraintError 正确识别 SQLite 唯一约束冲突错误消息
- **THEN** SHALL 验证 List 方法对每个 provider 调用 MaskAPIKey
#### Scenario: engine 降级路径测试
- **WHEN** 运行 conversion engine 的单元测试
- **THEN** SHALL 验证 convertEmbeddingBody 在 decode 失败时返回原始 bodypassthrough
- **THEN** SHALL 验证 convertRerankBody 在 decode 失败时返回原始 bodypassthrough
- **THEN** SHALL 验证降级过程不 panic、不返回空 body
#### Scenario: openai decoder 边界场景测试
- **WHEN** 运行 openai decoder 的单元测试
- **THEN** SHALL 覆盖 assistant message content 为 JSON 数组格式的解析text/refusal 类型)
- **THEN** SHALL 验证 decodeContentParts 正确提取文本内容和拒绝消息
#### Scenario: 业务逻辑负面测试
- **WHEN** 运行业务逻辑负面测试
- **THEN** SHALL 覆盖 JSON 格式错误请求体的处理
- **THEN** SHALL 覆盖并发创建相同 provider + model 的重复检测
- **THEN** SHALL 覆盖空结果集查询的正确处理
### Requirement: 建立集成测试体系
系统 SHALL 建立集成测试体系,覆盖 API 端到端流程。
@@ -63,26 +114,28 @@
#### Scenario: 测试数据库初始化
- **WHEN** 编写需要数据库的测试
- **THEN** SHALL 提供测试数据库初始化函数
- **THEN** SHALL 使用临时数据库文件
- **THEN** SHALL 提供统一的测试数据库初始化函数 `SetupTestDB`
- **THEN** SHALL 统一使用 SQLite `:memory:` + `MaxOpenConns(1)` 策略
- **THEN** SHALL 在测试结束后自动清理
- **THEN** 所有测试包 SHALL 通过 `tests.SetupTestDB()` 获取测试数据库,不允许各自独立实现
#### Scenario: Mock 工具
- **WHEN** 编写需要 Mock 的测试
- **THEN** SHALL 提供 Mock 接口实现
- **THEN** SHALL 支持常见 Mock 场景
- **THEN** SHALL 易于使用和扩展
- **THEN** SHALL 使用 mockgen 自动生成 mock 实现
- **THEN** SHALL 在接口定义文件中使用 `//go:generate` 注解标注生成命令
- **THEN** 生成的 mock SHALL 放置在 `tests/mocks/` 目录下
- **THEN** SHALL 覆盖 service 和 repository 接口的 mock 生成
### Requirement: 达到测试覆盖率目标
系统 SHALL 达到 > 80% 的测试覆盖率。
系统 SHALL 达到 > 85% 的测试覆盖率。
#### Scenario: 总体覆盖率
- **WHEN** 运行所有测试并生成覆盖率报告
- **THEN** 总体覆盖率 SHALL 大于 80%
- **THEN** 核心包覆盖率 SHALL 大于 85%
- **THEN** 总体覆盖率 SHALL 大于 85%
- **THEN** 核心包config、service、handler、conversion、repository覆盖率 SHALL 大于 85%
#### Scenario: 覆盖率报告生成
@@ -102,6 +155,14 @@
- **THEN** SHALL 显示测试结果
- **THEN** SHALL 在测试失败时返回非零退出码
#### Scenario: 分类测试命令
- **WHEN** 执行 `make test-unit` 命令
- **THEN** SHALL 仅运行 `./internal/...``./pkg/...` 下的单元测试
- **WHEN** 执行 `make test-integration` 命令
- **THEN** SHALL 仅运行 `./tests/...` 下的集成测试
#### Scenario: 覆盖率检查命令
- **WHEN** 执行 `make test-coverage` 命令
@@ -170,3 +231,33 @@
- **WHEN** 在 frontend/ 目录执行 E2E 测试命令
- **THEN** SHALL 启动 Playwright 运行 E2E 测试
- **THEN** SHALL 在测试失败时返回非零退出码
### Requirement: 清理 ProviderRepository 死代码
系统 SHALL 移除 ProviderRepository 中未被调用的重复方法。
#### Scenario: 移除死代码方法
- **WHEN** 审查 ProviderRepository 接口
- **THEN** SHALL 移除 `ListEnabledModels()` 方法声明和实现
- **THEN** SHALL 移除 `FindByProviderAndModelName()` 方法声明和实现
- **THEN** SHALL 确保所有现有调用者通过 ModelRepository 访问等效功能
- **THEN** SHALL 不影响任何运行时行为
### Requirement: 使用 mockgen 生成 mock
系统 SHALL 使用 mockgen 为接口自动生成 mock 实现,替代手写 mock。
#### Scenario: mock 生成配置
- **WHEN** 在接口定义文件中添加 `//go:generate mockgen` 注解
- **THEN** SHALL 为 `ProviderService``ModelService``RoutingService``StatsService` 接口生成 mock
- **THEN** SHALL 为 `ModelRepository``ProviderRepository``StatsRepository` 接口生成 mock
- **THEN** SHALL 为 `ProviderClient` 接口生成 mock
- **THEN** 生成的 mock SHALL 输出到 `tests/mocks/` 目录
#### Scenario: 替换手写 mock
- **WHEN** mockgen 生成的 mock 就绪
- **THEN** handler 测试中的手写 mock SHALL 被替换为生成的 mock
- **THEN** 所有测试 SHALL 继续通过,行为不变