---
source: ../../../../skills/bdd-assistant/bdd-workflow.md
source_version: 1.0.0
translation_version: 1.0.0
last_synced: 2026-02-05
status: current
---

# BDD 工作流程指南

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

---

## 探索-制定-自动化循环

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                     BDD 探索-制定-自动化                                      │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│      ┌───────────┐       ┌─────────────┐       ┌────────────┐              │
│      │ 🔍 探索   │─────▶│📝 制定       │─────▶│⚙️ 自动化    │             │
│      └───────────┘       └─────────────┘       └────────────┘              │
│           ▲                                          │                      │
│           │                                          │                      │
│           └──────────────────────────────────────────┘                      │
│                     （发现新行为）                                           │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
```

---

## 阶段 1：探索

### 目的

协作探索需求并识别具体示例。

### 时间

30-60 分钟

### 参与者

- 产品负责人 / 商业分析师
- 开发人员
- QA / 测试人员

### 活动

1. **故事介绍** (5 分钟)
   - PO 说明用户故事
   - 解释商业价值和背景

2. **澄清问题** (10 分钟)
   - 团队提问
   - 识别假设

3. **Example Mapping** (20 分钟)
   ```
   🟡 [用户故事]
        │
        ├─ 🔵 规则 1
        │      ├─ 🟢 示例 1.1
        │      └─ 🟢 示例 1.2
        │
        ├─ 🔵 规则 2
        │      └─ 🟢 示例 2.1
        │
        └─ 🔴 问题: 需要澄清
   ```

4. **边界案例识别** (10 分钟)
   - 可能出什么错？
   - 边界条件
   - 错误情境

5. **总结** (5 分钟)
   - 总结示例
   - 记录开放问题
   - 安排后续步骤

### 输出

- 具体示例清单
- 已识别的商业规则
- 待追踪的问题
- 粗略的可行性估算

### 检查清单

```
□ 利益相关方出席（商业、Dev、QA）
□ 用户故事已讨论并理解
□ 具体示例已收集
□ 边界案例已识别
□ 所有澄清问题已回答或记录
□ 范围已达成共识
```

---

## 阶段 2：制定

### 目的

将探索的示例转换为可执行的 Gherkin 场景。

### 时间

15-30 分钟

### 参与者

- 开发人员
- QA / 测试人员
- （可选）产品负责人审查

### 活动

1. **示例审查** (5 分钟)
   - 审查探索的示例
   - 确认理解

2. **场景撰写** (15 分钟)
   - 将每个示例转换为 Gherkin
   - 使用声明式风格
   - 应用通用语言

3. **审查与精炼** (10 分钟)
   - 团队审查场景
   - 检查声明式风格
   - 确保商业可读性

### Gherkin 风格指南

**应该：**
```gherkin
# 声明式 - 描述 WHAT，不是 HOW
Scenario: 使用有效凭证成功登录
  Given 我是注册用户
  When 我使用有效凭证登录
  Then 我应该看到我的仪表板
```

**不应该：**
```gherkin
# 命令式 - 描述 HOW
Scenario: 登录
  Given 我导航到 "/login"
  And 我点击 "#email" 字段
  And 我输入 "user@example.com"
  And 我点击 "#password" 字段
  And 我输入 "password123"
  And 我点击 "#submit" 按钮
  Then 我应该看到文字 "Dashboard"
```

### 场景结构

```gherkin
Feature: [功能名称]
  As a [角色]
  I want [功能]
  So that [好处]

  Background:
    Given [共同前置条件]

  Scenario: [描述性名称]
    Given [初始情境]
    And [额外情境]
    When [动作]
    Then [预期结果]
    And [额外结果]
```

### 输出

- 含 Gherkin 场景的 Feature 文件
- Tag 组织（@critical、@smoke 等）
- 准备自动化

### 检查清单

```
□ 场景使用正确的 Gherkin 语法
□ 场景是声明式的（WHAT，不是 HOW）
□ 使用商业语言（无技术术语）
□ 每个场景独立
□ 场景最多 5-10 个步骤
□ 场景已由团队审查
□ Feature 文件已提交到仓库
```

---

## 阶段 3：自动化

### 目的

实现步骤定义和功能代码使场景通过。

### 时间

可变（取决于功能复杂度）

### 参与者

- 开发人员
- QA / 测试人员（复杂的步骤定义）

### 活动

1. **执行场景**（初始 RED）
   - 所有场景应该失败
   - 确认场景可执行
   - 识别缺少的步骤定义

2. **撰写步骤定义**
   - 实现每个步骤
   - 使其可重用
   - 使用参数化

3. **实现功能代码**（使用 TDD）
   ```
   对于每个失败的场景：
   │
   ├─▶ 识别需要的组件
   │
   └─▶ 对于每个组件的 TDD 循环：
        🔴 撰写失败的单元测试
        🟢 实现最小代码
        🔵 重构
        │
        └─▶ 执行 BDD 场景（还在失败？）
             ├─ 是 → 继续 TDD
             └─ 否 → 移到下一个场景
   ```

4. **重构**
   - 清理代码
   - 移除重复
   - 改善命名

### 步骤定义示例

```typescript
// TypeScript/Cucumber.js 示例
import { Given, When, Then } from '@cucumber/cucumber';
import { expect } from 'chai';

Given('我是注册用户', async function () {
  this.user = await createTestUser();
});

When('我使用有效凭证登录', async function () {
  await this.loginPage.login(this.user.email, this.user.password);
});

Then('我应该看到我的仪表板', async function () {
  expect(await this.dashboardPage.isVisible()).to.be.true;
});
```

### BDD + TDD 整合

```
┌─────────────────────────────────────────────────────────────────┐
│                    BDD + TDD 整合                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   BDD 层（功能层级）                                             │
│   ┌─────────────────────────────────────────────────────┐       │
│   │  Scenario: 使用折扣结账                              │      │
│   │    Given 购物车商品总计 $100                        │      │
│   │    When 我应用折扣码 "SAVE20"                       │      │
│   │    Then 我的总计应该是 $80                          │      │
│   └─────────────────────────────────────────────────────┘       │
│                          │                                      │
│                          ▼                                      │
│   TDD 层（单元层级）                                             │
│   ┌─────────────────────────────────────────────────────┐       │
│   │  test_cart_calculates_total()                        │      │
│   │  test_discount_code_validates()                      │      │
│   │  test_discount_applies_percentage()                  │      │
│   │  test_invalid_code_rejected()                        │      │
│   └─────────────────────────────────────────────────────┘       │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

### 输出

- 运作中的步骤定义
- 通过的场景
- 实现的单元测试
- 重构、整洁的代码

### 检查清单

```
□ 所有步骤已创建步骤定义
□ 步骤定义可重用
□ 场景初始失败（RED）
□ TDD 用于单元实现
□ 所有场景现在通过（GREEN）
□ 代码重构且整洁
□ 活文档已生成
```

---

## 完整工作流程示例

### 用户故事

> 作为客户，我想要在购物车应用折扣码，以便在购买时省钱。

### 探索会议

**Example Mapping 结果：**
```
🟡 用户故事: 应用折扣码

🔵 规则 1: 有效码应用折扣
   🟢 示例: 码 "SAVE10" 给 10% 折扣
   🟢 示例: 码 "FLAT5" 给 $5 折扣

🔵 规则 2: 无效码显示错误
   🟢 示例: 过期码显示「码已过期」
   🟢 示例: 不存在的码显示「无效码」

🔵 规则 3: 某些码有最低要求
   🟢 示例: "MIN50" 需要最低 $50 购买

🔴 问题: 码可以组合吗？
   → 答案: 不行，每笔订单一个码
```

### 制定结果

```gherkin
Feature: 折扣码应用
  As a 客户
  I want 在购物车应用折扣码
  So that 我可以在购买时省钱

  Background:
    Given 我的购物车有商品

  Scenario: 应用百分比折扣码
    Given 我的购物车总计 $100
    When 我应用折扣码 "SAVE10"
    Then 我的总计应该是 $90
    And 我应该看到「已应用 10% 折扣」

  Scenario: 应用固定金额折扣码
    Given 我的购物车总计 $100
    When 我应用折扣码 "FLAT5"
    Then 我的总计应该是 $95
    And 我应该看到「已应用 $5 折扣」

  Scenario: 拒绝过期折扣码
    When 我应用折扣码 "EXPIRED2023"
    Then 我应该看到错误「此码已过期」
    And 我的总计应该保持不变

  Scenario: 拒绝低于最低购买的码
    Given 我的购物车总计 $30
    When 我应用折扣码 "MIN50"
    Then 我应该看到错误「需要最低购买 $50」
    And 我的总计应该保持不变
```

### 自动化结果

```typescript
// 步骤定义
Given('我的购物车总计 ${int}', async function (total) {
  await this.cart.setTotal(total);
});

When('我应用折扣码 {string}', async function (code) {
  this.result = await this.cart.applyDiscount(code);
});

Then('我的总计应该是 ${int}', async function (expected) {
  expect(await this.cart.getTotal()).to.equal(expected);
});

Then('我应该看到错误 {string}', async function (message) {
  expect(this.result.error).to.equal(message);
});
```

---

## 相关资源

- [Gherkin 快速参考](./gherkin-guide.md)
- [BDD 核心标准](../../../../core/behavior-driven-development.md)
- [TDD 工作流程](../tdd-assistant/tdd-workflow.md)
