easyai-ai-gateway/docs/test/loopback-test-checklist.md
wangbo 265b7e3cc6 docs(test): 添加 AI Gateway 回环测试任务清单
- 新增 loopback-test-checklist.md 文档
- 包含完整的测试原则和执行环境记录表格
- 提供测试数据准备、任务执行链路、历史记录验证流程
- 添加定价规则、权限控制、运行策略和限流控制测试用例
- 设计验收总表、失败处理记录和清理清单
- 支持 Chat、图像、视频等多模态功能验证
- 集成计费、认证、授权等核心业务逻辑测试
- 提供详细的测试状态跟踪和结果记录模板
2026-05-11 00:43:59 +08:00

189 lines
19 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.

# AI Gateway 回环测试任务清单
本文档用于记录 AI Gateway 回环测试的准备、执行、断言和最终结果。执行过程中,所有测试必须跑通;失败项先标记为 `失败`,定位原因并修复后重新执行,通过后再把状态更新为 `成功`,同时写入具体结果。
## 1. 测试原则
- 测试批次使用统一 `loopbackRunId`,建议格式:`loopback-YYYYMMDD-HHMMSS`。
- 用户提前创建真实测试平台、真实测试模型和真实平台 KEY这些真实对象只用于成功链路验证。
- 内部测试用的用户、用户组、API Key、定价规则、访问规则、运行策略、模拟平台和模拟模型可以由测试过程创建统一带 `loopbackRunId` 元数据。
- 成功链路可以走真实客户端,必须拿到真实返回结果;策略链路必须走 `runMode=simulation` 或模拟平台,不提交真实任务。
- 每个通过项都要写入任务 ID、结果 ID、计费金额、关键事件或错误码等可复查证据。
- 任一测试失败时,不能只记录失败;必须继续排查到代码、配置或测试数据层面的原因,修复后重跑。
## 2. 执行环境记录
| 项目 | 值 |
| --- | --- |
| 测试批次 `loopbackRunId` | 待填写 |
| Gateway 地址 | 待填写 |
| 数据库地址 | 待填写 |
| 管理员账号 / token | 待填写 |
| 真实 Chat 模型 | 用户创建后填写 |
| 真实图像测试模型 | `doubao-4.5图像编辑` |
| 真实文生图模型 | `doubao-4.5图像编辑`,若平台配置中该模型不支持文生图则补充用户创建的文生图模型 |
| 真实图生图模型 | `doubao-4.5图像编辑` |
| 真实视频生成模型 | `豆包Seedance-1.5-pro` |
| 视频能力覆盖 | 文生视频、图生视频、首尾帧 |
| 测试源图 | 测试过程自行选择并上传,记录 source image URL |
| 测试 mask 图 | 测试过程自行生成并上传,记录 mask image URL |
| 测试首帧图 | 测试过程自行选择并上传,记录 first frame URL |
| 测试尾帧图 | 测试过程自行选择并上传,记录 last frame URL |
| 真实平台 KEY | 用户创建后填写 |
| 执行人 | 待填写 |
| 开始时间 | 待填写 |
| 结束时间 | 待填写 |
状态约定:`未执行`、`执行中`、`成功`、`失败`、`阻塞`。
## 3. 测试数据准备
| ID | 任务 | 接口 / 方式 | 成功判定 | 状态 | 结果记录 |
| --- | --- | --- | --- | --- | --- |
| SETUP-01 | 确认服务可用 | `GET /healthz`、`GET /readyz` | `healthz.ok=true``readyz.ok=true` | 未执行 | 待填写 |
| SETUP-02 | 准备管理员权限 | 本地注册 / 登录,必要时将测试用户提升为 `admin``manager` | `GET /api/v1/me` 返回 `role` 具备 `manager` 权限 | 未执行 | 待填写 |
| SETUP-03 | 记录用户提供的真实平台、模型和 KEY | `GET /api/v1/platforms`、`GET /api/v1/models` | Chat 模型、`doubao-4.5图像编辑`、`豆包Seedance-1.5-pro` 均已启用,并能被管理员看到 | 未执行 | 待填写 |
| SETUP-04 | 创建内部测试用户组 | `POST /api/v1/user-groups` | 创建 `loopback-allow-group`、`loopback-deny-group`、`loopback-limit-group` | 未执行 | 待填写 |
| SETUP-05 | 创建内部测试 API Key | `POST /api/v1/api-keys` | 至少创建全量 Key、Chat-only Key、受限 Key、禁用验证 Key | 未执行 | 待填写 |
| SETUP-06 | 创建内部定价规则集 | `POST /api/v1/pricing/rule-sets` | 规则覆盖 `text_input`、`text_output`、`image`、`image_edit`、`video` | 未执行 | 待填写 |
| SETUP-07 | 创建内部运行策略集 | `POST /api/v1/runtime/policy-sets` | 规则覆盖重试、错误禁用、降级、RPM、TPM、并发 | 未执行 | 待填写 |
| SETUP-08 | 创建模拟平台和模拟模型 | `POST /api/v1/platforms`、`POST /api/v1/platforms/{platformID}/models` | 模拟平台 `credentials.mode=simulation`,同一模型至少有失败候选和成功候选 | 未执行 | 待填写 |
| SETUP-09 | 准备图像 / 视频测试素材 | 本地选择或生成图片,必要时先上传为网关可访问 URL | source、mask、first frame、last frame 均可被 Gateway 读取;素材不依赖易失效外链 | 未执行 | 待填写 |
建议内部策略命名:
- 定价规则集:`loopback-pricing-{loopbackRunId}`。
- 运行策略集:`loopback-runtime-{loopbackRunId}`。
- 用户组:`loopback-allow-{loopbackRunId}`、`loopback-deny-{loopbackRunId}`、`loopback-limit-{loopbackRunId}`。
- 模拟平台:`loopback-sim-fail-{loopbackRunId}`、`loopback-sim-success-{loopbackRunId}`。
测试图片选择原则:
- 使用清晰、非敏感、无版权争议的普通物体或风景图,避免真人肖像和复杂文字。
- 图生图源图建议使用 1:1 或 4:3 PNG/JPGmask 使用黑白图,明确覆盖需要编辑的区域。
- 图生视频和首尾帧建议使用 16:9 横图;首帧和尾帧主体一致,但动作、视角或场景状态有可观察变化。
- 所有图片先上传或转换成 Gateway 能读取的 URL再写入本表环境记录。
默认素材方案:
- source image本地生成或选取一张“明亮桌面上的红色马克杯”普通物体图用于 `doubao-4.5图像编辑` 图生图和 `豆包Seedance-1.5-pro` 图生视频。
- mask image基于 source image 生成黑白 mask覆盖背景或杯身局部验证图像编辑是否真正使用参考图和 mask。
- first frame16:9 桌面物体静止画面,主体与 source image 保持一致。
- last frame同一主体移动位置或状态变化的 16:9 画面,用于首尾帧视频验证过渡是否生效。
## 4. 完整任务执行链路
每个能力都需要验证同步响应、任务详情、事件流、历史记录和计费字段。非兼容路由预期返回 `202 Accepted``task`;兼容路由预期直接返回 OpenAI 风格结果。
| ID | 能力 | 请求 | 成功判定 | 状态 | 结果记录 |
| --- | --- | --- | --- | --- | --- |
| TASK-CHAT-01 | Chat 成功 | `POST /api/v1/chat/completions`,真实 Chat 模型 | `task.status=succeeded``result.object=chat.completion``choices[0].message.content` 非空 | 未执行 | taskId、requestId、content 摘要、charge 待填写 |
| TASK-CHAT-02 | Chat 兼容路由成功 | `POST /v1/chat/completions`,真实 Chat 模型 | HTTP 200返回 `object=chat.completion`,内容非空 | 未执行 | requestId、content 摘要待填写 |
| TASK-IMAGE-01 | 文生图成功 | `POST /api/v1/images/generations`,模型 `doubao-4.5图像编辑` 或用户补充的文生图模型 | `task.status=succeeded``result.id` 非空,`data[0].url` 或文件 URL 可访问 | 未执行 | taskId、image URL、charge 待填写 |
| TASK-IMAGE-02 | 图生图成功 | `POST /api/v1/images/edits`,模型 `doubao-4.5图像编辑`,传入测试源图和 mask | `task.status=succeeded``result.id` 非空,`data[0].url` 或文件 URL 可访问 | 未执行 | taskId、source URL、mask URL、image URL、charge 待填写 |
| TASK-VIDEO-01 | 文生视频成功 | `POST /api/v1/videos/generations`,模型 `豆包Seedance-1.5-pro`,仅传 prompt | `task.status=succeeded`,返回可下载或可播放的视频结果,任务事件完整 | 未执行 | taskId、video URL、duration、charge 待填写 |
| TASK-VIDEO-02 | 图生视频成功 | `POST /api/v1/videos/generations`,模型 `豆包Seedance-1.5-pro`,传 prompt 和测试源图 | `task.status=succeeded`,输出视频能体现源图主体,任务事件完整 | 未执行 | taskId、source URL、video URL、duration、charge 待填写 |
| TASK-VIDEO-03 | 首尾帧视频成功 | `POST /api/v1/videos/generations`,模型 `豆包Seedance-1.5-pro`,传 prompt、首帧图、尾帧图 | `task.status=succeeded`,输出视频首尾状态与输入帧一致或可明确对应 | 未执行 | taskId、first frame URL、last frame URL、video URL、duration、charge 待填写 |
| TASK-EVENT-01 | 任务事件保存 | 对上述每个 task 调 `GET /api/v1/tasks/{taskID}/events` | 至少包含 `task.progress``task.completed`seq 连续递增 | 未执行 | 每个 task 的事件数量和关键 phase 待填写 |
| TASK-DETAIL-01 | 任务详情查询 | 对上述每个 task 调 `GET /api/v1/tasks/{taskID}` | 返回 `requestId`、`resolvedModel`、`usage`、`metrics`、`billingSummary`、`finalChargeAmount` | 未执行 | 每个 task 的详情摘要待填写 |
## 5. 历史任务记录保存
`docs/design.md` 中说明业务对话、绘图历史最终仍可由 `server-main` 汇总Gateway 侧必须保存执行事实源。这里按 Gateway 当前数据模型验证 `gateway_tasks`、`gateway_task_attempts`、`gateway_task_events` 和 callback outbox。若产品口径确实是“历史人物记录”需要补充对应业务表和接口后再加专项用例。
| ID | 任务 | 验证点 | 成功判定 | 状态 | 结果记录 |
| --- | --- | --- | --- | --- | --- |
| HISTORY-01 | 任务主记录保存 | `gateway_tasks``GET /api/v1/tasks/{taskID}` | 每个成功任务均有一条主记录状态、模型、用户、租户、API Key、结果和计费字段完整 | 未执行 | taskId 列表待填写 |
| HISTORY-02 | 尝试记录保存 | `gateway_task_attempts` | 每次候选客户端执行都有 attempt成功和失败尝试均保存 request/response/error 快照 | 未执行 | attempt 数量待填写 |
| HISTORY-03 | 事件记录保存 | `gateway_task_events` | 事件包含接收、运行、重试、完成或失败,`simulated` 标记准确 | 未执行 | 事件摘要待填写 |
| HISTORY-04 | 回调 outbox 保存 | `gateway_task_callback_outbox`,开启回调配置时验证 | 每个 task event 写入幂等 outbox`task_id + seq + callback_url` 唯一 | 未执行 | outbox 数量待填写 |
| HISTORY-05 | API Key 身份保存 | 任务详情或数据库字段 | `apiKeyId`、`apiKeyName`、`apiKeyPrefix` 可追溯到发起 Key | 未执行 | key 信息待填写 |
## 6. 定价规则绑定与扣费计算
定价必须验证“绑定有效”和“计算正确”两个层面。测试时建议使用独立内部规则集,价格设置成易人工核算的值。
| ID | 任务 | 请求 / 数据 | 成功判定 | 状态 | 结果记录 |
| --- | --- | --- | --- | --- | --- |
| PRICE-01 | 绑定规则集到基准模型 | `PATCH /api/v1/catalog/base-models/{baseModelID}` 或创建自定义基准模型 | 模型返回 `pricingRuleSetId=loopback-pricing-*` | 未执行 | baseModelId、ruleSetId 待填写 |
| PRICE-02 | 绑定规则集到平台模型 | `POST /api/v1/platforms/{platformID}/models` 或更新模型 | 平台模型返回 `pricingRuleSetId=loopback-pricing-*``billingConfigOverride` 生效 | 未执行 | platformModelId 待填写 |
| PRICE-03 | Chat 预估计费 | `POST /api/v1/pricing/estimate`Chat 请求体 | 返回 `resolver=effective-pricing-v1``text_input` 与 `text_output` 金额按 tokens 计算 | 未执行 | estimate items 待填写 |
| PRICE-04 | Chat 最终扣费 | 执行 Chat 成功任务 | `finalChargeAmount=sum(billings.amount)`,输入/输出 token 数与 usage 对齐 | 未执行 | usage、billings、finalChargeAmount 待填写 |
| PRICE-05 | 文生图扣费 | 执行文生图成功任务 | `resourceType=image`,数量、尺寸、质量权重参与计算 | 未执行 | billings 待填写 |
| PRICE-06 | 图生图扣费 | 执行图生图成功任务 | `resourceType=image_edit`,优先使用编辑价格,缺省时回退图片价格 | 未执行 | billings 待填写 |
| PRICE-07 | 视频扣费 | 执行文生视频、图生视频、首尾帧视频成功任务 | `resourceType=video`,数量、分辨率或时长权重按规则计算,三类视频请求均有计费记录 | 未执行 | billings 待填写 |
| PRICE-08 | 用户组折扣 | 将测试用户放入带 `billingDiscountPolicy.discountFactor` 的用户组后执行 | `discountFactor` 同时体现模型折扣和用户组折扣,最终金额符合乘积 | 未执行 | groupId、discount、charge 待填写 |
## 7. 权限控制
权限控制分为认证可用性、API Key 层访问规则、用户组层访问规则。API Key 的 `scopes` 也要纳入检查;如果当前实现只保存不拦截,需要按失败项修复。
| ID | 层级 | 任务 | 成功判定 | 状态 | 结果记录 |
| --- | --- | --- | --- | --- | --- |
| AUTH-01 | API Key | 全量 Key 可调用 Chat、文生图、图生图、文生视频、图生视频、首尾帧视频 | 所有真实任务链路均成功,任务记录含对应 Key 身份 | 未执行 | taskId 列表待填写 |
| AUTH-02 | API Key | 禁用 Key 后调用任一任务 | HTTP 401不能创建新任务 | 未执行 | 状态码和响应待填写 |
| AUTH-03 | API Key | 删除 Key 后调用任一任务 | HTTP 401不能创建新任务 | 未执行 | 状态码和响应待填写 |
| AUTH-04 | API Key | Chat-only Key 调图片或视频能力 | 应被拒绝;若当前仅保存 scopes 不拦截,则标记失败并修复 | 未执行 | 状态码和修复结论待填写 |
| AUTH-05 | API Key | 给 API Key 添加 `deny platform_model` 访问规则后调用被拒模型 | `ListModelCandidates` 无候选,任务返回 404 或失败码 `no_model_candidate` | 未执行 | ruleId、响应待填写 |
| AUTH-06 | API Key | 给 API Key 添加 `allow platform_model` 后调用允许模型 | 允许模型成功,未被 allow 的受控资源不可用 | 未执行 | ruleId、taskId 待填写 |
| AUTH-07 | 用户组 | 给用户组添加 `deny platform_model` 后该组用户调用 | 该组用户被拒,非该组用户不受影响 | 未执行 | groupId、响应待填写 |
| AUTH-08 | 用户组 | 给用户组添加 `allow platform_model``minPermissionLevel` | 权限等级不足被拒,满足等级后成功 | 未执行 | groupId、角色、响应待填写 |
| AUTH-09 | 可见模型列表 | `GET /api/v1/playground/models` | 列表同样遵守 API Key / 用户组访问规则,不只在执行时过滤 | 未执行 | 模型数量和过滤结果待填写 |
## 8. 运行策略与模拟客户端
本节只使用模拟平台或 `runMode=simulation`,通过请求体 `simulationProfile` 或平台凭证 `simulationFailure` 制造不同错误。已知模拟客户端支持 `success`、`retryable_failure`、`fatal_failure` / `non_retryable_failure`
| ID | 策略 | 准备 | 成功判定 | 状态 | 结果记录 |
| --- | --- | --- | --- | --- | --- |
| POLICY-RETRY-01 | 可重试错误触发重试 | 同一模型配置两个候选,第一候选 `simulationFailure=retryable_failure`,第二候选成功,`retryPolicy.enabled=true,maxAttempts=2` | 任务最终 `succeeded`,事件含 `task.retrying`attempt 先失败后成功 | 未执行 | taskId、attempts、events 待填写 |
| POLICY-RETRY-02 | 重试策略禁用 | 第一候选 `retryable_failure``retryPolicy.enabled=false` | 任务失败,不出现 `task.retrying`,不会调用第二候选 | 未执行 | taskId、attempts 待填写 |
| POLICY-RETRY-03 | 非重试错误不重试 | `simulationProfile=fatal_failure``non_retryable_failure` | 任务失败,错误码为 bad_request 类,不出现 `task.retrying` | 未执行 | taskId、errorCode 待填写 |
| POLICY-DISABLE-01 | 错误策略自动禁用 | 配置 `autoDisablePolicy.enabled=true,threshold=1,keywords=[invalid_api_key]`,模拟命中关键词 | 命中后平台或模型被禁用,后续候选查询不再使用该客户端 | 未执行 | platformId、状态变化待填写 |
| POLICY-DISABLE-02 | 非命中关键词不禁用 | 同样策略下模拟不在关键词中的错误 | 平台和模型状态不变,仅记录失败 | 未执行 | 状态变化待填写 |
| POLICY-DEGRADE-01 | 降级策略生效 | 配置 `degradePolicy.enabled=true,cooldownSeconds=300,keywords=[rate_limit,overloaded]`,模拟命中关键词 | 失败平台被降级或进入冷却,下一次路由优先使用其他候选 | 未执行 | priority/cooldown 变化待填写 |
| POLICY-DEGRADE-02 | 非命中关键词不降级 | 模拟普通 bad_request | 不调整优先级、不进入冷却 | 未执行 | priority/cooldown 变化待填写 |
| POLICY-ORDER-01 | 候选排序 | 两个平台同模型,优先级和 running_count 不同 | 路由按优先级、限流占用、运行中数量排序 | 未执行 | 候选顺序证据待填写 |
## 9. 限流控制
限流需要覆盖平台模型维度和用户组维度。RPM / TPM 使用同一分钟窗口断言;并发使用 lease 断言。
| ID | 限流 | 准备 | 成功判定 | 状态 | 结果记录 |
| --- | --- | --- | --- | --- | --- |
| LIMIT-RPM-01 | 平台模型 RPM | 平台模型 `rateLimitPolicy.rules=[{metric:rpm,limit:1,windowSeconds:60}]` | 第一次成功,第二次同窗口返回 429 或任务失败码 `rate_limit` | 未执行 | taskId、窗口计数待填写 |
| LIMIT-RPM-02 | 用户组 RPM | 用户组 `rateLimitPolicy` 设置 RPM=1用户归属该组 | 同组第二次被限流,不同组用户不受影响 | 未执行 | groupId、响应待填写 |
| LIMIT-TPM-01 | 平台模型 TPM | 设置 `tpm_total` 极小值,发送长 prompt | 当估算 token 超出 limit 时被拒绝 | 未执行 | token 估算、响应待填写 |
| LIMIT-TPM-02 | 用户组 TPM | 用户组设置 `tpm_total` 极小值 | 该组用户被限制,非该组用户不受影响 | 未执行 | groupId、响应待填写 |
| LIMIT-CONC-01 | 并发限制 | 设置 `concurrent=1`,并发发起两个慢模拟任务或保留未释放 lease | 第二个任务被限流,`gateway_concurrency_leases` 记录正确 | 未执行 | leaseId、响应待填写 |
| LIMIT-CONC-02 | 并发释放 | 成功任务结束后再次发起 | lease 释放后新任务可成功 | 未执行 | released_at、taskId 待填写 |
| LIMIT-WINDOW-01 | 限流窗口查询 | `GET /api/v1/runtime/rate-limit-windows` | 返回对应 `scopeType/scopeKey/metric/usedValue/resetAt` | 未执行 | 窗口记录待填写 |
## 10. 成功验收总表
| 模块 | 必须通过的用例 | 状态 | 结果摘要 |
| --- | --- | --- | --- |
| 基础准备 | SETUP-01 到 SETUP-09 | 未执行 | 待填写 |
| 完整任务执行 | TASK-CHAT-01 到 TASK-DETAIL-01 | 未执行 | 待填写 |
| 历史任务记录 | HISTORY-01 到 HISTORY-05 | 未执行 | 待填写 |
| 定价与扣费 | PRICE-01 到 PRICE-08 | 未执行 | 待填写 |
| 权限控制 | AUTH-01 到 AUTH-09 | 未执行 | 待填写 |
| 运行策略 | POLICY-RETRY-01 到 POLICY-ORDER-01 | 未执行 | 待填写 |
| 限流控制 | LIMIT-RPM-01 到 LIMIT-WINDOW-01 | 未执行 | 待填写 |
## 11. 失败处理记录
| 时间 | 用例 ID | 失败现象 | 初步原因 | 修复位置 | 重跑结果 |
| --- | --- | --- | --- | --- | --- |
| 待填写 | 待填写 | 待填写 | 待填写 | 待填写 | 待填写 |
## 12. 清理清单
| ID | 清理对象 | 成功判定 | 状态 | 结果记录 |
| --- | --- | --- | --- | --- |
| CLEAN-01 | 内部测试 API Key | 禁用或删除所有 `loopbackRunId` 关联 Key | 未执行 | 待填写 |
| CLEAN-02 | 内部访问规则 | 删除 `loopbackRunId` 关联 `gateway_access_rules` | 未执行 | 待填写 |
| CLEAN-03 | 内部模拟平台和模型 | 删除或禁用 `loopback-sim-*` 平台和模型 | 未执行 | 待填写 |
| CLEAN-04 | 内部测试用户组和用户 | 删除或禁用 `loopback-*` 用户组和用户 | 未执行 | 待填写 |
| CLEAN-05 | 内部策略和规则集 | 删除非默认 `loopback-*` 运行策略和定价规则集 | 未执行 | 待填写 |