---
source: ../../../../skills/atdd-assistant/acceptance-criteria-guide.md
source_version: 1.0.0
translation_version: 1.0.0
last_synced: 2026-02-05
status: current
---

# 验收标准撰写指南

**版本**: 1.0.0
**最后更新**: 2026-01-19

---

## 概述

验收标准（AC）定义用户故事被视为完成必须满足的条件。良好撰写的 AC 确保共同理解并启用自动化测试。

---

## 用户故事的 INVEST 准则

撰写验收标准前，确保用户故事遵循 INVEST：

| 原则 | 描述 | 要问的问题 |
|------|------|----------|
| **I**ndependent 独立 | 可以不依赖其他故事开发 | 「这需要先完成另一个故事吗？」 |
| **N**egotiable 可协商 | 细节可以讨论，非合约 | 「范围有弹性吗？」 |
| **V**aluable 有价值 | 传递价值给用户或企业 | 「为什么这很重要？」 |
| **E**stimable 可估算 | 团队可以估算 | 「我们理解需要什么吗？」 |
| **S**mall 小 | 小到可以在一个 Sprint 内完成 | 「我们可以在 < 1 周内完成吗？」 |
| **T**estable 可测试 | 可以通过测试验证 | 「我们怎么知道它完成了？」 |

---

## 验收标准格式

### Given-When-Then（推荐）

```markdown
### AC-1: [标准名称]
**Given** [前置条件 / 初始情境]
**And** [额外前置条件]
**When** [动作 / 事件]
**And** [额外动作]
**Then** [预期结果]
**And** [额外预期结果]
**But** [预期结果的例外]
```

### 示例

```markdown
### AC-1: 使用有效凭证成功登录
**Given** 我在登录页面
**And** 我有一个已注册账号
**When** 我输入我的电子邮件 "user@example.com"
**And** 我输入我的密码 "correctpassword"
**And** 我点击登录按钮
**Then** 我应该被重新导向到仪表板
**And** 我应该看到带有我名字的欢迎消息
```

---

## 完整用户故事模板

```markdown
## 用户故事: [US-XXX] [标题]

**作为** [角色/人物]
**我想要** [功能/能力]
**以便** [好处/价值]

---

## 验收标准

### AC-1: [Happy path - 主要成功情境]
**Given** [前置条件]
**When** [动作]
**Then** [预期结果]

### AC-2: [替代路径]
**Given** [不同前置条件]
**When** [动作]
**Then** [不同预期结果]

### AC-3: [错误处理]
**Given** [前置条件]
**When** [无效动作]
**Then** [错误处理 / 恢复]

### AC-4: [边界案例]
**Given** [边界条件]
**When** [动作]
**Then** [适当行为]

---

## 范围外
- [明确不包含的功能]
- [延后至未来的增强]
- [未涵盖的变体]

---

## 技术备注
- [实现限制]
- [依赖]
- [性能需求]
- [安全考量]

---

## 开放问题
- [ ] [需要澄清的问题]
- [ ] [需要验证的假设]

---

## 元数据
- **优先级**: [高/中/低]
- **估算**: [故事点数]
- **Sprint**: [Sprint 编号]
- **相关规格**: [SPEC-XXX 如适用]
```

---

## 撰写良好的验收标准

### DO's 和 DON'Ts

| 应该做 | 不应该做 |
|--------|---------|
| 从用户角度撰写 | 从系统角度撰写 |
| 使用商业语言 | 使用技术术语 |
| 具体且明确 | 模糊或抽象 |
| 包含可衡量的结果 | 使用主观用语 |
| 保持标准独立 | 建立相互依赖 |
| 涵盖 happy path 和边界案例 | 只涵盖 happy path |

### 好与坏的示例

```markdown
# ❌ 坏：模糊且不可测试
AC-1: 用户可以轻松重设密码
AC-2: 系统快速发送电子邮件
AC-3: 体验对用户友善

# ✅ 好：具体且可测试
AC-1: 密码重设请求
Given 我在登录页面
And 我有一个电子邮件为 "user@example.com" 的注册账号
When 我点击「忘记密码」
And 我输入我的电子邮件 "user@example.com"
Then 我应该看到「重设链接已发送至您的电子邮件」
And 我应该在 5 分钟内收到电子邮件
And 电子邮件应该包含 24 小时有效的重设链接

# ❌ 坏：技术术语
AC-1: POST /api/auth/reset 返回 202
AC-2: Redis 队列在 SLA 内处理
AC-3: SendGrid webhook 已确认

# ✅ 好：商业语言
AC-1: 重设电子邮件送达
Given 我已请求密码重设
When 系统处理我的请求
Then 我应该在 5 分钟内收到电子邮件
And 电子邮件应该来自 "noreply@example.com"
```

---

## 验收标准类别

### 1. Happy Path

主要成功情境 - 一切正常运作时会发生什么。

```markdown
### AC-1: 成功结账
Given 我的购物车有商品
And 我有有效的付款方式
When 我完成结账流程
Then 我的订单应该被确认
And 我应该收到确认电子邮件
```

### 2. 错误处理

当事情出错时会发生什么。

```markdown
### AC-2: 付款被拒绝
Given 我的购物车有商品
When 我尝试使用无效的卡片结账
Then 我应该看到「付款被拒绝」
And 我的购物车仍应该包含我的商品
And 不应该创建订单
```

### 3. 边界案例

边界条件和不寻常的情境。

```markdown
### AC-3: 购物车商品达到上限
Given 我的购物车有 100 件商品（允许的最大数量）
When 我尝试添加另一件商品
Then 我应该看到「购物车已满」
And 该商品不应该被添加
```

### 4. 授权

谁可以做什么。

```markdown
### AC-4: 仅限管理员访问
Given 我以普通用户身份登录
When 我尝试访问管理面板
Then 我应该看到「访问被拒绝」
And 我应该被重新导向到首页
```

### 5. 验证

数据和输入验证。

```markdown
### AC-5: 电子邮件格式验证
Given 我在注册表单上
When 我输入无效的电子邮件格式 "not-an-email"
Then 我应该看到「请输入有效的电子邮件地址」
And 表单不应该被提交
```

### 6. 性能（如适用）

非功能性需求。

```markdown
### AC-6: 搜索响应时间
Given 我在搜索页面
When 我搜索「笔记本电脑」
Then 结果应该在 2 秒内显示
And 应该显示至少 10 个结果
```

---

## 验收标准检查清单

完成 AC 前，验证：

```
清晰度
□ 新团队成员能理解吗？
□ 没有技术术语吗？
□ 足够具体可以实现吗？

可测试性
□ 可以自动化吗？
□ 结果可衡量吗？
□ 有明确的通过/失败标准吗？

完整性
□ Happy path 涵盖了吗？
□ 错误情境涵盖了吗？
□ 边界案例考虑了吗？
□ 安全影响处理了吗？

独立性
□ 可以独立测试吗？
□ 没有依赖其他 AC 吗？
□ 没有假设测试顺序吗？

商业价值
□ 传递用户价值吗？
□ PO 能解释为什么重要吗？
□ 与商业目标一致吗？
```

---

## AC 反模式

| 反模式 | 示例 | 问题 | 修复 |
|--------|------|------|------|
| **模糊** | 「系统应该快」 | 不可衡量 | 「响应时间 < 2 秒」 |
| **技术性** | 「API 返回 200 OK」 | 商业无法验证 | 「用户看到成功消息」 |
| **复合** | 「用户可以创建、编辑和删除」 | 太多行为 | 拆分为独立 AC |
| **缺少 Given** | 「当我点击提交，订单创建」 | 没有情境 | 添加 Given 子句 |
| **缺少 Then** | 「假设我已登录，当我点击登出」 | 没有验证 | 添加 Then 子句 |
| **相依** | 「假设 AC-1 通过...」 | 不独立 | 自包含设置 |

---

## 各功能类型示例

### 用户认证

```markdown
## 用户故事: 用户登录

**作为** 注册用户
**我想要** 登录我的账号
**以便** 我可以访问我的个性化内容

### AC-1: 成功登录
Given 我在登录页面
And 我有一个电子邮件为 "user@example.com" 的注册账号
When 我输入我的电子邮件 "user@example.com"
And 我输入我正确的密码
And 我点击登录按钮
Then 我应该被重新导向到我的仪表板
And 我应该看到「欢迎回来，[用户名]」

### AC-2: 密码错误登录失败
Given 我在登录页面
When 我输入我的电子邮件 "user@example.com"
And 我输入错误的密码
And 我点击登录按钮
Then 我应该看到「电子邮件或密码无效」
And 我应该停留在登录页面
And 密码栏位应该被清空

### AC-3: 账号锁定
Given 我已失败登录 3 次
When 我尝试再次登录
Then 我应该看到「账号暂时锁定」
And 我应该可以选择密码重设
And 我应该在 15 分钟内无法登录
```

### 电子商务结账

```markdown
## 用户故事: 应用折扣码

**作为** 客户
**我想要** 在我的订单应用折扣码
**以便** 我可以在购买时省钱

### AC-1: 有效的百分比折扣
Given 我的购物车商品总计 $100
When 我应用折扣码 "SAVE10"
Then 我的总计应该减少到 $90
And 我应该看到「已应用 10% 折扣」

### AC-2: 有效的固定金额折扣
Given 我的购物车商品总计 $100
When 我应用折扣码 "FLAT5"
Then 我的总计应该减少到 $95
And 我应该看到「已应用 $5 折扣」

### AC-3: 过期的折扣码
Given 我的购物车有商品
When 我应用折扣码 "EXPIRED2023"
Then 我应该看到「此折扣码已过期」
And 我的总计应该保持不变

### AC-4: 最低购买要求
Given 我的购物车总计 $30
When 我应用折扣码 "MIN50"（需要最低 $50）
Then 我应该看到「需要最低购买 $50」
And 我的总计应该保持不变

### AC-5: 每笔订单一个折扣码
Given 我已应用折扣码 "SAVE10"
When 我尝试应用另一个折扣码 "SAVE20"
Then 我应该看到「每笔订单只能使用一个折扣码」
And 我原本的折扣应该保留
```

---

## 将 AC 对应到测试

### 从 AC 到 Gherkin

```markdown
### AC-1: 成功的密码重设
**Given** 我有一个注册账号
**When** 我请求密码重设
**And** 我点击电子邮件中的链接
**And** 我输入新的有效密码
**Then** 我的密码应该被更改
**And** 我应该能用新密码登录
```

变成：

```gherkin
@AC-1
Scenario: 成功的密码重设
  Given 我有一个电子邮件为 "user@example.com" 的注册账号
  When 我为 "user@example.com" 请求密码重设
  And 我点击电子邮件中的重设链接
  And 我输入新密码 "NewSecureP@ss123"
  And 我确认新密码
  Then 我应该看到「密码已成功更改」
  And 我应该能用 "NewSecureP@ss123" 登录
```

### 从 AC 到 FitNesse

```
!|Password Reset|
|email|action|result|
|user@example.com|request reset|link sent|
|user@example.com|click expired link|error: expired|
|user@example.com|click valid link|reset form shown|
|user@example.com|submit new password|password changed|
```

---

## 相关资源

- [ATDD 工作流程指南](./atdd-workflow.md)
- [ATDD 核心标准](../../../../core/acceptance-test-driven-development.md)
- [Gherkin 指南](../bdd-assistant/gherkin-guide.md)
- [需求助手](../requirement-assistant/SKILL.md)
