
🎯 学 gstack 的 11 阶段自动化 QA 工作流:不是"跑一下测试然后告诉你结果",而是从环境检测、认证、探索式测试、文档化、分诊到自我调节的修复循环——在修复和打破之间动态平衡,在
ctrl+c面前优雅退出。 ⏱️ 预计时间:45 分钟
[!quote]- 📖 原Skill精要 技能名称:qa 核心功能:系统化 QA 测试 Web 应用并修复发现的 Bug。从环境检测、认证、探索式测试到分诊和自我调节修复循环——在修复和打破之间动态平衡。三层测试深度:Quick(仅关键/高)、Standard(+中)、Exhaustive(+外观)。产出前后健康评分、修复证据和发布就绪摘要。纯报告模式请用 [[L6-21-纯报告式QA|qa-only]]。 所属体系:gstack 虚拟工程团队 协作关系:利用 [[L6-37-浏览器自动化|browse]] 浏览器自动化进行实际网站交互测试
1. 课程概览
💡 白话小课堂:传统测试流程是"跑 → 看红绿 → 修 → 再跑"的手动循环——人盯着终端等结果,然后手动定位失败原因,再手动修。gstack /qa 则是一个完整的质量保证系统工程:先检测你的技术栈和测试框架、认证所需的环境变量、扫描目录建立文件→测试的映射——然后执行三层测试(Quick 只跑单元 / Standard 单元+集成 diff-aware / Exhaustive 全量+E2E+性能),把所有失败文档化并分诊排序(CRITICAL > HIGH > MEDIUM > LOW),最后进入修复循环——但修复循环有两条安全绳:WTF 计数器(每次修复引入新失败就加惩罚分,WTF >= 5 就停止)和 50 次硬上限——防止 AI 陷入"修一个 bug 引入三个新 bug"的无底洞。更妙的是,ctrl+c 中断后不会丢数据——每个阶段之间都有检查点,可以从中断点继续。
2. QA 是什么——不是测试运行器,是质量保证系统
QA vs 传统的"跑测试"
传统测试: → npm test → 看红绿 → 修 → 再跑 → 重复
gstack /qa: → 检测技术栈 → 认证环境(API keys)→ 探索代码库 → 执行三层测试(Quick/Standard/Exhaustive) → diff-aware 模式(只测变更相关的代码) → 所有失败文档化 → 分诊 → 修复循环(带自我调节) → 健康评分 → 回归测试生成 → 持久化到 TODOS.md
这不是"跑测试",这是完整的质量保证系统工程。
3. 11 阶段工作流——从零到质量报告
Phase 1: Initialize(初始化)
→ 检测技术栈:package.json / Gemfile / pyproject.toml / go.mod → 检测测试框架:jest / rspec / pytest / go test → 设置 tier 参数(默认 standard) → 建立工作目录
Phase 2: Authenticate(认证)
→ 检测所需环境变量(CI=true, API keys, DB URLs) → 列出缺失的环境变量但不中断 → 设定测试模式:authenticated / unauthenticated → 缺失认证 → 降级运行(能跑多少跑多少)
Phase 3: Orient(定位)
→ 扫描目录结构:src/ app/ lib/ test/ spec/ → 识别测试类型:单元 / 集成 / E2E / 性能 → 建立文件映射:源文件 ↔ 测试文件 → 输出:测试覆盖率地图(哪些文件有测试、哪些没有)
Phase 4: Explore(探索)
→ diff-aware 模式:git diff origin/main --name-only → 过滤:只测试变更触及的代码路径 → 全量模式:所有源文件均纳入测试范围 → 输出:测试执行计划(哪些测试要运行)
Phase 5: Execute(执行)
→ 运行测试套件 → 解析输出:通过/失败/跳过/错误 → 捕获每个失败的:文件 + 行号 + 错误信息 + 堆栈 → 超时检测(长时间卡住的测试)
Phase 6: Document(文档化)
→ 每个失败生成结构化报告条目 → 格式:文件 | 行号 | 测试名 | 错误类型 | 完整堆栈 → 分类:BROKEN TEST / CODE BUG / ENV ISSUE / FLAKY → 去重:相同文件+行号的失败合并
Phase 7: Wrap Up(收尾)
→ 生成摘要:总测试数 / 通过 / 失败 / 跳过 / 耗时 → 生成健康评分(health score) → 生成建议:哪些失败值得立即修复、哪些可以延后
Phase 8: Triage(分诊)
→ 按严重度排序失败:CRITICAL > HIGH > MEDIUM > LOW → CRITICAL: 影响核心功能的测试失败 → HIGH: 多个测试因同一原因失败 → MEDIUM: 孤立测试失败、边缘情况 → LOW: 风格/格式测试失败 → 标记可自动修复的失败
Phase 9: Fix Loop(修复循环)
→ 按分诊顺序逐个处理失败 → 每个修复后重新运行相关测试 → 自调节机制(WTF-likelihood)防止无限循环 → 50 次修复硬上限——防止陷入无底洞
Phase 10: Final QA(最终验证)
→ 全量回归测试运行 → 验证所有修复未引入新问题 → 确认修复数量 vs 残留失败数
Phase 11: Report & Persist(报告与持久化)
→ 生成最终 QA 报告 → 更新 TODOS.md(残留项追踪) → 写入健康评分到 gstack 持久化存储 → 如有新测试生成 → 列出文件路径
4. 三层测试深度——选择合适的力量
Tier 1: Quick(快速——默认基准)
→ 只运行单元测试 → 耗时:通常 < 2 分钟 → 适用:小的增量变更、快速反馈 → 命令:/qa quick
Tier 2: Standard(标准——默认)
→ 单元测试 + 集成测试 → diff-aware 模式自动过滤 → 耗时:通常 2-8 分钟 → 适用:标准 PR 审查、中等变更 → 命令:/qa standard 或 /qa(默认)
Tier 3: Exhaustive(详尽——全面覆盖)
→ 单元 + 集成 + E2E + 性能测试 → 全量模式(不限于 diff) → 耗时:可能 20+ 分钟 → 适用:关键发布前、重大重构后 → 命令:/qa exhaustive
选择建议
→ 小 bug fix → Quick → 功能开发 → Standard → 架构变更 / 发版前 → Exhaustive → 不确定 → Standard(默认安全选择)
5. Diff-Aware 模式——只测变更相关的
为什么需要 Diff-Aware?
全量运行所有测试的问题: → 大型项目的测试套件可能运行 30+ 分钟 → 大部分测试与当前变更无关 → 浪费时间和 CI 预算
Diff-aware 模式的逻辑:
- git diff origin/main --name-only 获取变更文件列表
- 为每个变更文件找到对应的测试文件
- 使用测试框架的过滤功能只运行这些测试
- 同时运行受影响的依赖文件测试(import 链)
依赖追踪(受影响的测试)
→ 如果 src/models/user.js 变更了 → 不仅运行 test/models/user.test.js → 也运行导入了 User 模型的测试: test/services/auth.test.js test/controllers/users.test.js → 静态分析 import/require 链来确定影响范围
回退机制
→ 如果依赖追踪不准确 → 回退到全量运行 → 框架不支持文件过滤 → 全量运行 → 永不因优化而遗漏测试
6. 健康评分体系——量化代码质量
Health Score Rubric(健康评分量表)
8 个维度,加权计算,0-100 分:
| 维度 | 权重 | 评分规则 |
|---|---|---|
| Test Pass Rate | 20% | (通过数/总数) × 20 |
| Test Coverage | 18% | 行覆盖率 / 目标覆盖率 × 18(上限 18) |
| Critical Failures | 15% | 0 critical → 15, 每个 -3 |
| High Failures | 12% | 0 high → 12, 每个 -2 |
| Medium Failures | 10% | 0 medium → 10, 每个 -1 |
| Build/Compile | 10% | 编译通过 → 10, 失败 → 0 |
| Lint/Format | 8% | 0 问题 → 8, 每个 -0.5 |
| Type Safety | 7% | 0 类型错误 → 7, 每个 -1 |
评分解读
→ 90-100:优秀——生产就绪 → 80-89:良好——少量需要关注 → 70-79:可接受——有改进空间 → 60-69:需要关注——累积技术债务 → < 60:阻塞——不应合入
评分持久化
→ 存储到 gstack-review-log 中 → 与 /review 的 quality_score 互相验证 → /ship 读取作为合入决策的辅助输入
7. 修复循环——有节制的自动修复
Fix Loop 的工作方式
分诊完成后,进入修复循环:
- 按严重度降序取下一个失败
- 分析失败原因(读取测试代码 + 被测代码)
- 判断是否可自动修复: → AUTO-FIXABLE:明显的低级错误(类型不匹配、缺失导入、断言过时) → NEEDS ANALYSIS:需要理解意图的失败(逻辑 bug、设计问题)
- AUTO-FIXABLE → 直接修复 → 重新运行相关测试
- NEEDS ANALYSIS → 记录为残留问题,跳过
WTF-Likelihood 自调节机制
核心问题:修复循环无限运行怎么办?
解决方案——WTF计数器: → 初始 WTF = 0 → 每次修复后: ✓ 相关测试通过 → WTF = max(0, WTF - 1) ✗ 修复引入新失败 → WTF += 1 ✗ 修复未解决原失败 → WTF += 2 ✗ 修复导致 3+ 新失败 → WTF += 3 → WTF >= 5 → 停止修复循环,输出警告 → WTF >= 10 → 回退最近的修复
50 次修复硬上限
→ 无论 WTF 值如何,修复循环最多执行 50 次 → 达到上限 → 停止 + 报告残留失败 → 防止无限循环消耗资源和时间
修复回退机制
→ 每次修复记录 diff → WTF >= 10 时自动回退最近的修复 → 保留回退前的诊断信息供用户分析
⚠️ 避坑指南: WTF 计数器是修复循环的安全阀。AI 在修复代码时,有时候"修了一个 bug 引入三个新 bug"——这很正常。
8. 回归测试生成——不让 bug 再来一次
什么时候生成回归测试?
对每个修复的失败: → 如果是 CODE BUG 类型 → 生成回归测试 → 如果是 BROKEN TEST 类型 → 不生成(修复测试本身即可) → 如果是 ENV ISSUE 类型 → 不生成 → 如果是 FLAKY 类型 → 标记但不生成
回归测试格式
→ 放在现有测试文件中,靠近原来的失败测试 → 命名:should → 包含注释:// Regression test for: <原始失败描述> → 如果是新类别 → 创建新的 describe 块
为什么需要回归测试?
→ 修复了 bug 不代表它不会回来 → 回归测试是 bug 的"通缉令"——下次一出现就抓到 → 防止修复被将来变更破坏 → 积累测试知识——每个 bug 教会我们一个测试模式
9. Diff-Aware 与全量模式的切换
自动模式选择
/qa 根据上下文自动选择模式:
Diff-Aware(默认——有 diff 时)
→ 在功能分支上运行 → 有 diff → diff-aware → git diff origin/main 成功 → diff-aware → 只测试变更触及的代码
全量模式(回退——无 diff 或 explicit)
→ 在 main 分支上运行 → 全量 → git diff origin/main 无变化 → 全量 → 用户指定 /qa exhaustive → 全量 → 用户指定 /qa full → 全量
手动切换
→ /qa → 自动选择 → /qa diff → 强制 diff-aware → /qa full → 强制全量 → /qa exhaustive → 强制全量 + E2E + 性能
10. ctrl+c 优雅退出——不丢数据、不毁状态
为什么 QA 需要优雅退出?
QA 是长流程(可能 10+ 分钟),用户随时可能中断。
优雅退出策略: → 捕获中断信号(每个阶段之间的检查点) → 保存当前进度(已完成的阶段、未完成的任务) → 生成部分报告(已完成阶段的汇总) → 不残留临时文件 → 不清除已生成的回归测试 → 后续 /qa 运行可以从中断点继续(可选恢复)
检查点粒度
→ 每个 Phase 之间都有检查点 → Phase 5 (Execute) 中每条测试套件之间也有检查点 → Phase 9 (Fix Loop) 中每个修复之间检查
部分报告格式
QA INTERRUPTED at Phase 6/11 Completed: Initialize → Authenticate → Orient → Explore → Execute → Document Pending: Wrap Up → Triage → Fix Loop → Final QA → Report Partial results: 42/50 tests passed, 8 failures documented in /tmp/qa-partial.md
11. QA 与其他 gstack 系统的协同
/review 集成
→ /review 中 Testing 专家的发现 → /qa 可以验证 → /qa 发现的问题 → 反馈给 /review 的审查清单 → PR quality_score 与 health_score 交叉验证
/ship 集成
→ /ship 读取最后 QA 健康评分 → 评分 < 70 → /ship 警告但不阻止 → 评分 < 60 → /ship 强烈建议先运行 /qa
/investigate 集成
→ /qa 发现复杂失败 → 建议运行 /investigate → /investigate 找到根因 → 修复后 /qa 验证
/health 集成
→ /health 是静态代码质量面板 → /qa 是动态测试质量评估 → 两者互补——static + dynamic = 完整质量视图
12. 测试框架引导——没有测试也能 QA
Bootstrap 策略
如果项目中没有测试框架: → 检测语言 → 选择标准框架 → 检测项目结构 → 确定测试目录 → 创建最小的测试配置 → 不自动写测试——只是让框架可用 → 输出框架配置供用户审查
支持的框架引导
→ JavaScript/TypeScript: jest / vitest → Ruby: rspec / minitest → Python: pytest / unittest → Go: testing 包(标准库,无需引导) → Rust: cargo test(标准工具,无需引导)
引导的边界
→ 只创建配置文件,不安装依赖
→ 不修改 package.json / Gemfile 等
→ 不写测试用例——那是开发者的工作
→ 报告:"测试框架已就绪。运行 npm test 开始。"
13. 结构拆解:自动化测试修复 Skill 模板
自动化 QA 测试修复型 Skill 模板
核心特征
→ 管理对象 = Web 应用的完整质量保证——从测试运行到 bug 修复的闭环 → 核心原则 = 系统性(11 阶段流水线)+ 节制修复(WTF 计数器 + 硬上限)+ 优雅降级(ctrl+c 不丢数据) → 关键设计 = 三层测试深度(Quick/Standard/Exhaustive)、 Diff-Aware 智能过滤、8 维健康评分、WTF 自调节机制、回归测试生成
通用结构
11-Phase Pipeline(11 阶段流水线)
- Phase 1-4: Initialize → Authenticate → Orient → Explore(环境准备 + 范围确定)
- Phase 5-7: Execute → Document → Wrap Up(测试执行 + 文档化 + 摘要)
- Phase 8-10: Triage → Fix Loop → Final QA(分诊 + 修复循环 + 最终验证)
- Phase 11: Report & Persist(报告 + TODOS.md + 健康评分持久化)
Three-Tier Test Depth(三层测试深度)
- Tier 1 Quick:仅单元测试,< 2min,适用小增量
- Tier 2 Standard:单元+集成,diff-aware,2-8min,适用标准 PR
- Tier 3 Exhaustive:全量+E2E+性能,20+min,适用发版前/重大重构
Diff-Aware Filtering(Diff-Aware 过滤)
- git diff origin/main --name-only → 变更文件列表
- 依赖追踪(import 链):测试变更文件的测试 + 导入了变更模块的测试
- 回退机制:依赖追踪不准 / 框架不支持过滤 → 全量运行
- 永不因优化而遗漏测试
WTF Self-Regulating Fix Loop(WTF 自调节修复循环)
- WTF 计数器:初始 0 → 修复通过 WTF-1 / 引入新失败 WTF+1 / 未解决原失败 WTF+2 / 3+新失败 WTF+3
- WTF >= 5 → 停止修复循环,输出警告
- WTF >= 10 → 回退最近的修复
- 50 次修复硬上限(无论 WTF 值)
- 修复回退机制:记录每次修复 diff,支持回滚
Health Score(8 维健康评分,0-100)
- Test Pass Rate 20% + Coverage 18% + Critical 15% + High 12% + Medium 10% + Build 10% + Lint 8% + Type Safety 7%
- 功能正确性权重 > 风格规整性(Pass Rate+Critical 共 35% vs Lint+Type 共 15%)
Graceful Interruption(优雅退出)
- 每 Phase 之间 + Phase 5 每条测试套件之间 + Phase 9 每个修复之间 → 检查点
- 中断 → 保存进度 + 部分报告 + 不清除临时文件/回归测试
- 后续 /qa 可从中断点继续
14. 电商案例:QA 修复循环——支付模块 Bug 修复全流程
🛒 实战案例:某电商平台支付模块重构后,跑测试发现12个单元测试+5个集成测试失败。工程师执行
/qa standard启动自动化诊断和修复循环——目标是让AI自动分诊失败原因、修复机械性问题(AUTO-FIX)、标记需要人工判断的复杂问题(NEEDS ANALYSIS)。
- Phase 1-4 环境准备与Diff分析:检测到技术栈Node.js+TypeScript,测试框架Jest。CI=true环境变量检测通过,但由于缺少支付API Key而降级运行(集成测试部分跳过,单元测试不受影响)。Diff-Aware模式生效——
git diff origin/main --name-only检测到23个变更文件(支付回调、订单状态、优惠券模块),通过import依赖链追踪自动选择34个相关测试(而非全量89个)——节省了65%的测试运行时间:全量需22分钟,Diff-Aware仅5分钟。- Phase 5-7 执行与文档化:34个测试运行结果——17通过、12失败、3跳过、2超时。失败摘要分级:CRITICAL 2个(回调签名验证使用SHA256而非微信要求的HMAC-SHA256、金额单位转换错误——扣款¥100变成100分=¥1)、HIGH 3个(回调超时未正确处理、订单状态非原子转换
SET status='PAID'缺少WHERE status='PENDING'、库存扣减read-check-write模式)、MEDIUM 6个(多券叠加计算顺序等)。初始Health Score 42/100⚠️。- Phase 8-9 分诊与修复循环:12个失败测试分诊为——AUTO-FIXABLE 7个(58%)、NEEDS ANALYSIS 5个(42%)。修复优先级按严重度降序处理:
- Fix 1(CRITICAL):回调签名SHA256→HMAC-SHA256,替换
crypto.createHash('sha256')为crypto.createHmac('sha256', secret)→重跑payment.test.ts通过(WTF=0)。- Fix 2(CRITICAL):金额单位转换,
totalAmount/100→totalAmount(已经是元)→重跑通过。但引入1个新失败——退款模块期望"分"→WTF短暂升至1→关联修复:退款模块也改为"元"统一→2个测试同时通过(WTF降为0)。- Fix 3-5(HIGH):订单状态原子CAS、库存扣减
UPDATE WHERE stock>0、回调重试幂等性→逐个修复重跑通过(WTF保持0)。- Fix 6-7(MEDIUM):多券叠加计算顺序、魔数3600提取为常量→通过。
- 残留5个NEEDS ANALYSIS:涉及业务规则决策("满200可用"券的叠加时价格判断基础是原始价还是折后价?运费按原始价格还是促销折后价计算?微信支付0元订单直接标记已支付的触发条件?)——这些不是机械问题,需要产品经理确认业务规则。
- 最终结果:34个测试→30通过(88%)、0失败、2跳过(5.9%)、2超时(5.9%,确定为环境问题而非代码bug)。Health Score从42→78/100。修复循环总耗时8分钟(5分钟测试运行+3分钟修复+重跑),AUTO-FIX修复了58%的失败测试,WTF计数器全程仅短暂升至1(未触发安全阀50次硬上限)。Diff-Aware节省了77%的测试时间(22分钟→5分钟)。
🔑 启示:QA修复循环的"分诊"价值被严重低估——不是所有测试失败都值得AI去修。12个失败中7个是机械问题(API调用错误、单位转换、原子操作缺失),5个是业务决策问题(券叠加规则、运费计算场景)。AUTO-FIX快速解决机械问题让人觉得"AI真快",NEEDS ANALYSIS让人类决策复杂问题让人知道"AI真聪明"——分诊的准确度决定了修复循环的效率。
16. 掌握检验
Q1:/qa 的三层测试深度中,Standard 模式与 Exhaustive 模式的核心区别是什么?
- A) Standard 只跑单元测试,Exhaustive 跑所有测试
- B) Standard 跑单元+集成测试(diff-aware),Exhaustive 跑单元+集成+E2E+性能(全量)
- C) Standard 不需要认证,Exhaustive 需要认证
- D) Standard 和 Exhaustive 完全相同
Q2:WTF-likelihood 自调节机制中,"修复引入 3+ 新失败"时 WTF +3,这比"修复未解决原失败"(WTF +2)惩罚更重。请解释为什么——这两种情况的危害有什么本质不同?
Q3:Diff-aware 模式的依赖追踪(import 链)如果漏掉了某个真正受影响的测试文件,回退机制是什么?为什么说"永不因优化而遗漏测试"?
Q4:Health Score 的 8 个维度中,为什么 Test Pass Rate(20%)和 Test Coverage(18%)权重最高,而 Lint/Format(8%)和 Type Safety(7%)权重较低?这个权重分配体现了对"测试质量"和"代码风格"的什么工程价值观?
Q5:在 ctrl+c 优雅退出策略中,检查点粒度为什么要细化到"Phase 9 中每个修复之间"?如果在修复循环第 27 次修复后用户中断,恢复机制应该基于什么信息来决定"是否从中断点继续"?
Q6:QA 修复循环和 review 的 Fix-First 启发式都涉及自动修复,但 QA 的修复循环多了 WTF 计数器和 50 次硬上限。请从"测试环境的不确定性"和"代码修复的可逆性"两个角度,解释为什么 QA 的修复循环需要比 review 更强的安全机制。
17. 答案
点击查看答案
Q1:B —— Quick 只跑单元测试(<2min),Standard 跑单元+集成测试且 diff-aware 过滤(2-8min),Exhaustive 跑单元+集成+E2E+性能测试全量模式(20+min)。
Q2:"修复未解决原失败"(WTF +2)说明修复方向可能错了——应该从头分析而非继续盲目修。"修复引入 3+ 新失败"(WTF +3)是灾难性的——不仅没修好原来的问题,还制造了连锁破坏。这就像给漏水的水管打补丁时把整个水管系统打破了——危害远大于"补丁没贴上"。惩罚更重是因为"制造新问题"的修复如果不被快速阻止,会在短时间内把代码库质量从 X 分恶化到 X-n 分,而且是多维度恶化(3+ 新失败可能分布在不同的模块)。
Q3:回退机制是当 import 链追踪不准确或测试框架不支持文件过滤时,自动回退到全量运行所有测试。优化(diff-aware)是可选的,但正确性(不遗漏测试)是强制性的——这就是"永不因优化而遗漏测试"的含义。Diff-aware 模式的价值在于"通常更快",而非"有时更准"——如果它的准确性不确定,宁可慢但全,绝不快但漏。
Q4:高权重的 Test Pass Rate 和 Coverage 衡量的是"代码的行为正确性"——你的代码做对了该做的事吗?低权重的 Lint 和 Type Safety 衡量的是"代码的书写规范性"——你的代码写得规整吗?工程价值观:功能正确 > 风格规整。一个 Lint 全过但逻辑错误的代码 = 生产事故;一个 Lint 有 20 个 warning 但逻辑正确的代码 = 可运维(虽然需要改善)。权重分配反映了"什么错误会造成实际损失"的优先级排序。
Q5:每修一个 bug 后立即检查点是必要的,因为每次修复都可能引入新问题(WTF 计数器在每次修复后更新)。如果在第 27 次修复后中断,恢复决策应基于:①中断前的 WTF 值(低 → 修复质量好,值得继续;高 → 之前的修复方向有问题应先分析再继续);②已完成修复的测试结果(都通过了?有些引入新失败?);③剩余未处理的失败数量和严重度。如果 WTF < 5 且 90% 以上修复通过,可从中断点继续;如果 WTF >= 5,应分析根因后重新开始修复而非盲目继续。
Q6:测试环境的不确定性——QA 中的测试失败可能来自环境问题(CI 机器慢、数据库状态不一致、外部服务不可达)而非代码 bug。修复"环境导致的假失败"几乎不可能成功——每次修复都在打一个不存在的 bug——需要更强的"停止机制"来识别这种无底洞。代码修复的可逆性——QA 修复可能涉及业务逻辑修改(不只是 review 中的 AUTO-FIX 级别),错误的业务逻辑修复比错误的死代码删除更难发现和回退——更需要 WTF 计数器来及时阻止"用更多错误修复覆盖原始错误"的雪崩。
(5/6 通过)
延伸阅读
- [[L6-19-外部AI评论分诊|外部AI评论智能分诊 —— 过滤噪音、保留真问题]]
- [[L6-21-纯报告式QA|纯报告式QA —— 只告诉你哪里有问题但不乱改代码]]
- [[L6-22-线上故障侦探|线上故障侦探 —— 像福尔摩斯一样追查bug的根因]]

评论区
共 0 条评论