31c - 需求到测试用例自动化
本文是《AI Agent 实战手册》第 31 章第 3 节。 上一节:31b-AI测试生成工作流 | 下一节:31d-AI辅助PBT
概述
“需求写完了,测试用例谁来写?“——这是每个团队在交付压力下都会面对的问题。2025-2026 年,AI 正在将”需求→测试用例”这条链路从手动、碎片化的过程,转变为自动化、可追溯的管线。本节深入拆解从验收标准提取、BDD/Gherkin 自动生成、需求可追溯性矩阵(RTM)维护,到 Spec 驱动测试和 CI/CD 集成的完整自动化管线,帮助你建立从需求文档到测试代码的全链路闭环。
1. 验收标准提取自动化
1.1 为什么验收标准是测试自动化的起点?
验收标准(Acceptance Criteria, AC)是需求和测试之间的桥梁。一条好的验收标准天然就是一个测试用例的描述:
需求文档 (PRD/User Story/Jira Ticket)
│
▼
验收标准 (AC) ←── 测试用例的"种子"
│
┌────┼────┐
▼ ▼ ▼
单元 集成 E2E
测试 测试 测试传统做法中,QA 工程师手动阅读需求文档,提取验收标准,再转化为测试用例。这个过程存在三个核心问题:
| 问题 | 影响 | AI 解决方案 |
|---|---|---|
| 遗漏 | 需求文档中的隐含条件被忽略 | AI 系统化扫描,枚举所有条件分支 |
| 歧义 | 自然语言描述不精确,不同人理解不同 | AI 将模糊描述转化为结构化 EARS 格式 |
| 滞后 | 需求变更后测试用例未同步更新 | AI 监控需求变更,自动触发测试更新 |
1.2 AI 提取验收标准的工作流
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 需求来源 │ │ AI 解析 │ │ 结构化 AC │
│ │ │ │ │ │
│ • PRD 文档 │────→│ • NLP 解析 │────→│ • EARS 格式 │
│ • Jira Ticket │ │ • 条件提取 │ │ • Given/When │
│ • User Story │ │ • 边界识别 │ │ /Then │
│ • Slack 讨论 │ │ • 隐含推理 │ │ • 优先级标注 │
└──────────────┘ └──────────────┘ └──────┬───────┘
│
┌──────┴───────┐
│ 人工审查 │
│ 确认/补充/修正│
└──────────────┘工具推荐
| 工具 | 用途 | 价格 | 适用场景 |
|---|---|---|---|
| Claude Code | 从需求文档提取 AC,生成结构化测试需求 | $20/月(Pro)/ $100/月(Max 5x) | 全项目需求分析,复杂业务逻辑 |
| Kiro | Spec 驱动自动提取 AC,生成正确性属性 | 免费(50 次/月)/ $19/月(Pro) | 结构化需求→测试全链路 |
| Qase | AI 测试管理,从需求自动生成测试用例 | 免费(3 用户)/ $35/月起(Business) | 团队测试管理与追溯 |
| Kollabe AC Generator | 从用户故事生成验收标准 | 免费 | 快速生成 AC 草稿 |
| Gherkinizer | 从用户故事生成 BDD Gherkin 测试 | 免费(基础)/ 付费计划 | BDD 团队快速生成 Feature 文件 |
| AIO Tests | Jira 集成的 AI 测试管理 | $4.79/用户/月起 | Jira 生态团队 |
| Testomat.io | AI 驱动测试管理,BDD 支持 | 免费(基础)/ $15/用户/月起 | 敏捷团队自动化测试管理 |
| Codespell | 企业级 AI Gherkin Feature 文件生成 | 联系销售 | 大规模 BDD 自动化 |
操作步骤
步骤 1:准备需求文档
确保需求文档包含以下关键信息:
- 功能描述(What)
- 用户角色(Who)
- 业务价值(Why)
- 约束条件(Constraints)
- 非功能需求(Performance, Security 等)
步骤 2:使用 AI 提取验收标准
步骤 3:人工审查和补充
审查 AI 提取的验收标准,重点关注:
- 是否覆盖了所有业务规则?
- 是否包含了隐含的边界条件?
- 是否考虑了异常和错误场景?
- 是否有歧义需要澄清?
提示词模板
模板 1:从 PRD 提取验收标准
你是一个资深 QA 架构师。请从以下需求文档中提取所有验收标准。
## 需求文档
[粘贴 PRD 或用户故事]
## 提取要求
1. 使用 EARS(Easy Approach to Requirements Syntax)格式:
- Ubiquitous(始终成立):THE 系统 SHALL [行为]
- Event-Driven(事件触发):WHEN [触发条件], THE 系统 SHALL [行为]
- State-Driven(状态触发):WHILE [状态], THE 系统 SHALL [行为]
- Unwanted Behavior(异常处理):IF [异常条件], THEN THE 系统 SHALL [处理]
- Optional Feature(可选功能):WHERE [配置条件], THE 系统 SHALL [行为]
2. 对每条验收标准标注:
- 编号(如 AC-1.1)
- 优先级(P0/P1/P2)
- 测试类型建议(单元/集成/E2E/PBT)
- 是否需要特殊测试环境
3. 额外识别:
- 隐含的边界条件(文档中未明确但逻辑上存在的)
- 潜在的竞态条件或并发场景
- 安全相关的验收标准
- 性能相关的验收标准
4. 输出格式:Markdown 表格 + 详细描述模板 2:从 Jira Ticket 提取验收标准
分析以下 Jira Ticket,提取结构化的验收标准:
## Ticket 信息
- 标题:[Ticket 标题]
- 描述:[Ticket 描述]
- 评论/讨论:[相关评论]
- 关联 Ticket:[依赖或关联的 Ticket]
## 提取要求
1. 从描述和评论中提取所有显式和隐式的验收标准
2. 将每条标准转化为 Given/When/Then 格式
3. 标注每条标准对应的 Ticket 来源(描述/评论/关联)
4. 识别评论中讨论但未写入描述的隐含需求
5. 标注需要与产品经理确认的模糊点
输出格式:
| AC 编号 | Given | When | Then | 来源 | 优先级 | 待确认 |1.3 EARS 格式详解与测试映射
EARS(Easy Approach to Requirements Syntax)是一种结构化的需求编写方法,每种模式天然对应不同的测试策略:
| EARS 模式 | 语法模板 | 测试策略 | 测试类型 | 示例 |
|---|---|---|---|---|
| Ubiquitous | THE 系统 SHALL [行为] | 全局不变量检查 | PBT(属性测试) | THE 系统 SHALL 在所有 API 响应中包含请求 ID |
| Event-Driven | WHEN [事件], THE 系统 SHALL [行为] | 触发条件 + 预期结果 | 单元测试 + 集成测试 | WHEN 用户提交注册表单, THE 系统 SHALL 发送验证邮件 |
| State-Driven | WHILE [状态], THE 系统 SHALL [行为] | 状态前置条件 + 行为验证 | 状态机测试 + PBT | WHILE 用户处于试用期, THE 系统 SHALL 显示升级提示 |
| Unwanted | IF [异常], THEN THE 系统 SHALL [处理] | 异常注入 + 错误处理验证 | 异常路径测试 | IF 数据库连接失败, THEN THE 系统 SHALL 返回 503 |
| Optional | WHERE [配置], THE 系统 SHALL [行为] | 功能开关 + 条件行为 | 配置驱动测试 | WHERE 用户启用 2FA, THE 系统 SHALL 要求验证码 |
EARS 到测试用例的自动转化规则
EARS 模式 → 测试骨架
Ubiquitous:
THE 系统 SHALL X → FORALL input: ValidInput, X(input) == true
(属性测试:对所有有效输入,X 始终成立)
Event-Driven:
WHEN A, SHALL B → test: given(precondition), when(A), then(B)
(单元/集成测试:触发 A 后验证 B)
State-Driven:
WHILE S, SHALL B → test: given(state == S), when(action), then(B)
(状态测试:在状态 S 下执行操作,验证 B)
Unwanted:
IF E, THEN SHALL H → test: given(precondition), when(inject(E)), then(H)
(异常测试:注入异常 E,验证处理 H)
Optional:
WHERE C, SHALL B → test: given(config(C) == true), when(action), then(B)
test: given(config(C) == false), when(action), then(NOT B)
(配置测试:开启/关闭配置 C,验证不同行为)1.4 实际示例:从用户故事到验收标准
输入:用户故事
作为一个电商用户,我希望能够使用优惠券下单,
以便在购物时享受折扣优惠。
业务规则:
- 每个订单只能使用一张优惠券
- 优惠券有有效期
- 优惠券有最低消费门槛
- 部分商品不参与优惠AI 提取的验收标准(EARS 格式):
## AC-1: 优惠券应用
### AC-1.1 [Event-Driven] 正常应用
WHEN 用户在结算页面输入有效优惠券码,
THE 系统 SHALL 验证优惠券有效性并显示折扣金额
- 优先级:P0
- 测试类型:集成测试
### AC-1.2 [Unwanted] 过期优惠券
IF 用户输入的优惠券已过期,
THEN THE 系统 SHALL 显示"优惠券已过期"错误提示并不应用折扣
- 优先级:P0
- 测试类型:单元测试
### AC-1.3 [State-Driven] 最低消费未达标
WHILE 订单金额低于优惠券最低消费门槛,
THE 系统 SHALL 显示"未达到最低消费 ¥[金额]"提示
- 优先级:P0
- 测试类型:单元测试 + PBT
### AC-1.4 [Ubiquitous] 单券限制
THE 系统 SHALL 确保每个订单最多只能应用一张优惠券
- 优先级:P0
- 测试类型:PBT(属性测试)
### AC-1.5 [Optional] 商品排除
WHERE 购物车中包含不参与优惠的商品,
THE 系统 SHALL 仅对参与优惠的商品计算折扣
- 优先级:P1
- 测试类型:集成测试
### AC-1.6 [隐含] 并发使用
IF 同一优惠券被多个用户同时使用且剩余次数为 1,
THEN THE 系统 SHALL 仅允许一个用户成功使用,其他用户收到"优惠券已被使用"提示
- 优先级:P1
- 测试类型:并发测试
- 备注:原需求未明确,建议与产品确认2. 需求到测试用例的映射管线
2.1 全链路映射架构
从需求到可执行测试代码的完整管线包含五个阶段:
┌─────────────────────────────────────────────────────────────────────────┐
│ 需求→测试用例自动化管线 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 阶段 1 阶段 2 阶段 3 阶段 4 │
│ 需求解析 AC 提取 测试设计 代码生成 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ PRD/Story │───→│ EARS 格式│───→│ 测试策略 │───→│ 测试代码 │ │
│ │ Jira/Spec │ │ AC 列表 │ │ 类型选择 │ │ 框架适配 │ │
│ │ 会议纪要 │ │ 优先级 │ │ 覆盖矩阵 │ │ 断言生成 │ │
│ └──────────┘ └──────────┘ └──────────┘ └────┬─────┘ │
│ │ │
│ 阶段 5 │
│ 验证与追溯 │
│ ┌──────────┐ │
│ │ 运行测试 │ │
│ │ RTM 更新 │ │
│ │ 覆盖报告 │ │
│ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘2.2 各阶段详解
| 阶段 | 输入 | AI 动作 | 输出 | 人工审查点 |
|---|---|---|---|---|
| 1. 需求解析 | PRD、User Story、Jira Ticket | 解析自然语言,识别功能点和约束 | 结构化需求列表 | 确认需求理解正确 |
| 2. AC 提取 | 结构化需求 | 提取验收标准,转化为 EARS 格式 | AC 列表(含优先级) | 审查 AC 完整性和准确性 |
| 3. 测试设计 | AC 列表 | 选择测试类型,设计测试策略 | 测试设计文档 | 确认测试策略合理 |
| 4. 代码生成 | 测试设计 + 源代码 | 生成测试代码,适配框架 | 可执行测试文件 | 审查断言正确性 |
| 5. 验证追溯 | 测试代码 + AC 列表 | 运行测试,更新 RTM | 测试报告 + RTM | 审查覆盖率 |
工具推荐
| 工具 | 用途 | 价格 | 适用场景 |
|---|---|---|---|
| Kiro Specs | 需求→设计→任务→测试的全链路管线 | 免费(50 次/月)/ $19/月(Pro) | Spec 驱动开发团队 |
| TestRail | 测试管理 + 需求追溯 | $40/用户/月起 | 企业级测试管理 |
| Qase AIDEN | AI 测试 Agent,自动生成和执行测试 | 免费(3 用户)/ $35/月起 | AI 驱动测试管理 |
| Testomat.io | AI 测试管理 + BDD 支持 + 自动化集成 | 免费(基础)/ $15/用户/月起 | 敏捷团队 |
| AccelQ | AI 自愈自动化 + 智能测试管理 | 联系销售(约 $60/用户/月起) | 企业级无代码自动化 |
| Zephyr Scale | Jira 原生测试管理 + 追溯 | $1/用户/月起(Cloud) | Jira 深度集成团队 |
| Xray | Jira 测试管理 + BDD + 追溯矩阵 | $10/用户/月起 | Jira 生态 BDD 团队 |
操作步骤
步骤 1:建立需求→测试的映射规则
在项目的 Steering 规则文件中定义映射约定:
# 需求→测试映射规则(.kiro/steering/test-mapping.md)
## 映射约定
- 每条 P0 验收标准必须有至少 2 个测试用例(正常路径 + 异常路径)
- 每条 P1 验收标准必须有至少 1 个测试用例
- P2 验收标准根据风险评估决定是否需要测试
- Ubiquitous 类型的 AC 优先使用 PBT
- Event-Driven 类型的 AC 使用 example-based 测试
- 每个测试用例必须标注对应的 AC 编号
## 测试文件命名
- 单元测试:`*.test.ts`(与源文件同目录)
- 集成测试:`*.integration.test.ts`(tests/integration/)
- E2E 测试:`*.e2e.ts`(tests/e2e/)
- PBT:`*.property.test.ts`(与源文件同目录)
## 追溯标注格式
每个测试用例必须包含以下注释:
// Validates: AC-X.Y [AC 描述]
// Priority: P0/P1/P2步骤 2:使用 AI 生成测试设计文档
基于以下验收标准,生成测试设计文档:
## 验收标准
[粘贴 AC 列表]
## 源代码
[粘贴相关源代码或 API 定义]
请为每条 AC 生成:
1. 测试场景列表(正常/边界/异常)
2. 测试数据需求
3. 前置条件和后置条件
4. 预期结果
5. 推荐的测试类型和框架步骤 3:生成可执行测试代码
基于以下测试设计文档,生成可执行的测试代码:
## 测试设计
[粘贴测试设计文档]
## 技术栈
- 测试框架:[Vitest/Jest/Pytest]
- PBT 框架:[fast-check/Hypothesis]
- 项目约定:[粘贴 Steering 规则]
要求:
1. 每个测试标注对应的 AC 编号
2. 使用 AAA 模式(Arrange-Act-Assert)
3. PBT 属性标注 Validates 注释
4. 生成器约束到有效输入空间提示词模板
模板 3:端到端需求→测试生成
你是一个资深测试架构师。请完成从需求到测试代码的全链路转化。
## 输入:需求文档
[粘贴需求文档]
## 输出要求
### Part 1:验收标准提取
- 使用 EARS 格式
- 标注优先级和测试类型
- 识别隐含需求
### Part 2:测试设计
- 为每条 AC 设计测试场景
- 包含正常路径、边界值、异常路径
- 标注测试数据需求
### Part 3:测试代码
- 使用 [测试框架] 框架
- 每个测试标注 AC 编号:// Validates: AC-X.Y
- Ubiquitous AC 使用 PBT
- Event-Driven AC 使用 example-based 测试
- 遵循项目测试约定
### Part 4:追溯矩阵
- 生成 AC→测试用例的映射表
- 标注覆盖状态3. 可追溯性矩阵(RTM)
3.1 什么是需求可追溯性矩阵?
需求可追溯性矩阵(Requirements Traceability Matrix, RTM)是一个将需求、验收标准、测试用例和缺陷关联起来的文档。它回答一个核心问题:每个需求是否都被充分测试了?
RTM 的四向追溯
需求 ←──────→ 验收标准 ←──────→ 测试用例 ←──────→ 缺陷
│ │ │ │
│ 前向追溯 │ 前向追溯 │ 前向追溯 │
│ (需求→测试) │ (AC→测试) │ (测试→缺陷) │
│ │ │ │
│ 后向追溯 │ 后向追溯 │ 后向追溯 │
│ (测试→需求) │ (测试→AC) │ (缺陷→测试) │
▼ ▼ ▼ ▼3.2 RTM 的结构
一个完整的 RTM 包含以下列:
| 需求 ID | 需求描述 | AC 编号 | AC 描述 | 测试用例 ID | 测试类型 | 状态 | 缺陷 ID |
|---|---|---|---|---|---|---|---|
| REQ-001 | 用户注册 | AC-1.1 | 有效注册 | TC-001 | 集成 | ✅ 通过 | — |
| REQ-001 | 用户注册 | AC-1.2 | 重复邮箱 | TC-002 | 单元 | ✅ 通过 | — |
| REQ-001 | 用户注册 | AC-1.3 | 无效邮箱 | TC-003 | 单元 | ❌ 失败 | BUG-042 |
| REQ-001 | 用户注册 | AC-1.4 | 弱密码 | TC-004 | PBT | ✅ 通过 | — |
| REQ-002 | 用户登录 | AC-2.1 | 正常登录 | TC-005 | 集成 | ✅ 通过 | — |
| REQ-002 | 用户登录 | AC-2.2 | 锁定账户 | — | — | ⚠️ 未覆盖 | — |
3.3 AI 自动生成和维护 RTM
传统 RTM 维护是一项繁琐的手动工作。AI 可以自动化以下环节:
┌──────────────────────────────────────────────────────────────┐
│ AI 驱动的 RTM 自动化 │
├──────────────────────────────────────────────────────────────┤
│ │
│ ① 初始生成 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 需求文档 │───→│ AI 解析 │───→│ RTM 初稿 │ │
│ │ 测试代码 │ │ 匹配关联 │ │ 覆盖分析 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ② 持续更新 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 需求变更 │───→│ AI 检测 │───→│ RTM 更新 │ │
│ │ 代码变更 │ │ 影响分析 │ │ 差异报告 │ │
│ │ 测试结果 │ │ 覆盖计算 │ │ 告警通知 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ③ 覆盖率报告 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ RTM 数据 │───→│ AI 分析 │───→│ 覆盖热力图│ │
│ │ 测试结果 │ │ 风险评估 │ │ 风险报告 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘工具推荐
| 工具 | 用途 | 价格 | 适用场景 |
|---|---|---|---|
| Kiro Specs | 内置需求→设计→任务追溯 | 免费(50 次/月)/ $19/月 | Spec 驱动项目 |
| TestRail | 专业 RTM 管理 + 报告 | $40/用户/月起 | 企业级追溯管理 |
| Xray for Jira | Jira 原生追溯矩阵 | $10/用户/月起 | Jira 生态团队 |
| Zephyr Scale | Jira 测试管理 + 追溯 | $1/用户/月起 | 轻量级 Jira 追溯 |
| AIO Tests | AI 驱动追溯分析 | $4.79/用户/月起 | AI 增强追溯 |
| Qase | 现代测试管理 + 追溯 | 免费(3 用户)/ $35/月起 | 敏捷团队 |
| SpiraTest | 全生命周期追溯 | $44.99/用户/月起 | 合规要求高的项目 |
操作步骤
步骤 1:定义追溯粒度
确定 RTM 的追溯粒度——是需求级别、验收标准级别还是测试步骤级别:
## 追溯粒度决策
### 小型项目(<50 个需求)
- 粒度:需求 → 测试用例
- 工具:Markdown 表格 + AI 自动更新
- 维护频率:每个 Sprint
### 中型项目(50-200 个需求)
- 粒度:验收标准 → 测试用例
- 工具:Qase / Testomat.io
- 维护频率:每次需求变更
### 大型项目(200+ 个需求)
- 粒度:验收标准 → 测试步骤
- 工具:TestRail / Xray / SpiraTest
- 维护频率:持续自动化步骤 2:使用 AI 生成初始 RTM
步骤 3:建立自动更新机制
提示词模板
模板 4:RTM 生成
基于以下需求文档和测试代码,生成需求可追溯性矩阵(RTM)。
## 需求文档
[粘贴需求文档或验收标准列表]
## 测试代码目录结构
[粘贴测试文件列表或目录树]
## 测试代码中的追溯标注
[粘贴包含 "Validates: AC-X.Y" 注释的测试代码片段]
请生成:
1. 完整的 RTM 表格(需求→AC→测试用例→状态)
2. 覆盖率分析:
- 已覆盖的 AC 数量和百分比
- 未覆盖的 AC 列表(高亮 P0 未覆盖项)
- 过度测试的 AC(测试用例数 > 5 的)
3. 风险评估:
- 高风险未覆盖需求
- 建议补充的测试类型
4. 输出格式:Markdown 表格模板 5:RTM 变更影响分析
以下需求发生了变更,请分析对现有测试的影响:
## 变更前
[粘贴原始需求/AC]
## 变更后
[粘贴修改后的需求/AC]
## 现有 RTM
[粘贴当前 RTM]
请分析:
1. 哪些现有测试需要修改?
2. 哪些测试需要删除?
3. 需要新增哪些测试?
4. 变更对覆盖率的影响
5. 更新后的 RTM4. Spec 驱动测试(Spec-Driven Testing)
4.1 Spec 驱动测试的核心理念
Spec 驱动测试是将测试深度集成到 Spec 驱动开发流程中的方法论。与传统”代码写完后补测试”不同,Spec 驱动测试从需求定义阶段就开始规划测试:
传统流程:
需求 → 设计 → 编码 → [补测试] → 发布
↑
测试是事后补充,覆盖率低
Spec 驱动流程:
需求(AC) → 设计(属性) → 任务(含测试任务) → 编码+测试 → 发布
↓ ↓ ↓
测试种子 测试属性 测试代码
↑
测试从第一步就开始规划,覆盖率高4.2 Kiro Spec 驱动测试的三阶段
Kiro 的 Spec 驱动开发将需求→测试的链路分为三个阶段:
┌─────────────────────────────────────────────────────────────┐
│ Kiro Spec 驱动测试三阶段 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 阶段 1:Requirements(需求文档) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ requirements.md │ │
│ │ │ │
│ │ ## Requirement 1: 用户注册 │ │
│ │ ### Acceptance Criteria │ │
│ │ 1.1 WHEN 用户提交有效信息, SHALL 创建账户 │ │
│ │ 1.2 WHEN 邮箱已存在, SHALL 返回 409 │ │
│ │ 1.3 WHEN 密码少于 8 字符, SHALL 返回 400 │ │
│ │ │ │
│ │ → 验收标准 = 测试用例的种子 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 阶段 2:Design(设计文档) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ design.md │ │
│ │ │ │
│ │ ## Correctness Properties │ │
│ │ Property 1: 注册幂等性 │ │
│ │ FORALL input: ValidRegistration │ │
│ │ register(input) 成功后, register(input) 返回 409 │ │
│ │ Validates: Requirement 1.1, 1.2 │ │
│ │ │ │
│ │ → 正确性属性 = PBT 测试的规格 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 阶段 3:Tasks(任务列表) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ tasks.md │ │
│ │ │ │
│ │ - [ ] 2.1 编写用户注册单元测试 │ │
│ │ - 覆盖 AC 1.1-1.3 │ │
│ │ - _Requirements: 1.1, 1.2, 1.3_ │ │
│ │ - [ ] 2.2 编写用户注册 PBT │ │
│ │ - 实现 Property 1(注册幂等性) │ │
│ │ - _Requirements: 1.1, 1.2_ │ │
│ │ │ │
│ │ → 测试任务 = 可执行的测试开发计划 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘4.3 Spec 驱动测试 vs 传统测试
| 维度 | 传统测试 | Spec 驱动测试 |
|---|---|---|
| 测试规划时机 | 编码完成后 | 需求定义时 |
| 测试依据 | 代码实现 | 验收标准和正确性属性 |
| 追溯性 | 手动维护 RTM | 内置追溯(AC→Property→Test Task) |
| PBT 支持 | 需要额外规划 | 正确性属性天然适合 PBT |
| 覆盖率度量 | 代码覆盖率 | 需求覆盖率 + 代码覆盖率 |
| 变更影响 | 手动分析 | 通过 Spec 链路自动追溯 |
| AI 生成质量 | 依赖 prompt 质量 | Spec 提供结构化上下文 |
4.4 从 Spec 到测试代码的自动生成
步骤 1:从 requirements.md 提取测试需求
// AI 从 requirements.md 的 AC 1.1 自动生成
// Validates: AC-1.1 WHEN 用户提交有效信息, SHALL 创建账户
describe('用户注册 - AC-1.1', () => {
it('should create user account with valid registration info', async () => {
// Arrange
const validInput = {
email: 'alice@example.com',
password: 'securePass123',
name: 'Alice',
};
// Act
const result = await registerUser(validInput);
// Assert
expect(result.id).toBeDefined();
expect(result.email).toBe('alice@example.com');
expect(result.name).toBe('Alice');
});
});步骤 2:从 design.md 的正确性属性生成 PBT
import { fc } from 'fast-check';
// AI 从 design.md 的 Property 1 自动生成
// Validates: Property 1 - 注册幂等性
// Validates: Requirements 1.1, 1.2
describe('Property: 注册幂等性', () => {
it('should return 409 when registering with same email twice', () => {
fc.assert(
fc.asyncProperty(
fc.record({
email: fc.emailAddress(),
password: fc.string({ minLength: 8, maxLength: 64 }),
name: fc.string({ minLength: 1, maxLength: 100 }),
}),
async (input) => {
// 第一次注册应该成功
const first = await registerUser(input);
expect(first.id).toBeDefined();
// 第二次注册应该返回 409
await expect(registerUser(input)).rejects.toThrow(/already exists/);
}
),
{ numRuns: 100 }
);
});
});步骤 3:从 tasks.md 追踪测试完成状态
# tasks.md 中的测试任务追踪
- [x] 2.1 编写用户注册单元测试 ✅
- 覆盖 AC 1.1-1.3
- _Requirements: 1.1, 1.2, 1.3_
- [x] 2.2 编写用户注册 PBT ✅ (passed)
- 实现 Property 1(注册幂等性)
- _Requirements: 1.1, 1.2_提示词模板
模板 6:Spec 驱动测试生成
基于以下 Kiro Spec 文档生成完整的测试套件:
## requirements.md(验收标准)
[粘贴相关的验收标准]
## design.md(正确性属性)
[粘贴相关的正确性属性]
## tasks.md(测试任务)
[粘贴当前要实现的测试任务]
## 源代码
[粘贴被测试的源代码]
要求:
1. 为每条 AC 生成至少一个 example-based 测试
2. 为每个 Correctness Property 生成一个 PBT
3. 每个测试标注:
- // Validates: AC-X.Y [描述]
- // Validates: Property N [描述]
- // Validates: Requirements X.Y
4. PBT 使用 [fast-check/Hypothesis] 框架
5. 生成器智能约束输入空间
6. 测试文件命名遵循项目约定
7. 生成追溯矩阵摘要5. BDD/Gherkin 自动生成
5.1 BDD 与 Gherkin 概述
行为驱动开发(Behavior-Driven Development, BDD)使用自然语言描述软件行为,Gherkin 是 BDD 的标准语法格式。AI 在 BDD 工作流中的核心价值是将非结构化的需求自动转化为结构化的 Gherkin Feature 文件。
BDD 工作流中的 AI 角色
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 需求/用户故事 │ │ AI 转化 │ │ Gherkin │
│ │ │ │ │ Feature 文件 │
│ "用户可以用 │────→│ 解析意图 │────→│ Feature: 优惠券│
│ 优惠券下单" │ │ 枚举场景 │ │ Scenario: ... │
│ │ │ 生成步骤 │ │ Given ... │
│ │ │ 识别边界 │ │ When ... │
└──────────────┘ └──────────────┘ │ Then ... │
└──────┬───────┘
│
┌──────┴───────┐
│ Step 定义 │
│ (自动化代码) │
└──────────────┘5.2 Gherkin 语法速查
# Gherkin 核心语法
Feature: 功能名称
功能描述(可选)
Background: 前置条件(所有场景共享)
Given 共享的前置条件
Scenario: 场景名称
Given 前置条件(准备状态)
And 额外的前置条件
When 触发动作
And 额外的动作
Then 预期结果
And 额外的预期结果
But 不应该发生的事情
Scenario Outline: 参数化场景
Given 前置条件 "<参数1>"
When 触发动作 "<参数2>"
Then 预期结果 "<参数3>"
Examples:
| 参数1 | 参数2 | 参数3 |
| 值1 | 值2 | 值3 |
| 值4 | 值5 | 值6 |
@tag1 @tag2
Scenario: 带标签的场景
...5.3 AI 生成 Gherkin 的工作流
工具推荐
| 工具 | 用途 | 价格 | 适用场景 |
|---|---|---|---|
| Gherkinizer | 从用户故事自动生成 Gherkin Feature 文件 | 免费(基础)/ 付费计划 | 快速生成 BDD 场景 |
| Codespell | 企业级 AI Gherkin 生成 + 质量保证 | 联系销售 | 大规模 BDD 自动化 |
| Claude Code | 通用 AI 生成 Gherkin + Step 定义 | $20/月(Pro) | 灵活的 BDD 生成 |
| Cucumber | BDD 框架(执行 Gherkin) | 免费(开源) | Gherkin 执行引擎 |
| SpecFlow | .NET BDD 框架 | 免费(开源)/ $45/月(SpecFlow+) | .NET 项目 BDD |
| Behave | Python BDD 框架 | 免费(开源) | Python 项目 BDD |
| Playwright BDD | Playwright + Gherkin 集成 | 免费(开源) | E2E BDD 测试 |
操作步骤
步骤 1:从需求生成 Feature 文件
使用 AI 将用户故事转化为 Gherkin Feature 文件:
# AI 生成的 Feature 文件示例
# 来源:用户故事 "用户可以使用优惠券下单"
Feature: 优惠券应用
作为一个电商用户
我希望能够在结算时使用优惠券
以便享受折扣优惠
Background:
Given 用户已登录
And 购物车中有商品
@happy-path @P0
Scenario: 成功应用有效优惠券
Given 用户有一张有效的优惠券 "SAVE20"
And 优惠券折扣为 20%
And 购物车总金额为 200 元
And 购物车金额满足最低消费 100 元
When 用户在结算页面输入优惠券码 "SAVE20"
Then 系统应显示折扣金额 40 元
And 应付金额应为 160 元
@error-handling @P0
Scenario: 使用过期优惠券
Given 用户有一张已过期的优惠券 "EXPIRED10"
When 用户在结算页面输入优惠券码 "EXPIRED10"
Then 系统应显示错误提示 "优惠券已过期"
And 订单金额不应变化
@boundary @P0
Scenario Outline: 最低消费门槛验证
Given 用户有一张最低消费 <门槛> 元的优惠券
And 购物车总金额为 <金额> 元
When 用户尝试应用优惠券
Then 系统应 <结果>
Examples:
| 门槛 | 金额 | 结果 |
| 100 | 99 | 显示 "未达到最低消费 ¥100" |
| 100 | 100 | 成功应用优惠券 |
| 100 | 101 | 成功应用优惠券 |
| 200 | 150 | 显示 "未达到最低消费 ¥200" |
@business-rule @P0
Scenario: 单券限制
Given 用户已应用优惠券 "SAVE20"
When 用户尝试再应用优惠券 "SAVE10"
Then 系统应显示提示 "每个订单只能使用一张优惠券"
And 原优惠券 "SAVE20" 应保持生效
@edge-case @P1
Scenario: 部分商品不参与优惠
Given 购物车中有参与优惠的商品总价 150 元
And 购物车中有不参与优惠的商品总价 50 元
And 用户有一张 10% 折扣优惠券
When 用户应用优惠券
Then 折扣应仅基于参与优惠的商品计算
And 折扣金额应为 15 元
And 应付金额应为 185 元步骤 2:生成 Step 定义代码
// AI 生成的 Step 定义(Playwright BDD 示例)
import { Given, When, Then } from '@cucumber/cucumber';
import { expect } from '@playwright/test';
// Validates: AC-1.1
Given('用户有一张有效的优惠券 {string}', async function (couponCode: string) {
this.coupon = await createTestCoupon({
code: couponCode,
status: 'active',
expiresAt: new Date(Date.now() + 86400000), // 明天过期
});
});
Given('优惠券折扣为 {int}%', async function (discount: number) {
this.coupon.discountPercent = discount;
await updateCoupon(this.coupon);
});
Given('购物车总金额为 {int} 元', async function (amount: number) {
await setCartTotal(this.userId, amount);
});
// Validates: AC-1.1
When('用户在结算页面输入优惠券码 {string}', async function (code: string) {
await this.page.goto('/checkout');
await this.page.fill('[data-testid="coupon-input"]', code);
await this.page.click('[data-testid="apply-coupon"]');
});
// Validates: AC-1.1
Then('系统应显示折扣金额 {int} 元', async function (discount: number) {
const discountText = await this.page.textContent('[data-testid="discount-amount"]');
expect(discountText).toContain(`¥${discount}`);
});
Then('应付金额应为 {int} 元', async function (total: number) {
const totalText = await this.page.textContent('[data-testid="total-amount"]');
expect(totalText).toContain(`¥${total}`);
});
// Validates: AC-1.2
Then('系统应显示错误提示 {string}', async function (message: string) {
const error = await this.page.textContent('[data-testid="coupon-error"]');
expect(error).toContain(message);
});步骤 3:集成到测试框架
// cucumber.json 配置
{
"default": {
"paths": ["features/**/*.feature"],
"require": ["step-definitions/**/*.ts"],
"format": [
"progress-bar",
"json:reports/cucumber-report.json",
"html:reports/cucumber-report.html"
],
"publishQuiet": true
}
}提示词模板
模板 7:Gherkin Feature 文件生成
你是一个 BDD 专家。请将以下需求转化为 Gherkin Feature 文件。
## 需求/用户故事
[粘贴需求文档]
## 生成要求
1. Feature 文件结构:
- Feature 描述使用"作为...我希望...以便..."格式
- 使用 Background 提取共享前置条件
- 使用 Scenario Outline + Examples 参数化相似场景
2. 场景覆盖:
- Happy Path(正常路径):至少 2 个
- Error Handling(错误处理):至少 2 个
- Boundary(边界值):至少 1 个 Scenario Outline
- Edge Case(边缘情况):至少 1 个
3. 标签规范:
- @happy-path / @error-handling / @boundary / @edge-case
- @P0 / @P1 / @P2(优先级)
- @smoke(冒烟测试场景)
- @regression(回归测试场景)
4. 步骤编写规范:
- Given:描述前置状态,使用过去时或现在时
- When:描述触发动作,使用现在时
- Then:描述预期结果,使用"应"/"应该"
- 避免在步骤中包含实现细节(如 CSS 选择器)
- 步骤要可复用(参数化)
5. 每个 Scenario 标注对应的 AC 编号模板 8:Step 定义代码生成
基于以下 Gherkin Feature 文件,生成 Step 定义代码。
## Feature 文件
[粘贴 .feature 文件内容]
## 技术栈
- BDD 框架:[Cucumber/SpecFlow/Behave]
- 测试框架:[Playwright/Cypress/Selenium]
- 语言:[TypeScript/Python/C#]
## 生成要求
1. 每个 Step 定义标注对应的 AC 编号
2. 使用 Page Object 模式(如涉及 UI)
3. 参数化步骤使用正确的类型转换
4. 包含 setup/teardown 逻辑
5. 使用 data-testid 属性定位元素(避免脆弱选择器)
6. 异步步骤使用 async/await
7. 包含合理的等待策略(避免硬编码 sleep)6. 测试覆盖率与需求覆盖率
6.1 两种覆盖率的区别
大多数团队只关注代码覆盖率(Code Coverage),但这只回答了”多少代码被测试了”。更重要的问题是”多少需求被测试了”——这就是需求覆盖率(Requirements Coverage)。
代码覆盖率 vs 需求覆盖率
代码覆盖率(Code Coverage):
┌────────────────────────────────┐
│ 源代码 │
│ ████████████░░░░░░░░ │ 80% 行覆盖
│ ████████░░░░░░░░░░░ │ 60% 分支覆盖
└────────────────────────────────┘
回答:多少代码被执行了?
局限:100% 代码覆盖 ≠ 所有需求都被验证了
需求覆盖率(Requirements Coverage):
┌────────────────────────────────┐
│ 需求/验收标准 │
│ AC-1.1 ✅ AC-1.2 ✅ AC-1.3 ❌│ 67% 需求覆盖
│ AC-2.1 ✅ AC-2.2 ⚠️ AC-2.3 ✅│ 83% 需求覆盖
└────────────────────────────────┘
回答:多少需求被验证了?
价值:直接反映业务风险6.2 需求覆盖率的计算方法
需求覆盖率 = 已覆盖的 AC 数量 / 总 AC 数量 × 100%
其中"已覆盖"的定义:
- 至少有 1 个测试用例验证该 AC
- 该测试用例当前状态为"通过"
- 测试用例标注了对应的 AC 编号(可追溯)
加权需求覆盖率(考虑优先级):
= (P0 已覆盖 × 3 + P1 已覆盖 × 2 + P2 已覆盖 × 1)
/ (P0 总数 × 3 + P1 总数 × 2 + P2 总数 × 1) × 100%6.3 需求覆盖率仪表板
┌─────────────────────────────────────────────────────────────┐
│ 需求覆盖率仪表板 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 总体覆盖率 │
│ ████████████████████░░░░░ 82% (41/50 AC) │
│ │
│ 按优先级 │
│ P0: ████████████████████████ 96% (24/25 AC) ← 关注! │
│ P1: ████████████████░░░░░░░ 72% (13/18 AC) │
│ P2: ██████████░░░░░░░░░░░░ 57% (4/7 AC) │
│ │
│ 按模块 │
│ 用户管理: ████████████████████████ 100% │
│ 订单系统: ████████████████████░░░░ 85% │
│ 支付模块: ████████████████░░░░░░░░ 70% ← 风险! │
│ 优惠券: ████████████░░░░░░░░░░░░ 55% ← 高风险! │
│ │
│ 未覆盖的 P0 需求(需立即处理) │
│ ⚠️ AC-3.5: 支付超时处理 │
│ │
│ 代码覆盖率 vs 需求覆盖率 │
│ 代码覆盖率: ████████████████████████ 88% │
│ 需求覆盖率: ████████████████████░░░░ 82% │
│ 差距分析: 6% 的代码被测试但未关联到需求 │
│ │
└─────────────────────────────────────────────────────────────┘6.4 将测试覆盖率映射回需求覆盖率
操作步骤
步骤 1:在测试代码中标注需求追溯
// 在每个测试中标注对应的 AC
describe('优惠券应用', () => {
// Validates: AC-1.1 成功应用有效优惠券
it('should apply valid coupon and calculate discount', () => { ... });
// Validates: AC-1.2 过期优惠券
it('should reject expired coupon', () => { ... });
// Validates: AC-1.4 单券限制
// Validates: Property 1 - 单券不变量
it('should enforce single coupon per order', () => { ... });
});步骤 2:使用脚本提取覆盖率映射
// scripts/requirements-coverage.ts
// 从测试文件中提取 "Validates: AC-X.Y" 注释,生成覆盖率报告
import * as fs from 'fs';
import * as path from 'path';
import { glob } from 'glob';
interface CoverageEntry {
acId: string;
testFile: string;
testName: string;
status: 'passed' | 'failed' | 'skipped';
}
async function extractCoverage(): Promise<CoverageEntry[]> {
const testFiles = await glob('**/*.test.ts', { ignore: 'node_modules/**' });
const entries: CoverageEntry[] = [];
for (const file of testFiles) {
const content = fs.readFileSync(file, 'utf-8');
const lines = content.split('\n');
for (let i = 0; i < lines.length; i++) {
const match = lines[i].match(/\/\/\s*Validates:\s*(AC-[\d.]+)/);
if (match) {
// 查找下一个 it/test 块
for (let j = i + 1; j < lines.length; j++) {
const testMatch = lines[j].match(/(?:it|test)\s*\(\s*['"`](.+?)['"`]/);
if (testMatch) {
entries.push({
acId: match[1],
testFile: file,
testName: testMatch[1],
status: 'passed', // 从测试结果 JSON 中获取实际状态
});
break;
}
}
}
}
}
return entries;
}
async function generateReport() {
const coverage = await extractCoverage();
// 从 requirements.md 提取所有 AC
const allACs = extractACsFromRequirements('requirements.md');
// 生成覆盖率报告
const covered = new Set(coverage.map(e => e.acId));
const uncovered = allACs.filter(ac => !covered.has(ac.id));
console.log(`\n📊 需求覆盖率报告`);
console.log(`总 AC 数: ${allACs.length}`);
console.log(`已覆盖: ${covered.size}`);
console.log(`未覆盖: ${uncovered.length}`);
console.log(`覆盖率: ${((covered.size / allACs.length) * 100).toFixed(1)}%`);
if (uncovered.length > 0) {
console.log(`\n⚠️ 未覆盖的验收标准:`);
uncovered.forEach(ac => {
console.log(` - ${ac.id}: ${ac.description} [${ac.priority}]`);
});
}
}
generateReport();步骤 3:集成到 CI/CD
# .github/workflows/requirements-coverage.yml
name: Requirements Coverage Check
on: [pull_request]
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm ci
- run: npx vitest run --reporter=json --outputFile=test-results.json
- run: npx tsx scripts/requirements-coverage.ts
- name: Check P0 Coverage
run: |
# 确保所有 P0 需求都被覆盖
UNCOVERED_P0=$(npx tsx scripts/check-p0-coverage.ts)
if [ -n "$UNCOVERED_P0" ]; then
echo "❌ 以下 P0 需求未被测试覆盖:"
echo "$UNCOVERED_P0"
exit 1
fi提示词模板
模板 9:需求覆盖率分析
分析以下项目的需求覆盖率:
## 验收标准列表
[粘贴所有 AC,含编号和优先级]
## 测试文件列表
[粘贴测试文件名和包含的 "Validates: AC-X.Y" 注释]
## 测试运行结果
[粘贴测试运行结果摘要]
请生成:
1. 需求覆盖率报告(总体 + 按优先级 + 按模块)
2. 未覆盖的 AC 列表(按优先级排序)
3. 过度测试的 AC(测试用例 > 5 个的)
4. 风险评估(未覆盖的 P0 需求)
5. 建议补充的测试(优先级排序)
6. 代码覆盖率 vs 需求覆盖率的差距分析7. CI/CD 集成:自动化需求→测试管线
7.1 CI/CD 中的需求→测试自动化架构
将需求到测试的管线集成到 CI/CD 中,实现持续的需求验证:
┌─────────────────────────────────────────────────────────────────────┐
│ CI/CD 中的需求→测试自动化管线 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 触发器 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ PR 提交 │ │ 需求变更 │ │ 定时触发 │ │ 手动触发 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ └──────────────┴──────────────┴──────────────┘ │
│ │ │
│ ▼ │
│ 阶段 1:需求同步 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ • 从 Jira/Spec 拉取最新需求和 AC │ │
│ │ • 检测需求变更(新增/修改/删除) │ │
│ │ • 生成需求变更报告 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 阶段 2:测试生成/更新 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ • AI 分析需求变更影响 │ │
│ │ • 自动生成新测试 / 更新现有测试 │ │
│ │ • 生成测试变更 PR(人工审查) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 阶段 3:测试执行 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ • 运行单元测试 + PBT │ │
│ │ • 运行集成测试 │ │
│ │ • 运行 E2E 测试(BDD Gherkin) │ │
│ │ • 收集测试结果 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 阶段 4:覆盖率分析 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ • 计算代码覆盖率 │ │
│ │ • 计算需求覆盖率 │ │
│ │ • 更新 RTM │ │
│ │ • 生成覆盖率报告 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 阶段 5:质量门 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ • P0 需求覆盖率 ≥ 95%? │ │
│ │ • 代码覆盖率 ≥ 80%? │ │
│ │ • 所有 P0 测试通过? │ │
│ │ • 无新增未覆盖的 P0 需求? │ │
│ │ → 通过:允许合并 │ │
│ │ → 失败:阻止合并 + 通知团队 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘7.2 GitHub Actions 完整配置示例
# .github/workflows/requirements-to-test.yml
name: Requirements-to-Test Pipeline
on:
pull_request:
paths:
- 'requirements/**'
- 'src/**'
- 'tests/**'
- '.kiro/specs/**'
schedule:
- cron: '0 6 * * 1' # 每周一早上 6 点运行完整检查
jobs:
# 阶段 1:需求变更检测
detect-changes:
runs-on: ubuntu-latest
outputs:
requirements-changed: ${{ steps.changes.outputs.requirements }}
code-changed: ${{ steps.changes.outputs.code }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
requirements:
- 'requirements/**'
- '.kiro/specs/**/requirements.md'
code:
- 'src/**'
# 阶段 2:测试执行
test:
runs-on: ubuntu-latest
needs: detect-changes
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- run: npm ci
# 运行单元测试 + PBT
- name: Run Unit Tests & PBT
run: npx vitest run --coverage --reporter=json --outputFile=test-results.json
# 运行 BDD 测试
- name: Run BDD Tests
run: npx cucumber-js --format json:reports/bdd-results.json
# 上传测试结果
- uses: actions/upload-artifact@v4
with:
name: test-results
path: |
test-results.json
reports/
coverage/
# 阶段 3:需求覆盖率分析
requirements-coverage:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- run: npm ci
- uses: actions/download-artifact@v4
with:
name: test-results
# 生成需求覆盖率报告
- name: Generate Requirements Coverage
run: npx tsx scripts/requirements-coverage.ts > coverage-report.md
# 质量门检查
- name: Quality Gate - P0 Coverage
run: |
P0_COVERAGE=$(npx tsx scripts/p0-coverage-check.ts)
echo "P0 需求覆盖率: $P0_COVERAGE%"
if [ $(echo "$P0_COVERAGE < 95" | bc) -eq 1 ]; then
echo "❌ P0 需求覆盖率低于 95%"
exit 1
fi
# PR 评论
- name: Comment PR with Coverage
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('coverage-report.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 📊 需求覆盖率报告\n\n${report}`
});
# 阶段 4:RTM 更新(仅在需求变更时)
update-rtm:
runs-on: ubuntu-latest
needs: [detect-changes, requirements-coverage]
if: needs.detect-changes.outputs.requirements-changed == 'true'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm ci
- name: Update RTM
run: npx tsx scripts/update-rtm.ts
- name: Commit RTM Update
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add docs/rtm.md
git diff --staged --quiet || git commit -m "chore: update RTM [automated]"
git push7.3 Kiro Hooks 自动化配置
Kiro 的 Hooks 机制可以在文件变更时自动触发需求→测试的管线:
# .kiro/hooks/requirements-sync.yaml
# 需求文件变更时自动检查测试覆盖
trigger: onFileEdited
pattern: ".kiro/specs/**/requirements.md"
action: askAgent
prompt: |
需求文件已更新。请执行以下操作:
1. 分析需求变更(新增/修改/删除的 AC)
2. 检查现有测试是否覆盖了变更的 AC
3. 如果有未覆盖的新 AC,生成测试骨架
4. 更新 RTM 文档
5. 报告覆盖率变化# .kiro/hooks/test-traceability.yaml
# 测试文件变更时检查追溯标注
trigger: onFileEdited
pattern: "**/*.test.ts"
action: askAgent
prompt: |
测试文件已更新。请检查:
1. 所有新增的测试是否包含 "Validates: AC-X.Y" 注释
2. 追溯标注是否指向有效的 AC 编号
3. 是否有 AC 的测试被意外删除
如果发现问题,请提醒开发者补充追溯标注。7.4 质量门配置
// scripts/quality-gate.ts
// 需求→测试管线的质量门检查
interface QualityGateConfig {
p0CoverageThreshold: number; // P0 需求覆盖率阈值
overallCoverageThreshold: number; // 总体需求覆盖率阈值
codeCoverageThreshold: number; // 代码覆盖率阈值
maxUncoveredP0: number; // 允许的最大未覆盖 P0 数量
requireTraceability: boolean; // 是否要求所有测试有追溯标注
}
const defaultConfig: QualityGateConfig = {
p0CoverageThreshold: 95,
overallCoverageThreshold: 80,
codeCoverageThreshold: 80,
maxUncoveredP0: 0,
requireTraceability: true,
};
async function checkQualityGate(config: QualityGateConfig = defaultConfig) {
const results = {
passed: true,
checks: [] as { name: string; passed: boolean; message: string }[],
};
// 检查 1:P0 需求覆盖率
const p0Coverage = await calculateP0Coverage();
results.checks.push({
name: 'P0 需求覆盖率',
passed: p0Coverage >= config.p0CoverageThreshold,
message: `${p0Coverage}% (阈值: ${config.p0CoverageThreshold}%)`,
});
// 检查 2:总体需求覆盖率
const overallCoverage = await calculateOverallCoverage();
results.checks.push({
name: '总体需求覆盖率',
passed: overallCoverage >= config.overallCoverageThreshold,
message: `${overallCoverage}% (阈值: ${config.overallCoverageThreshold}%)`,
});
// 检查 3:代码覆盖率
const codeCoverage = await getCodeCoverage();
results.checks.push({
name: '代码覆盖率',
passed: codeCoverage >= config.codeCoverageThreshold,
message: `${codeCoverage}% (阈值: ${config.codeCoverageThreshold}%)`,
});
// 检查 4:追溯标注完整性
if (config.requireTraceability) {
const untracedTests = await findUntracedTests();
results.checks.push({
name: '追溯标注完整性',
passed: untracedTests.length === 0,
message: untracedTests.length === 0
? '所有测试都有追溯标注'
: `${untracedTests.length} 个测试缺少追溯标注`,
});
}
results.passed = results.checks.every(c => c.passed);
return results;
}提示词模板
模板 10:CI/CD 管线配置生成
为以下项目生成需求→测试自动化的 CI/CD 管线配置:
## 项目信息
- CI/CD 平台:[GitHub Actions/GitLab CI/Jenkins]
- 测试框架:[Vitest/Jest/Pytest]
- BDD 框架:[Cucumber/Behave](如使用)
- 需求管理:[Kiro Specs/Jira/Markdown]
- 部署平台:[Vercel/AWS/GCP]
## 管线要求
1. PR 触发:运行测试 + 需求覆盖率检查
2. 需求变更触发:影响分析 + 测试更新建议
3. 定时触发:完整覆盖率报告
4. 质量门:
- P0 需求覆盖率 ≥ [阈值]%
- 代码覆盖率 ≥ [阈值]%
- 所有测试有追溯标注
5. 报告:PR 评论 + 仪表板更新
请生成:
1. 完整的 CI/CD 配置文件
2. 需求覆盖率计算脚本
3. 质量门检查脚本
4. RTM 自动更新脚本实战案例:电商订单系统的需求→测试全链路
案例背景
一个电商团队正在开发订单系统,使用 Kiro Spec 驱动开发。团队希望建立从需求到测试的全链路自动化管线。
案例分析
第一步:需求定义(requirements.md)
## Requirement 1: 订单创建
### Acceptance Criteria
1.1 WHEN 用户提交包含有效商品和地址的订单,
THE 系统 SHALL 创建订单并返回订单号
1.2 WHEN 订单中的商品库存不足,
THE 系统 SHALL 返回库存不足错误并标明具体商品
1.3 THE 系统 SHALL 确保订单总金额等于所有商品单价×数量之和
1.4 IF 支付网关超时,
THEN THE 系统 SHALL 将订单标记为"待支付"并在 30 分钟后自动取消
1.5 WHEN 用户应用优惠券,
THE 系统 SHALL 验证优惠券有效性并计算折扣第二步:设计文档中的正确性属性(design.md)
## Correctness Properties
Property 1: 订单金额一致性
FORALL items: NonEmptyList<OrderItem>
calculateTotal(items) == sum(items.map(i => i.price * i.quantity))
Validates: Requirement 1.3
Property 2: 库存扣减原子性
FORALL order: ValidOrder
createOrder(order) 成功 => 所有商品库存减少对应数量
createOrder(order) 失败 => 所有商品库存不变
Validates: Requirement 1.1, 1.2
Property 3: 优惠券单次使用
FORALL coupon: ValidCoupon, order1: Order, order2: Order
applyCoupon(order1, coupon) 成功后,
applyCoupon(order2, coupon) 返回"优惠券已使用"
Validates: Requirement 1.5第三步:AI 生成测试任务(tasks.md)
- [ ] 3.1 编写订单创建单元测试
- 覆盖 AC 1.1-1.5 的 example-based 测试
- _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5_
- [ ] 3.2 编写订单创建 PBT
- 实现 Property 1(订单金额一致性)
- 实现 Property 2(库存扣减原子性)
- 实现 Property 3(优惠券单次使用)
- _Requirements: 1.1, 1.2, 1.3, 1.5_
- [ ] 3.3 编写订单创建 BDD 测试
- 生成 Gherkin Feature 文件
- 实现 Step 定义
- _Requirements: 1.1, 1.2, 1.4, 1.5_第四步:AI 生成的测试代码
// tests/order/create-order.test.ts
import { describe, it, expect, beforeEach } from 'vitest';
import { createOrder, OrderInput } from '../../src/services/order';
describe('订单创建', () => {
// Validates: AC-1.1 有效订单创建
it('should create order with valid items and address', async () => {
const input: OrderInput = {
items: [
{ productId: 'P001', quantity: 2, price: 99.9 },
{ productId: 'P002', quantity: 1, price: 199.0 },
],
address: { city: '北京', street: '朝阳区xxx路', zip: '100000' },
};
const order = await createOrder(input);
expect(order.id).toBeDefined();
expect(order.status).toBe('created');
expect(order.total).toBe(398.8); // 99.9*2 + 199.0
});
// Validates: AC-1.2 库存不足
it('should return stock error when inventory insufficient', async () => {
const input: OrderInput = {
items: [{ productId: 'P003', quantity: 999, price: 10 }],
address: { city: '上海', street: 'xxx路', zip: '200000' },
};
await expect(createOrder(input)).rejects.toThrow(/库存不足/);
});
// Validates: AC-1.4 支付超时
it('should mark order as pending and auto-cancel after 30min', async () => {
// ... 测试支付超时逻辑
});
});// tests/order/create-order.property.test.ts
import { describe, it, expect } from 'vitest';
import { fc } from 'fast-check';
import { calculateTotal, OrderItem } from '../../src/services/order';
// Validates: Property 1 - 订单金额一致性
// Validates: Requirements 1.3
describe('Property: 订单金额一致性', () => {
const orderItemArb = fc.record({
productId: fc.string({ minLength: 1, maxLength: 20 }),
quantity: fc.integer({ min: 1, max: 100 }),
price: fc.double({ min: 0.01, max: 99999.99, noNaN: true }),
});
it('total should equal sum of item prices × quantities', () => {
fc.assert(
fc.property(
fc.array(orderItemArb, { minLength: 1, maxLength: 20 }),
(items: OrderItem[]) => {
const total = calculateTotal(items);
const expected = items.reduce(
(sum, item) => sum + item.price * item.quantity,
0
);
// 使用近似比较处理浮点精度
expect(Math.abs(total - expected)).toBeLessThan(0.01);
}
),
{ numRuns: 200 }
);
});
});第五步:生成的 RTM
| 需求 ID | AC 编号 | AC 描述 | 测试用例 | 测试类型 | 状态 |
|---|---|---|---|---|---|
| REQ-1 | AC-1.1 | 有效订单创建 | create-order.test.ts#1 | 单元 | ✅ |
| REQ-1 | AC-1.1 | 有效订单创建 | order.feature#Scenario1 | BDD | ✅ |
| REQ-1 | AC-1.2 | 库存不足 | create-order.test.ts#2 | 单元 | ✅ |
| REQ-1 | AC-1.2 | 库存扣减原子性 | create-order.property.test.ts#P2 | PBT | ✅ |
| REQ-1 | AC-1.3 | 金额一致性 | create-order.property.test.ts#P1 | PBT | ✅ |
| REQ-1 | AC-1.4 | 支付超时 | create-order.test.ts#3 | 单元 | ✅ |
| REQ-1 | AC-1.4 | 支付超时 | order.feature#Scenario4 | BDD | ✅ |
| REQ-1 | AC-1.5 | 优惠券应用 | create-order.test.ts#4 | 单元 | ✅ |
| REQ-1 | AC-1.5 | 优惠券单次使用 | create-order.property.test.ts#P3 | PBT | ✅ |
覆盖率:100%(5/5 AC 已覆盖)
案例总结
| 维度 | 传统方式 | Spec 驱动自动化 | 提升 |
|---|---|---|---|
| AC 提取时间 | 2-4 小时 | 10-15 分钟 | 10x |
| 测试设计时间 | 4-8 小时 | 30-60 分钟 | 8x |
| 测试代码编写 | 1-2 天 | 2-4 小时 | 4x |
| RTM 维护 | 持续手动 | 自动化 | ∞ |
| 需求覆盖率 | 60-80% | 95-100% | 显著提升 |
| 变更影响分析 | 数小时 | 数分钟 | 20x |
避坑指南
❌ 常见错误
-
只关注代码覆盖率,忽视需求覆盖率
- 问题:代码覆盖率 90% 但关键业务需求未被测试。代码覆盖率衡量的是”多少代码被执行了”,而非”多少需求被验证了”。一个函数可能被测试执行了,但测试并未验证其业务行为的正确性。
- 正确做法:同时追踪代码覆盖率和需求覆盖率,优先确保 P0 需求 100% 覆盖。在 CI/CD 中设置需求覆盖率质量门。
-
AI 生成的验收标准未经人工审查就直接使用
- 问题:AI 可能遗漏隐含的业务规则,或生成与实际需求不符的 AC。例如,AI 可能不理解”VIP 用户享受 8 折”的具体折扣计算方式。
- 正确做法:AI 生成 AC 后,必须经过产品经理或业务专家审查。将 AI 生成视为”初稿”而非”终稿”。
-
RTM 只在项目初期创建,之后不维护
- 问题:需求变更后 RTM 与实际测试脱节,变成一份过时的文档,失去追溯价值。
- 正确做法:将 RTM 更新集成到 CI/CD 管线中,每次需求或测试变更时自动更新。使用代码中的追溯标注(
// Validates: AC-X.Y)作为 RTM 的数据源。
-
BDD Feature 文件包含实现细节
- 问题:Gherkin 步骤中包含 CSS 选择器、API 路径等实现细节,导致 UI 或 API 变更时 Feature 文件需要大量修改。
- 正确做法:Feature 文件只描述业务行为,实现细节封装在 Step 定义中。例如,用”用户登录”而非”用户在 #login-form 中输入用户名”。
-
过度依赖 AI 生成测试,跳过测试设计阶段
- 问题:直接让 AI 从需求生成测试代码,跳过测试策略设计。结果是生成了大量低价值的测试,但关键的集成场景和并发场景未被覆盖。
- 正确做法:遵循”需求→AC→测试设计→测试代码”的分阶段流程,每个阶段都有人工审查点。
-
测试追溯标注不规范或缺失
- 问题:测试代码中没有标注对应的 AC 编号,导致无法自动生成 RTM,需求覆盖率无法计算。
- 正确做法:在 Steering 规则中强制要求所有测试包含
// Validates: AC-X.Y注释,并在 CI 中检查追溯标注的完整性。
-
将所有需求都用同一种测试类型覆盖
- 问题:所有 AC 都只用单元测试覆盖,忽略了某些需求更适合用 PBT、集成测试或 E2E 测试验证。
- 正确做法:根据 EARS 模式选择测试类型——Ubiquitous 用 PBT,Event-Driven 用 example-based,Unwanted 用异常路径测试。
-
需求变更后不做影响分析就修改测试
- 问题:需求变更后直接修改测试代码,没有分析变更对其他测试的影响,导致回归问题。
- 正确做法:使用 AI 进行变更影响分析,识别所有受影响的测试用例,系统化地更新测试和 RTM。
✅ 最佳实践
-
从第一天就建立追溯链路:在项目启动时就定义 AC 编号规范和测试追溯标注格式,而非事后补充。
-
使用 EARS 格式编写验收标准:结构化的 AC 格式让 AI 更容易理解和转化,也让人工审查更高效。
-
分层测试策略:不同类型的 AC 使用不同的测试方法——Ubiquitous 用 PBT 验证不变量,Event-Driven 用 example-based 验证具体场景。
-
CI/CD 中设置需求覆盖率质量门:将 P0 需求覆盖率作为 PR 合并的必要条件,防止关键需求被遗漏。
-
定期进行需求-测试健康审计:每月检查 RTM 的完整性,识别过度测试和测试不足的区域。
-
Spec 驱动开发优先:使用 Kiro 等 Spec 驱动工具,从需求定义阶段就规划测试,而非代码写完后补测试。
-
AI 生成 + 人工审查的协作模式:AI 负责初稿生成和机械性工作(AC 提取、测试骨架、RTM 更新),人工负责业务语义审查和策略决策。
-
保持 Feature 文件的业务可读性:BDD Feature 文件应该是产品经理和 QA 都能读懂的”活文档”,避免技术术语和实现细节。
相关资源与延伸阅读
- Cucumber 官方文档 — BDD 框架 Cucumber 的完整文档,包含 Gherkin 语法参考和最佳实践
- Gherkinizer — AI 驱动的 Gherkin Feature 文件生成工具,支持从用户故事自动生成 BDD 场景
- Kiro 官方文档 — Spec 驱动开发 IDE 的文档,详细介绍 Requirements→Design→Tasks 的工作流
- Qase 测试管理平台 — 现代 AI 驱动测试管理工具,支持需求追溯和 AI 测试生成
- fast-check GitHub 仓库 — TypeScript/JavaScript PBT 框架,适合从正确性属性生成属性测试
- TestRail 需求追溯指南 — 企业级测试管理工具的 RTM 最佳实践
- Xray for Jira — Jira 原生测试管理插件,支持 BDD 和需求追溯矩阵
- AIO Tests — AI 驱动的 Jira 测试管理工具,支持从需求自动生成测试用例
- Codespell AI BDD — 企业级 AI Gherkin 生成平台,专注于大规模 BDD 自动化
- Testomat.io — 现代测试管理系统,支持 BDD、自动化集成和 AI 测试分析
参考来源
- Enterprise Guide to AI-Generated Feature Files (2025 年)
- Requirements Traceability Matrix (RTM) for Effective QA (2025 年)
- Acceptance Test Generation with Large Language Models (2025 年)
- GenAI-based test case generation and execution (2025 年)
- Gherkin Test Cases: A Strategic Guide for Enterprise QA (2025 年)
- 12 Must-Have Software Testing Documents (Manual vs AI Workflows) (2025 年)
- Master Behavior Driven Development with Gherkin & AIO Tests (2025 年)
- Traceability Analysis in Test Management (2025 年)
- AWS Launches Kiro, A Specification-Driven Agentic IDE (2025 年 7 月)
- Qase vs TestRail Comparison 2026 (2026 年)
- Top Test Management Tools for QA in 2025 (2025 年)
- Is This the Future of E2E Testing? AI Automates Browser Tests from Plain English (2025 年)
📖 返回 总览与导航 | 上一节:31b-AI测试生成工作流 | 下一节:31d-AI辅助PBT