关于 ai-test-generation
面向测试团队的 AI 测试生成技能,通过结构化流程把需求转化为可审查的测试。它先形成风险分析、覆盖矩阵和断言预言机,再生成代码并要求人工审核。
主要功能
- 01从需求、缺陷或代码提取规则
- 02分析风险、不变量与歧义
- 03建立需求到场景的覆盖矩阵
- 04将测试场景与断言设计分开
- 05生成可追溯的测试代码
- 06要求人工审查生成结果
适用场景
- 01根据 PRD 或用户故事规划测试
- 02针对代码变更生成回归场景
- 03为缺陷报告编写验证测试
- 04从 API 模式设计覆盖场景
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ petrkindlmann/ qa-skills --skill ai-test-generation安装后在 Claude Code 中输入/ai-test-generation确认已加载。
附带文件references/prompt-patterns.md
详细介绍
**开始之前:**检查项目根目录下是否有 .agents/qa-project-context.md。该文件包含技术栈、测试框架、命名约定、选择器策略和已知风险区域,可显著提升生成测试的质量。
快速路径
无论输入是什么,流水线都相同;只有第 1 步提取的重点会改变。找到匹配的行,然后保持不变地执行第 2 至第 7 步。
| 输入类型 | 第 1 步提取内容 | 注意事项 |
|---|---|---|
| PRD / 功能规格 | 实体、业务规则、验收标准、NFR、明确说明的假设 | 从“无缝”“快速”等措辞中推断出的隐含需求 |
| 用户故事 + AC | 每条 AC → ≥1 个正常场景 + ≥1 个异常场景 | 一行 AC 中隐含多种行为的情况 |
代码差异(git diff main...HEAD) | 新增/变更的代码路径、修改的条件判断、移除的行为 | 回归范围:测试变更的路径,而不是整个模块 |
| Bug 报告 | 复现步骤、预期结果与实际结果、环境 | 编写断言预期结果的测试——当前会失败,修复后会通过 |
| OpenAPI / GraphQL SDL | 端点、架构、必填字段、枚举、身份验证 | 每个端点都覆盖验证、身份验证失败和边缘情况,而不只是 200 响应 |
Playwright 项目还需选择 Agent 集成模式——参见“探索问题”中的问题 2。
探索问题
先检查 .agents/qa-project-context.md——如果文件存在,请使用其中的信息,并跳过已得到解答的问题。然后澄清以下事项:
-
**输入来源是什么?**PRD / 规格、用户故事 + AC、代码差异、Bug 报告或 API 架构。这决定了第 1 步提取的重点(参见“快速路径”)。对于 LLM/AI 功能规格,请停止——应在
ai-system-testing中生成评估数据集,而不是 Playwright 规格。 -
目标测试框架是什么?(如果使用 Playwright)应采用哪种 Agent 集成模式?
- **端到端测试:**Playwright(首选)、Cypress。**单元测试:**Jest、Vitest、pytest。**API 测试:**Playwright
APIRequestContext、Supertest、requests。 - Playwright CLI + agents(推荐用于 Claude Code / Codex / Cursor):
npx playwright init-agents --loop=claude会将规划、生成和修复 Agent 脚手架生成为.claude/agents/中的 Markdown 文件。这些是交互式开发工具,可生成在 CI 中无需修改即可运行的标准 Playwright 测试。可节省 Token;在 Agent 的循环中运行。 - Playwright MCP(
npx @playwright/mcp@latest):开销较高,但适用于 Agent 必须在长时间会话中交互式操控实时浏览器的情况。 - 两者都不用——使用 AI 作为草稿助手,手动编写测试。
- **端到端测试:**Playwright(首选)、Cypress。**单元测试:**Jest、Vitest、pytest。**API 测试:**Playwright
-
**有哪些项目上下文可用?**现有测试模式、Page Object / 助手、数据工厂 / 固件、CI 限制(超时、并行度)。上下文越充分,后续清理工作越少。
-
**审查工作流是什么?**完整流水线 → 人工审查 → 合并(默认);仅生成场景 → 人工编写代码;或先生成代码 → 人工迭代完善。
-
**需要哪些领域知识?**受监管行业(医疗保健、金融)的合规要求、领域不变量(金额不得为负、预约不得重叠)、过去事件中已知的风险区域。
核心原则
-
先规划流水线,再编写代码。 在明确测试什么、为什么测试以及如何验证之前,绝不生成测试代码。七步流水线旨在防止过早生成代码,以免测试错了对象。
-
结构化中间产物才是核心成果。 假设文档、覆盖矩阵和判定依据定义比测试代码本身更有价值。它们可供审查、可追溯且可复用。
-
将测试内容与验证方式分开。 场景生成(测试什么)和判定依据设计(如何验证)是两项不同的认知任务。将两者混在一起,会让场景偏向容易断言的内容,并把断言当作事后补充。
-
AI 生成初稿;由人工审查和完善。 绝不在未经人工审查的情况下发布 AI 生成的测试。AI 能加快进度,但不能取代判断。
-
上下文至关重要。 向大模型提供你的约定、现有模式、选择器策略和数据设置。上下文越充分,后续清理工作就越少。
-
质量胜于数量。 每项测试都有维护成本。应聚焦关键路径、复杂逻辑和已知风险区域,而不是测试数量。
流水线
强制工作流 — Agent 必须按以下顺序执行:
Step 1: Extract → Requirements, entities, business rules from input
Step 2: Analyze → Risks, invariants, edge cases, ambiguities
Step 3: Map → Coverage matrix (requirement → scenario → priority)
Step 4: Generate → Candidate scenarios (happy + boundary + negative + security + a11y)
Step 5: Design → Assertions and oracles SEPARATELY from scenarios
Step 6: Code → Test code (only after all above exist)
Step 7: Review → Human review with traceability back to source
每个步骤(提取、风险分析、场景、判定依据、代码)的完整提示词模板都位于 references/prompt-patterns.md。以下说明各步骤输出的形式。
步骤 1:提取需求和实体
将输入解析为结构化元素:实体(包含角色/状态/属性)、业务规则(编号)、显式需求([REQ-N],在源材料中明确说明)和隐式需求([IMP-N],推断得出——每一项都要标记,供人工确认)。将显式需求与推断需求分开,是防止把假设当成规范进行测试的关键。
步骤 2:风险分析与不变量
推导可能出错的情况、必须始终成立的条件,以及源材料未明确说明的部分。
- 风险 — 表格列为
Risk | Likelihood | Impact | Source Requirement(例如,库存扣减时发生竞态条件、邮件延迟超过 30s)。 - 不变量(必须始终成立)—
stock >= 0、order total = sum(items) + tax + shipping、user sees only their own orders。 - 歧义(需要人工答复)—“免运费是在应用折扣码之前还是之后生效?”明确记录这些问题;不要默默自行选择。
- 从风险推导的边界情况 — 两个用户同时购买最后一件商品;付款成功,但邮件服务不可用。
步骤 3:覆盖矩阵
这是最重要的单一产物,可防止遗漏和重复。将每项需求映射到场景,并标明类别、优先级和判定依据类型:
| Requirement | Scenario | Category | Priority | Oracle Type |
|---|---|---|---|---|
| REQ-1 | 将单件商品添加到空购物车 | Happy path | P0 | State: cart count = 1 |
| REQ-1 | 添加缺货商品 | Negative | P0 | UI: error message, cart unchanged |
| REQ-2 | 使用有效银行卡完成结账 | Happy path | P0 | State: order created, stock decremented |
| REQ-2 | 两个用户同时结账购买最后一件商品 | Race condition | P1 | 一人成功,另一人收到库存错误 |
| INV-1 | 库存绝不为负数 | Invariant | P0 | Data: stock >= 0 after any operation |
完成后,进行验证:每项需求至少有 1 个正常场景和 1 个负向场景;每个不变量都有直接测试;步骤 2 中的每项风险都有对应场景;没有两行测试相同内容。
步骤 4:生成候选场景
针对矩阵中的每一行,使用 Given/When/Then 格式编写完整场景,并明确测试数据要求(Given: 用户购物车中有 99 件商品(上限为 100 件);When: 再添加一件;Then: 数量 = 100)。系统地覆盖以下类别:
| 类别 | 描述 |
|---|---|
| 正常路径 | 用户严格按照功能设计的方式操作 |
| 边界 | 有效输入范围的边缘——使用 BOUNDARIES 框架(references/prompt-patterns.md) |
| 负面 | 无效输入、未经授权的操作 |
| 安全 | 绕过身份验证、注入、权限提升 |
| 无障碍 | 屏幕阅读器、仅使用键盘、对比度 |
| 状态转换 | 状态之间的有效和无效转换 |
| 并发 | 两个用户同时操作 |
步骤 5:设计断言与判定依据
与步骤 4 刻意分开。 场景描述行为;判定依据描述如何验证行为。针对每个场景,定义涵盖以下类别的判定依据——单条断言很少足以证明某个行为:
| 判定依据类别 | 断言内容 | 示例 |
|---|---|---|
| UI 状态 | 可见文本/元素状态 | cart badge toHaveText('1') |
| 数据 | 通过 API/数据库持久化的状态 | GET /api/cart 返回 1 件商品,且总额正确 |
| 负面 | 不应发生的情况 | 无错误提示;未跳转离开当前页面 |
| 副作用 | 异步/外部结果 | 触发 analytics add_to_cart;< 30 秒内邮件进入收件箱 |
**判定依据质量规则:**断言业务结果,而不是实现细节;使用最具体的可用断言(toHaveText('$29.99'),而不是 toBeTruthy());加入负面断言;验证数据完整性,而不仅仅是 UI;断言无障碍特性(焦点管理、实时区域播报)。
步骤 6:生成测试代码
仅在步骤 1-5 产出经过审查的工件后执行。 代码是将场景和判定依据机械地转换为框架语法,并附上追溯注释,将测试关联到需求和场景:
/**
* Scenario: SC-001 — Add single item to empty cart
* Requirement: REQ-1 (User can add items to cart)
* Priority: P0
*/
test('add single item to empty cart', async ({ page, testProduct }) => {
await page.goto(`/products/${testProduct.id}`); // Given
await page.getByRole('button', { name: 'Add to cart' }).click(); // When
await expect(page.getByTestId('cart-badge')).toHaveText('1'); // Then
await expect(page.getByTestId('error-toast')).not.toBeVisible(); // Negative oracle
});
**代码生成规则:**遵循项目约定(来自 qa-project-context.md);复用现有 Page Objects、夹具和数据工厂;添加追溯注释(Scenario: SC-XXX、Requirement: REQ-XX);遵循项目的选择器策略;将设置/清理操作放在夹具中,而不是内联编写。
步骤 7:人工审查
此步骤不可省略——这是必需的流水线步骤。审查此流水线刚刚生成的测试,并在合并前完成。(如需审查并非由此流水线刚生成的现有测试套件,请改用 ai-qa-review。)根据此清单逐一检查生成的测试:
- **可追溯到需求:**测试 → 场景 → 覆盖矩阵行 → 需求的关联链清晰可循。
- **测试行为,而非实现:**无害的重构不会导致测试失败。
- **抽象层级正确:**测试类型合适(单元测试、集成测试或 E2E 测试)。
- **测试命名与可读性:**测试名称说明了所测行为;读者无需解读测试正文即可理解意图。
- **测试隔离/无共享状态:**测试创建并清理自己的数据,不依赖同组测试的执行顺序,并且单独运行或按任意顺序运行都能通过。
- **测试数据真实:**数据合理、多样,并使用
example.com。 - **断言有意义:**与判定依据的定义一致;具体明确,而非
toBeTruthy()。 - **符合项目约定:**遵循命名、结构和选择器策略。
- **无不稳定性风险:**没有硬编码超时、竞态条件或顺序依赖。
- **包含边缘情况:**不局限于正常路径。
- **假设已验证:**步骤 2 中的模糊之处已在编码前解决。
**每项测试的审查结果:**保留(原样合并)· 修改(修复列出的问题后合并)· 拒绝(需求错误、抽象层级错误、虚构 API)· 暂缓(受模糊之处阻碍)。
护栏
硬性规则。Agent 必须遵守。
- 禁止先写代码再补覆盖。 在步骤 1-3(需求、含书面假设的风险分析、覆盖矩阵)完成之前,绝不编写测试代码。如果 Agent 跳过这些步骤直接写代码:立即停止,返回前面的步骤。
- 断言结果,而非实现。 使用
expect(screen.getByRole('progressbar')).toBeVisible(),而不是expect(component.state.isLoading).toBe(true)。使用expect(page.getByTestId('cart-badge')).toHaveText('1'),而不是expect(store.dispatch).toHaveBeenCalledWith(...)。 - 始终先写场景(步骤 4),再写预期结果(步骤 5)。 场景说明发生了什么;预期结果说明如何验证。将二者混在一起,会使场景偏向容易断言的内容。
- 始终产出中间成果——假设文档、未解决的歧义、预期结果候选项和可追溯链,即使是简略版本也不例外。
发现以下情况时请标记:
- 臆造的 API——代码库中不存在的端点、选择器、方法或导入项。在人工审查前进行机械验证(参见“验证”)。
- 重复场景——相同行为仅使用了略有不同的数据。合并或参数化。
- 低价值断言——
expect(response).toBeTruthy()、expect(page).toHaveURL(/.*/). - 缺少负面用例——如果所有场景都是成功路径,覆盖矩阵就不完整。
- 不真实的测试数据——
[email protected]、John Doe、password123。请使用多样、可信的数据,并采用example.com域名。
各步骤的模型选择
按难度选择模型,而非凭习惯。机械式提取(步骤 1)和覆盖矩阵整理(步骤 3)使用低成本模型即可——Haiku 4.5 或 Sonnet 4.6 已足够。预期结果设计(步骤 5)和对臆造内容敏感的代码生成(步骤 6)出错代价较高,应升级到 Opus 4.8;只有面对真正困难的推理问题(微妙的不变量、受监管领域的逻辑)时,才使用 Fable 5。每一步都运行最强模型很浪费;步骤 6 使用最便宜的模型则会导致编造 API。
验证
将“臆造的 API”警告转化为机械检查关卡。在步骤 6 完成后、人工审查前:
- 解析导入项 / 类型。 TypeScript:
npx tsc --noEmit——臆造的导入项和错误的签名都会在此处报错。Python:python -m pyflakes <files>或ruff check。 - 使用 grep 对照代码库检查生成的选择器 / 端点。 确认每个
getByTestId('...')中的 ID,以及测试调用的每个 API 路径,确实存在于源代码中:grep -roE "getByTestId\('([^']+)'\)" generated/ | sed -E "s/.*'([^']+)'.*/\1/" | sort -u \ | while read id; do grep -rq "$id" src/ || echo "MISSING testid: $id"; done - 运行一次测试套件。 引用了不存在的路由 / 选择器的测试会立即失败;在审查前将这些测试隔离,而不要审查无效代码。
任何 MISSING 行或 tsc 错误都表示存在臆造内容,必须在人工投入审查时间前修复。
反模式
- 跳过步骤,直接写代码。 最常见的失败:Agent 拿到 PRD 后就立即编写测试。没有覆盖矩阵,就会漏掉一些场景,还会重复覆盖另一些场景。这套流程就是为避免这种情况而设立的。
- 断言实现,而非行为。
expect(component.state.isLoading).toBe(true)会在任何重构时失效。应断言expect(screen.getByRole('progressbar')).toBeVisible()——也就是用户能观察到的内容。 - 混淆场景和断言。 把“测试这件事并检查这个值”写成一个步骤。应将测试什么与如何验证分开。
- 提示词中没有项目上下文。 没有项目约定和现有模式,就只能得到通用测试。
qa-project-context.md正是为此而设。 - 生成过多。 AI 可能会为一个简单函数编写 50 个测试。每个测试都会增加维护成本。使用覆盖矩阵,将生成范围限定在有意义的场景内。
- 不求甚解地复制粘贴。 如果你无法解释生成的测试做了什么,以及为什么这么做,就不要合并。你不理解的测试,出了问题也无从调试。
- 未经审查就交付。 第 7 步不是可选项。AI 测试经常包含幻觉 API、错误的选择器、不正确的业务逻辑,以及只有人工审查才能发现的不稳定性。
- 忽略反馈闭环。 AI 测试发现真实 Bug 时,记录有效的提示词模式;出现误报时,记录问题所在。建立项目专属的有效方法库。
完成标准
- 七项产物全部齐备:需求文档、风险与不变量、覆盖矩阵、场景集、判定标准定义、测试代码,以及包含每项测试 KEEP/MODIFY/REJECT/DEFER 决策的审查记录。
- 在编写任何测试代码文件之前,已生成并审查覆盖矩阵。
- 验证通过:
tsc --noEmit(或对应语言的等效命令)以 0 退出,并且选择器/端点 grep 结果中没有MISSING行。 - 每项生成的测试都有记录在案的人工审查决策;没有任何测试在缺少审查决策的情况下被标记为 KEEP。
- 套件的 CI 作业以 0 退出(绿色)。
- 已记录可复现性元数据:确切的模型 ID(例如
claude-opus-4-8、claude-sonnet-4-6、claude-haiku-4-5-20251001)、输入源哈希,以及所调用的任何 skill / CLI / MCP 服务的版本。
相关 Skills
- qa-project-context — 设置上下文文件,大幅提升 AI 生成测试的质量。请先配置此项。
- playwright-automation — 深入介绍 Playwright 模式(POM、fixtures、CI),以及 Test Agents(
init-agents --loop=claude,脚手架生成到.claude/agents/中)和在 Discovery Q2 中选择的@playwright/mcp模式。生成的测试会放在此框架内。 - unit-testing — 用于生成单元级测试的 Jest、Vitest、pytest 模式。
- api-testing — 从 OpenAPI 规范生成测试时使用的端点测试模式。
- test-strategy — 在生成测试之前,决定测试什么以及在哪个层级测试。
- test-reliability — 提高生成测试的可靠性:不稳定测试分类、修复、视频凭证。
- ai-system-testing — 当输入是 LLM 功能规范时,在此处生成评估数据集(Promptfoo、DeepEval、Ragas、Braintrust),而不是生成 Playwright 规范。
- ai-qa-review — 审查你并非刚刚生成的现有测试套件(测试异味、可测试性)。此处的第 7 步仅审查这套流程自身的产出。
- ai-bug-triage — 生成的测试发现 Bug 时,通过分诊流程对其分类并报告。
参考文件(位于 references/ 中)
- prompt-patterns.md — 与七个步骤对应的完整提示词库:提取、风险分析、场景生成、判定标准设计和代码生成提示词,以及第 4 步中使用的 BOUNDARIES 边缘情况框架。