BDD 行为驱动开发:用自然语言描述需求

FreeGuideOnline 7阅读 2026-07-01

BDD 行为驱动开发:用自然语言描述需求

什么是行为驱动开发

行为驱动开发(Behavior-Driven Development,BDD)是一种敏捷软件开发实践,它将业务需求、开发设计与测试验证统一为“可执行的自然语言规范”。BDD 强调通过具体示例来描述系统行为,让技术团队和非技术干系人(产品经理、QA、业务分析师)使用同一份文档沟通,减少歧义,确保从需求到代码的可追溯性。

BDD 的核心并非测试框架,而是一种协作方法:先通过示例澄清需求,再将这些示例转化为自动化验收标准,最后驱动实现。它建立在测试驱动开发(TDD)与领域驱动设计(DDD)的理论基础之上,用“用户故事 + 场景”的结构让所有人都能看懂。

BDD 的核心要素

通用语言:Gherkin

BDD 采用结构化自然语言描述行为,最常用的语法是 Gherkin。它是一种基于行、使用关键字编写的格式,支持多种人类语言(中文、英文、日文等)。Gherkin 的核心关键字包括:

  • Feature(功能):对软件功能的简要描述,通常对应一个用户故事。
  • Scenario(场景):具体的业务规则示例,描述在特定条件下系统应如何表现。
  • Given(假设):场景的前置条件或上下文。
  • When(当):用户执行的操作或触发的事件。
  • Then(那么):预期的结果或系统应输出的信息。
  • And / But(并且 / 但是):用于连接多个 Given / When / Then 步骤。

3 个关键角色(3 Amigos)

BDD 依赖三类角色的紧密协作:

  1. 业务人员(Business):定义需求、提供示例,确保场景覆盖业务规则。
  2. 开发人员(Development):将场景转化为可执行的测试和实现代码。
  3. 测试人员(Testing):负责场景的质量,补充边界案例和异常流程。

他们定期举行“示例映射”会议,用具体示例澄清模糊需求,形成 Gherkin 场景。

可执行规约(Living Documentation)

Gherkin 文件不是静态文档,而是活的文档。它通过自动化工具(Cucumber、SpecFlow、Behat 等)与测试框架绑定,执行后直接生成测试报告。当场景通过时,文档即为最新的系统行为说明;失败时则标记出与实现不一致的地方,提示需要修复代码或调整需求。

BDD 工作流程

BDD 遵循一个简单而强大的“由外向内”开发循环:

  1. 发现(Discovery)
    产品负责人与团队一起编写用户故事,并用具体示例讨论可能的场景。强调“用示例说话”,避免抽象描述。

  2. 制定(Formulation)
    将示例转化为 Gherkin 格式的 Feature 文件。确保每个场景都有一个清晰的标题和完整的 Given-When-Then 结构。

  3. 自动化(Automation)
    开发人员基于 Gherkin 场景编写 Step Definitions(步骤定义),将自然语言映射到具体的测试代码或自动化操作方法。此时测试是失败的(红)。

  4. 实现(Implementation)
    编写应用代码让场景通过。遵循 TDD 的微观循环:写一点实现,运行场景,逐渐使所有步骤变绿。

  5. 重构与维护
    代码通过后重构优化,并确保场景仍然通过。随着需求变化,团队同步更新 Gherkin 文件和步骤定义,保持文档、测试和代码始终一致。

flowchart LR
    A[发现示例] --> B[编写Gherkin场景]
    B --> C[实现步骤定义]
    C --> D[场景失败(红)]
    D --> E[编写应用代码]
    E --> F[场景通过(绿)]
    F --> G[重构代码]
    G --> D

动手实践:一个简单的 BDD 示例

我们以实现一个“用户登录”功能为例,逐步展示 BDD 的完整过程。

1. 编写 Feature 文件

文件 login.feature 使用中文描述:

# language: zh-CN
功能: 用户登录
  作为注册用户
  我想要使用邮箱和密码登录
  以便访问我的个人中心

  场景: 使用有效凭据成功登录
    假设 我未登录状态
     我使用邮箱 "[email protected]" 和密码 "correct123" 进行登录
    那么 我应被重定向到个人中心页面
    而且 页面应显示 "欢迎回来,Alice"

  场景: 使用错误密码登录失败
    假设 我未登录状态
     我使用邮箱 "[email protected]" 和密码 "wrongpass" 进行登录
    那么 我应停留在登录页面
    而且 页面应显示错误提示 "邮箱或密码不正确"

2. 自动化步骤定义

用 Cucumber.js(JavaScript 版)为例编写步骤定义:

const { Given, When, Then } = require('@cucumber/cucumber');
const assert = require('assert');

let currentPage, loginPage, userCredentials;

Given('我未登录状态', function () {
  loginPage = new LoginPage();
  loginPage.visit();
});

When('我使用邮箱 {string} 和密码 {string} 进行登录', function (email, password) {
  userCredentials = { email, password };
  currentPage = loginPage.submitLogin(email, password);
});

Then('我应被重定向到个人中心页面', function () {
  assert.strictEqual(currentPage.url(), '/profile');
});

Then('页面应显示 {string}', function (expectedMessage) {
  const actualMessage = currentPage.getWelcomeMessage();
  assert.strictEqual(actualMessage, expectedMessage);
});

Then('我应停留在登录页面', function () {
  assert.strictEqual(currentPage.url(), '/login');
});

3. 运行并观察结果

第一次运行测试,所有步骤定义未实现时报告为“未定义”或失败。随着逐步编写 LoginPage 类和对应的路由逻辑,场景将从失败转为通过。最终所有场景变绿,意味登录功能符合需求。

BDD 与 TDD 的关系

维度 TDD(测试驱动开发) BDD(行为驱动开发)
关注点 代码内部设计,单元测试 系统外部行为,端到端场景
语言 技术语言(assert, expect) 自然语言,业务可读
编写主体 开发人员 业务、开发、测试共同编写
文档价值 低,测试即文档(但对非技术人员不友好) 高,Gherkin 文件即活的文档
典型框架 JUnit, NUnit, PHPUnit Cucumber, SpecFlow, Behat, JBehave

BDD 并不替代 TDD,而是建立在 TDD 之上。TDD 驱动内部设计,BDD 驱动外部行为。在实现步骤定义时,开发人员仍可继续使用 TDD 编写单元测试。

BDD 的典型应用场景与优势

适用场景

  • 需求变更频繁、需要持续与业务对齐的项目。
  • 跨职能团队,非技术人员需要参与验收标准制定。
  • 微服务或 API 开发,BDD 可清晰描述接口合约。
  • 遗留系统改造,可先为现有行为补充 BDD 文档再安全重构。

核心优势

  • 消除歧义:用具体示例取代抽象描述,所有角色对需求理解一致。
  • 活文档:文档与测试执行同步更新,无文档过期问题。
  • 快速反馈:场景失败立即指出哪个业务规则被破坏。
  • 回归保护网:积累的场景成为可靠的自动化验收套件。
  • 促进协作:3 Amigos 会议让团队对需求有共同所有权。

常见误区与最佳实践

误区1:把 Gherkin 当作测试脚本编写工具
BDD 场景应该描述业务意图,而不是 UI 操作细节。避免“点击 ID 为 xxx 的按钮”这类脆弱的步骤,应表达为“提交登录表单”。保持场景技术无关。

误区2:场景过于冗长或包含多个 Given-When-Then
每个场景应当只验证一条行为规则。如果一个场景包含很多分支或循环,应拆分为独立的场景或用场景大纲(Scenario Outline)进行参数化。

误区3:忽略非功能性场景
认证、授权、性能、安全等非功能需求也可以用场景描述,例如:“当用户在 3 秒内未收到响应,那么系统应显示超时提示”。

最佳实践总结:

  • 使用业务语言,避免实现细节。
  • 场景标题使用“主语 + 动词”的形式,读者一眼看出验证的内容。
  • 异步操作或后台任务,增加显式等待步骤(当 我等待订单状态变为“已确认”)。
  • 定期举行“示例映射”会议,保持 Feature 文件整洁并贴合当下需求。
  • 将 Gherkin 文件放在版本控制系统中,与实践代码一同提交。

工具生态速览

工具 语言/平台 特点
Cucumber Ruby, JVM, JS, C++ 等 最流行的 BDD 框架,多语言支持
SpecFlow .NET 与 Visual Studio 深度集成,支持 Azure DevOps
Behat PHP 与 Symfony 等框架结合紧密
JBehave Java 纯 Java 实现,Gherkin 语法稍早版本
behave Python 轻量级,适合 Python 生态
Serenity BDD Java 提供丰富的活文档和测试聚合报告

选择工具时优先考虑团队技术栈,确保所有角色都能方便参与 Gherkin 文件的阅读与编写。

结语

行为驱动开发不仅是一种技术实践,更是一种协作文化。它通过将需求转化为可执行的自然语言,让软件交付团队能够持续聚焦于业务价值,而不是技术实现细节。从今天起,下次拿到用户故事时,不妨邀请业务伙伴一起写下第一个 Gherkin 场景——你会看到不同的改变。