Files
ai-proj-helper/skills-req/req-test-gate-plugin/skills/SKILL.md
John Qiu 2309e31e74 refactor(skills): 澄清 dev-test 与 req-test-gate 的职责边界
- dev-test: 移除 "Gate 4" 编号,改用 "E2E 冒烟门禁"(避免与 req-test-gate 的 Gate 编号冲突)
- dev-test: 添加与 req-test-gate 的关系说明(本文档定义执行技术,门禁流程在 req-test-gate)
- req-test-gate: 2C 联调节新增无后端替代方案提示,引用 dev-test 的 API Mock 模式
- req-test-gate: Gate 5 前端回归贡献引用 dev-test 的 e2e-testing.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 11:40:47 +10:30

452 lines
18 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.
---
name: req-test-gate
description: 测试与质量门禁制度。覆盖需求级测试(Gates 1-5含前后端联调+视觉验证)、部署级验证(Deploy Gates)、持续回归(Regression)。
---
# 测试与质量门禁制度 (req-test-gate) v2.1
## 概述
三层质量门禁架构,确保从需求到上线每个阶段都有结构化验证。
**三层架构**
```
需求级 (Gates 1-5) → /req test 触发,单需求维度
部署级 (Deploy Gates) → /req deploy 触发,批量部署维度
持续维度 (Regression) → 定时/部署后触发,系统级回归
```
## 需求级门禁 (Gates 1-5)
**触发时机**`/req test` 执行、`/req next` 从 testing 推进
```
Gate 0: Scope 分级(自动,决定后续 Gate 裁剪)
Gate 1: 前置条件检查(自动)
Gate 2: 测试执行验证2A→2B→2C→2D→2E→2F按 scope 裁剪)
Gate 3: 测试质量验证(子代理,按 scope 决定是否触发)
Gate 4: 文档持久化(自动,按 scope 选模板)
Gate 5: 回归贡献检查(按 scope 区分贡献形式)
通过 → 允许 /req next 推进到待部署池
```
## Gate 0: Scope 分级(自动)
**从 `git diff` 自动推断变更范围,决定后续 Gate 的裁剪策略。**
```bash
# 自动推断逻辑
git diff main...HEAD --name-only | classify_scope
```
| scope | 判断依据 | Gate 裁剪效果 |
|-------|---------|--------------|
| `backend` | 仅 `.go` 文件变更 | 2A(go) + 2B 必须2C/2F 跳过 |
| `frontend` | `.tsx/.ts` 变更(含业务逻辑) | 2A(tsc/build) 必须2B 跳过 |
| `style-only` | 仅 `.css/.less` 或 shared/ 变更 | 2A(build) + **2F(视觉验证)** 必须2B/2C 跳过 |
| `fullstack` | 前后端都有改动 | 2A + 2B + 2C 全部必须 |
**frontend vs style-only 区分**`.tsx/.ts` 文件中是否包含 API 调用(`import.*api``fetch``request`)。仅样式/布局改动归为 style-only。
**scope 影响全部后续 Gate**,在测试报告中必须标注。
---
## Gate 1: 前置条件检查
**自动检查,不可跳过。**
| 检查项 | 检查方式 | 阻塞级别 |
|--------|---------|----------|
| CR 已通过 | `delivery_stage >= review` 或有 completed 的 code_review 任务 | 阻塞 |
| 开发任务全部完成 | 所有 `linkRole=implementation` 的任务状态为 completed | 阻塞 |
| CR 文档存在code 类型) | `has_task_document` 对 code_review 任务 | 警告 |
**未通过处理**
- 阻塞项 → 直接拒绝,提示「请先完成 {缺失项}」
- 警告项 → AskUserQuestion 确认是否继续
## Gate 2: 测试执行验证
**按需求类型执行分层测试,从静态到动态逐步验证。**
### 类型推断
`get_requirement_tasks` 的 linkRole 集合推断:
- **code**: 有 `implementation` 任务 → 代码需求
- **skill**: 无 `implementation`,有 `prd`/`test` → Skill/文档需求
- **ops**: 仅 `deploy` 任务 → 运维需求
### code 类型:五阶段验证
#### 2A: 静态验证(编译+类型检查)
**按 scope 裁剪执行项:**
| 序号 | 测试项 | 命令 | scope 触发条件 | 通过条件 |
|------|--------|------|---------------|----------|
| T1 | 后端编译 | `go build ./...` | backend / fullstack | exit 0 |
| T2 | 后端单元测试 | `go test ./...` | backend / fullstack | 全部 PASS |
| T4 | 前端类型检查 | `tsc --noEmit` | frontend / fullstack | exit 0 |
| T4b | 前端构建 | `vite build` | **所有前端 scope** | 构建成功 |
| T5 | 前端测试 | `npm test` 相关组件 | frontend / fullstack | PASS |
| T7 | iOS 编译 | `xcodebuild build` | 有 iOS 改动时 | exit 0 |
**style-only scope**:仅执行 T4b构建验证跳过 T1/T2/T4/T5。
#### 2B: API 端点验证(后端独立)
| 序号 | 测试项 | 命令 | 必须 | 通过条件 |
|------|--------|------|------|----------|
| T3 | API 端点验证 | `curl localhost:8080` 调用新/改 API | 必须 | 预期状态码和数据 |
| T3.1 | DB 约束验证 | `curl` 测试 FK/唯一约束 | 推荐 | 错误码正确400/404 |
| T3.2 | 错误处理验证 | 无效输入/缺失参数 | 推荐 | 错误响应格式正确 |
| T3.3 | **并发/原子性** | 2 个并发请求竞争边界量(如库存恰好=N发 2 个各 N 件的请求)| 涉及库存/积分/财务时必须 | 恰好 1 个成功,另一个返回"不足"DB 无超卖 |
| T3.4 | **租户隔离** | 用 tenant B token 操作 tenant A 的资源 ID | 多租户系统必须 | 返回 403/无权DB 未被篡改 |
| T3.5 | **状态流转完整性** | 触发所有 change_type/状态流转后查流水表 | 有状态机实体时必须 | 所有预期流水类型都出现过 |
> **触发判断(以下任一为真则 T3.3T3.5 必须执行):**
> - 需求涉及库存/积分/余额/限购
> - 需求有多租户资源隔离要求
> - 需求引入了新的状态机status 枚举 ≥ 3 个)
#### 2C: 前后端联调(开发环境)
**触发条件**scope 为 `fullstack`,或前端 `.tsx/.ts` 文件包含 API 调用(`import.*api``fetch``request`
**不触发**scope 为 `backend``style-only`,或前端改动不涉及 API 调用
**环境要求**:本地开发环境,前端 :3000 + 后端 :8080 同时运行
> **无后端替代方案**IT6 页面可访问性验证可用 Playwright API Mock 模式(`page.route()`)替代真实后端。详见 `dev-test` 技能的 `e2e-testing.md` §API Mock 冒烟测试。
**前置步骤**
1. 确认本地数据库已执行相关 migration菜单、表结构等
2. 启动后端 `cd backend && go run main.go`
3. 启动前端 `cd frontend && npm start`
4. 获取 JWT Token`POST /api/v1/auth/login`
| 序号 | 测试项 | 方法 | 必须 | 通过条件 |
|------|--------|------|------|----------|
| IT1 | 前端代理连通 | `curl localhost:3000/api/v1/health` | 必须 | 200前端代理到后端成功 |
| IT2 | 菜单可见性 | `curl localhost:3000/api/v1/menus/user-menus` | 必须 | 新菜单出现在响应中 |
| IT3 | API 代理验证 | `curl localhost:3000/api/v1/<新端点>` | 必须 | 通过前端代理调用后端 API 返回预期数据 |
| IT4 | 路由配置 | 检查 App.tsx 有 `<Route path="..." />` | 必须 | 路由存在且 lazy import 正确 |
| IT5 | 图标映射 | 检查 Layout.tsx iconMap 有对应图标 | 条件 | 有新菜单图标时必须验证 |
| IT6 | 页面可访问 | 浏览器访问 `localhost:3000/<新路径>` | 推荐 | 页面加载无白屏、无 console 报错 |
**无前端改动时**:标记 `⏭️ 跳过: 无前端改动`
**常见联调问题及排查**
| 问题 | 根因 | 解决方案 |
|------|------|----------|
| 菜单不显示 | 本地 DB 未执行 menu migration | 执行 migration SQL + 修复 sequence |
| API 返回 404 | 前端代理路径不匹配 | 检查 `setupProxy.js``package.json` proxy 配置 |
| 页面白屏 | React 组件 import 错误或 TS 类型不匹配 | 检查 console 错误,修复 import 路径 |
| 登录失败 | 本地用户密码不匹配 | 重新生成 bcrypt cost 12 哈希并更新本地 DB |
| Redis 缓存脏数据 | 菜单/权限缓存未清理 | `redis-cli KEYS "menu:user:*"` 后逐个 DEL |
#### 2D: 冒烟测试Staging 环境)
**触发条件**:已部署到 staging
| 序号 | 测试项 | 命令 | 必须 | 通过条件 |
|------|--------|------|------|----------|
| SM1 | API 健康检查 | `curl staging/api/v1/health` | 必须 | 200 |
| SM2 | 核心流程验证 | `curl` 新功能关键 API | 必须 | 预期响应 |
| SM3 | 数据一致性 | 创建→读取→验证 | 推荐 | 数据完整返回 |
**未部署到 staging 时**:标记 `⏭️ 跳过: 未部署到 staging`
#### 2E: 原型符合性测试
**触发条件**:有关联原型 HTML`prototype-*.html`
| 序号 | 测试项 | 方法 | 必须 | 通过条件 |
|------|--------|------|------|----------|
| PC1 | 结构完整性 | 对比原型 Section 数 vs 实现区块 | 必须 | 所有 Section 有对应实现 |
| PC2 | 数据模型对齐 | 对比原型字段 vs API 返回字段 | 必须 | 字段名/类型匹配 |
| PC3 | 交互流程覆盖 | 对比原型操作 vs 实现事件绑定 | 推荐 | 所有交互有绑定 |
| PC4 | 状态覆盖 | 对比原型状态标签 vs 实现枚举 | 推荐 | 状态集一致 |
**无原型时**:标记 `⏭️ 跳过: 无关联原型`
**原型冻结规则**:原型在评审通过后冻结,设计变更需创建新需求。
#### 2F: 视觉/响应式验证v2.1 新增)
**触发条件**scope 为 `style-only``frontend`(有 CSS/LESS 变更时)
**不触发**scope 为 `backend`
| 序号 | 测试项 | 方法 | 必须 | 通过条件 |
|------|--------|------|------|----------|
| VR1 | 断点一致性 | `grep -rn "max-width\|min-width" --include="*.css" --include="*.less"` 对比 breakpoints 定义 | 必须 | 所有新增 media query 使用标准断点值 |
| VR2 | 构建无警告 | `vite build` 输出检查 | 必须 | 无 CSS 相关 warning |
| VR3 | !important 审计 | `grep -c "!important"` 统计新增数量 | 推荐 | 新增 !important ≤ 3 个,或有合理理由 |
| VR4 | 文件完整性 | 新增组件/样式文件全部存在 | 必须 | 所有 import 的文件可解析 |
| VR5 | 移动端适配 | 检查关键页面在 ≤768px 下的 CSS 规则覆盖 | 推荐 | 有对应的移动端样式 |
**无 CSS 变更时**:标记 `⏭️ 跳过: 无样式改动`
### skill 类型 Checklist
| 序号 | 测试项 | 方法 | 必须 |
|------|--------|------|------|
| S1 | 关键词一致性 | `grep` 核心概念跨文件对齐 | 必须 |
| S2 | 规则无歧义 | 审查每条规则触发条件和动作 | 必须 |
| S3 | 边界情况 | 至少 1 个边界场景验证 | 必须 |
| S4 | 交叉引用 | 文件间引用指向正确 | 推荐 |
| S5 | Token 大小 | `wc -w` < 7500 词 | 推荐 |
### ops 类型 Checklist
| 序号 | 测试项 | 方法 | 必须 |
|------|--------|------|------|
| O1 | 命令可执行 | dry-run 或 staging 执行 | 必须 |
| O2 | 健康检查 | `curl` 健康端点 | 必须 |
| O3 | 回滚方案 | 文档审查 | 推荐 |
### UAT 场景设计(复杂业务需求适用)
当需求涉及以下任一情况时,在 2B 之后额外执行 UAT 场景矩阵:
- 完整业务流程(下单→支付→发货→退款)
- 并发控制(乐观锁/悲观锁/原子 SQL
- 多角色协作(消费者 + 管理员 + 供应商)
**执行方式**:参照 [uat-patterns.md](uat-patterns.md) 的 5 类场景框架逐一设计用例,用 ai-proj 创建 stage="testing" 的子任务跟踪进度。
### 执行记录格式
```
| T1 | 后端编译 | `go build ./...` | ✅ PASS | exit 0, 0 errors |
| IT1 | 前端代理连通 | `curl localhost:3000/api/v1/health` | ✅ PASS | 200 |
| IT2 | 菜单可见性 | user-menus API | ✅ PASS | 持续管理+2子菜单 |
| SM1 | 健康检查 | `curl staging/health` | ✅ PASS | 200 |
| PC1 | 结构完整性 | 原型 11 sections vs 实现 | ⏭️ 跳过 | 无关联原型 |
```
## Gate 3: 测试质量验证(子代理)
派遣 test-validator 子代理审查。模板: `~/.claude/skills/req-test-gate/test-validator.md`
**触发规则(按 scope 裁剪)**
- code + `backend` / `fullstack`**总是触发**
- code + `frontend`(含业务逻辑):**触发**
- code + `style-only`**不触发**CR 已覆盖样式审查)
- skill 类型:**≥5 测试项时触发**
- ops 类型:**不触发**
```typescript
Task({
subagent_type: "superpowers:code-reviewer",
prompt: `使用 test-validator 模板审查测试质量。
模板路径: ~/.claude/skills/req-test-gate/test-validator.md
填充参数:
- REQUIREMENT_TITLE: "{需求标题}"
- REQUIREMENT_TYPE: "{code|skill|ops}"
- TEST_RESULTS: "{Gate 2 的执行记录表格}"
- CODE_CHANGES_SUMMARY: "{改动文件列表和摘要}"
- CHECKLIST_USED: "{使用的 checklist 类型}"
`
})
```
| 评估结果 | 处理 |
|---------|------|
| "测试充分" | Gate 3 通过 |
| "需补充测试"(Important) | AskUserQuestion 确认 |
| "测试不足"(Critical) | 阻塞,必须补充后重新验证 |
## Gate 4: 文档持久化
**不可跳过。** `create-and-attach` 写入测试任务文档。**按 scope 选择模板。**
### 轻量模板scope = style-only / frontend 无 API
```markdown
## 测试报告 - {需求标题}
| 字段 | 值 |
|------|-----|
| 需求 | REQ-XXXX |
| scope | {style-only/frontend} |
| 门禁版本 | test-gate v2.1 |
### 构建验证
| 项目 | 命令 | 结果 |
|------|------|------|
| TypeScript | tsc --noEmit | ✅/❌/⏭️ |
| Vite Build | vite build | ✅/❌ |
### 视觉验证 (2F)
| 序号 | 测试项 | 结果 | 备注 |
|------|--------|------|------|
| VR1 | 断点一致性 | ✅/❌ | ... |
| VR2 | 构建无警告 | ✅/❌ | ... |
| VR4 | 文件完整性 | ✅/❌ | ... |
### 总结
通过: {N}/{M} | 结论: ✅ 通过 / ❌ 未通过
```
### 完整模板scope = backend / fullstack
```markdown
## 测试报告 - {需求标题}
| 字段 | 值 |
|------|-----|
| 需求 | REQ-XXXX |
| 类型 | {code/skill/ops} |
| 时间 | {YYYY-MM-DD HH:MM} |
| 门禁版本 | test-gate v2 |
### 前置条件 (Gate 1)
- CR 状态: ✅ 已通过
- 开发任务: ✅ 全部完成 ({N}/{N})
### 测试执行 (Gate 2)
| 序号 | 阶段 | 测试项 | 命令/方法 | 结果 | 备注 |
|------|------|--------|----------|------|------|
| T1 | 2A | 后端编译 | ... | ✅/❌/⏭️ | ... |
| IT1 | 2C | 前端代理连通 | ... | ✅/❌/⏭️ | ... |
| SM1 | 2D | 健康检查 | ... | ✅/❌/⏭️ | ... |
| PC1 | 2E | 结构完整性 | ... | ✅/❌/⏭️ | ... |
### 跳过的测试
⏭️ {测试项}: {原因}
(无则写「无」)
### 质量验证 (Gate 3)
{子代理结果摘要或「未触发ops 类型)」}
### 回归贡献 (Gate 5)
{贡献的回归用例数,或「无需贡献」或「⏭️ 跳过: 过渡期」}
### 总结
通过: {N}/{M} | 跳过: {K} | 结论: ✅ 通过 / ❌ 未通过
```
### 文档质量门禁(被 `/req next` 检查)
- 含测试项表格(`|` 分隔符 ≥ 3 行)
- 含通过/失败结论(`✅ 通过``❌ 未通过`
- 总字符数 ≥ 200
- 门禁版本标记(`test-gate v2``test-gate v2.1`
## Gate 5: 回归贡献检查
**确保 code 类型需求为回归池贡献测试用例。按 scope 区分贡献形式。**
**触发条件**code 类型需求
| 检查项 | 说明 | 阻塞级别 |
|--------|------|----------|
| 有 regression linkRole 任务 | `get_requirement_tasks(linkRole=regression)` | 警告 |
| 任务有文档附件 | `has_task_document` | 警告 |
| 文档包含可执行用例 | 含 `curl` 命令或测试脚本 | 建议 |
**过渡期规则v2.1**警告但不阻塞AskUserQuestion 提醒补充。
### Scope 贡献形式
| scope | 贡献形式 | 示例 |
|-------|---------|------|
| `backend` | curl 脚本API 回归) | `curl -X POST .../api` → 201 |
| `frontend` | E2E 场景描述Playwright API Mock | 页面加载 + 核心交互验证。编写模式见 `dev-test` 技能 `e2e-testing.md` |
| `style-only` | 视觉回归 checklist | 断点覆盖 + !important 审计 |
| `fullstack` | curl 脚本 + E2E 场景 | 两者都需要 |
### 回归用例模板backend / fullstack
```markdown
## 回归用例 - REQ-XXXX {需求标题}
### 模块
{okr / task / auth / ...}
### 用例列表
| ID | 场景 | 命令 | 预期结果 | 优先级 |
|----|------|------|----------|--------|
| RC1 | ... | `curl ...` | 200 + ... | 高 |
```
### 回归用例模板frontend / style-only
```markdown
## 回归用例 - REQ-XXXX {需求标题}
### 模块
{product / order / layout / ...}
### 视觉/交互用例
| ID | 场景 | 验证方法 | 预期结果 | 优先级 |
|----|------|---------|----------|--------|
| VRC1 | 移动端列表布局 | 浏览器 375px 宽度截图 | 卡片正常排列 | 高 |
| VRC2 | 响应式断点切换 | 768px→769px 切换 | 布局无跳变 | 中 |
```
详见 [regression.md](regression.md) 了解完整回归系统设计。
## 部署级门禁 (Deploy Gates)
**触发时机**`/req deploy` 执行
详见 [deploy-gates.md](deploy-gates.md)
概要流程:
```
DG1: 迁移检查(不可跳过) → 有未执行 migration?
DG2: Staging 部署 → 构建+部署到 singapore
DG3: 冒烟测试 → 核心 API 可用
DG4: 影响域回归 → module-deps 决定范围
DG5: 性能基线(推荐) → 关键 API 响应时间
DG6: 生产部署(不可跳过) → 健康检查+文档
```
## 回归测试模块
**系统级持续活动,独立于单需求生命周期。**
详见 [regression.md](regression.md)
核心概念:
- **回归池**:所有需求贡献的测试用例汇集处
- **回归判定**:上次 PASS + 本次 FAIL = 回归(高优先级,自动创建 bug 需求)
- **闭环**:回归失败 → 创建 bug 需求 → 修复 → 回归池更新
- **三种执行模式**:影响域(部署触发)、关键路径(每日)、全量(每周)
## Force 跳过规则
| 门禁 | 可否 Force | 说明 |
|------|-----------|------|
| Gate 1 前置条件 | **不可** | 必须满足 |
| Gate 2 测试执行 | 单项可跳过 | 需记录原因 |
| Gate 3 质量验证 | Critical 不可Important 可 | AskUserQuestion 后跳过 |
| Gate 4 文档持久化 | **不可** | 必须生成文档 |
| Gate 5 回归贡献 | 可(过渡期) | 警告级别 |
| Deploy Gates | DG1/DG6 不可,其余可 | 迁移和健康检查不可跳过 |
## 与现有流程集成
### `/req test` 增强
```
v1: Gate 1 → Gate 2 → Gate 3 → Gate 4
v2: Gate 1 → Gate 2(2A→2B→2C→2D→2E) → Gate 3 → Gate 4 → Gate 5
v2.1: Gate 0(scope) → Gate 1 → Gate 2(2A→2B→2C→2D→2E→2F按scope裁剪) → Gate 3 → Gate 4 → Gate 5
```
### `/req next` testing→staging 门禁
验证测试文档Gate 1-5 全部通过的完整报告 + 门禁版本 `test-gate v2`
### `/req deploy` 部署门禁
在 req-deploy 流程前增加 Deploy Gates (DG1-DG6) 检查。