name: bdd-principles user-invocable: false description: BDD核心概念、哲学和三友实践
BDD 原则
掌握行为驱动开发的基础原则和哲学。
什么是BDD?
行为驱动开发(BDD)是一种协作软件开发方法,它:
- 弥合业务团队和技术团队之间的差距
- 使用具体示例描述系统行为
- 创建活文档作为测试
- 专注于交付业务价值
- 通过对话促进共享理解
核心哲学
发现 > 开发 > 交付
发现:协作理解需求
- 举行三友会议
- 用示例探索
- 挑战假设
- 建立共享理解
开发:以示例为指导实现
- 使用示例作为规范
- 自动化示例作为测试
- 遵循由外而内的TDD
交付:验证真实行为
- 可执行规范提供信心
- 活文档保持最新
- 回归问题被早期捕获
三友实践
一种三种视角协作探索和定义功能的实践:
1. 业务视角(产品负责人/业务分析师)
- 我们解决什么问题?
- 它提供什么价值?
- 业务规则是什么?
2. 开发视角(开发者)
- 我们如何构建这个?
- 技术约束是什么?
- 边缘情况是什么?
3. 测试视角(测试员/QA)
- 可能会出什么错?
- 我们遗漏了什么?
- 如何验证它工作?
示例三友会议
功能:密码重置
业务:“忘记密码的用户需要通过电子邮件重置密码。”
开发者:“我们需要生成带过期时间的安全令牌。令牌应有效多久?”
测试员:“如果他们请求多个重置邮件怎么办?旧令牌还能用吗?”
业务:“令牌应有效1小时。多次请求应使旧令牌无效。”
开发者:“我们是否应限制重置请求以防止滥用?”
测试员:“如果电子邮件地址不在我们系统中怎么办?”
业务:“出于安全考虑,无论电子邮件是否存在,都显示相同的成功消息。”
结果:成为场景的具体示例:
Scenario: Request password reset with valid email
Given a user account exists for "user@example.com"
When I request a password reset for "user@example.com"
Then I should receive a reset email
And the reset link should be valid for 1 hour
Scenario: Request password reset with non-existent email
When I request a password reset for "nonexistent@example.com"
Then I should see a success message
But no email should be sent
Scenario: Multiple password reset requests
Given I have requested a password reset
When I request another password reset
Then the previous reset link should be invalidated
And I should receive a new reset email
活文档
BDD场景作为:
- 可执行规范:验证行为的自动化测试
- 文档:系统如何工作的最新描述
- 共同语言:业务和技术团队之间的共享词汇
- 回归套件:更改时的安全网
示例:活文档
Feature: Promotional Discount Application
To attract customers and increase sales
As a marketing manager
I want to offer promotional discounts
Rule: Percentage discounts apply to order subtotal
Example: 20% off for orders over $100
Given I have a $150 order
When I apply a "20% off" promotion
Then my discount should be $30
And my order total should be $120
Rule: Minimum purchase amount must be met
Example: Promotion requires $50 minimum
Given I have a $40 order
When I try to apply a "$50 minimum" promotion
Then the promotion should not apply
And I should see "Minimum purchase not met"
Rule: Only one promotion per order
Example: Cannot stack multiple promotions
Given I have a $100 order
And I have applied "10% off"
When I try to apply "Free shipping"
Then I should see "One promotion per order"
And only "10% off" should be applied
通用语言
开发和共享词汇:
❌ 技术术语:
"当用户提交表单时,我们验证输入,
用bcrypt哈希密码,将记录插入用户表,
并返回201响应。"
✅ 通用语言:
"当客户注册时,我们验证他们的信息,
创建他们的账户,并发送欢迎电子邮件。"
构建通用语言
通过对话发现术语:
- 你怎么称呼这个?
- X和Y有什么区别?
- 这个状态何时改变?
在场景中记录术语:
# 使用"会员"而非"用户"(业务术语)
Given I am a Gold Member
# 使用"下单"而非"提交订单"(领域术语)
When I place an order
# 使用"待处理"而非"进行中"(系统状态)
Then the order should be Pending
维护词汇表:
会员:有订阅的客户
访客:没有订阅的客户
订单:准备购买的商品集合
购物车:正在考虑的商品临时集合
示例映射
一种用示例探索功能的研讨会技术:
四种颜色
黄卡:用户故事/功能 蓝卡:规则(验收标准) 绿卡:示例(场景) 红卡:问题(不确定性)
示例映射会话
故事:用户注册
规则(蓝卡):
- 电子邮件必须唯一
- 密码必须强壮
- 年龄必须18岁以上
示例(绿卡):
- 用有效详细信息注册 → 成功
- 用现有电子邮件注册 → 错误
- 用弱密码注册 → 错误
- 18岁以下注册 → 错误
问题(红卡):
- 我们验证电子邮件地址吗?
- 什么定义"强壮"密码?
- 未成年人需要父母同意吗?
示例规范
使用具体示例驱动开发:
模糊需求
“用户应能搜索产品。”
示例规范
Scenario: Search by product name
Given products "Laptop", "Mouse", "Keyboard" exist
When I search for "lap"
Then I should see "Laptop" in results
But I should not see "Mouse" or "Keyboard"
Scenario: Search with no results
Given products "Laptop", "Mouse" exist
When I search for "phone"
Then I should see "No results found"
Scenario: Search is case-insensitive
Given a product "Laptop" exists
When I search for "LAPTOP"
Then I should see "Laptop" in results
由外而内开发
从外部(用户面对行为)开始,向内工作:
- 编写失败场景(验收测试)
- 编写失败单元测试(针对当前层)
- 编写最小代码使单元测试通过
- 重构
- 重复直到场景通过
场景(验收) ─┐
├─> 控制器测试 ─┐
│ ├─> 服务测试 ─┐
│ │ ├─> 代码
│ │ │
│ ├─ 服务 │
│ │ │
├─ 控制器 │ │
│ │ │
场景通过 ───────┴───────────────┴─────────────┘
BDD vs TDD
TDD(测试驱动开发):
- 开发者为中心
- 测试实现
- 红-绿-重构循环
- 单元测试指导设计
BDD(行为驱动开发):
- 业务为中心
- 测试行为
- 对话-规范-自动化
- 场景指导开发
它们互补:
- BDD:我们应该构建什么?(由外而内)
- TDD:我们如何构建它?(由内而外)
关键原则
- 协作至关重要 - BDD需要业务、开发和测试的积极参与
- 示例澄清需求 - 具体示例揭示歧义和边缘情况
- 自动化重要事项 - 并非所有都需要自动化,专注于高价值场景
- 思考行为而非测试 - 描述系统做什么,而非如何测试
- 迭代和精炼 - 随着理解加深,场景演变
- 保持场景可维护 - 编写清晰、集中的易于更新的场景
常见误解
❌ “BDD只是用Cucumber测试” ✅ BDD是一种协作实践;工具只是使能者
❌ “BDD意味着在代码前写测试” ✅ BDD意味着通过示例发现需求后再实现
❌ “BDD场景应测试一切” ✅ BDD场景应记录关键行为;用单元测试处理细节
❌ “只有测试员写场景” ✅ 业务、开发者和测试员协作场景
❌ “BDD减慢开发” ✅ BDD通过首次构建正确的东西减少返工
BDD的好处
- 减少返工:从一开始构建正确的东西
- 更好协作:跨角色共享理解
- 活文档:始终最新的规范
- 更快入职:新团队成员从场景学习
- 回归安全:自动化场景捕获破坏性更改
- 业务信心:利益相关者看到价值交付
记住:BDD本质上是关于沟通和协作。目标是确保每个人都有共享理解需要构建什么,从而构建交付真正价值的软件。