本文目录导读:

- 核心概念:用户故事 vs BDD场景
- 将用户故事与BDD结合的标准结构
- 核心要素:Given-When-Then 语法
- 实战案例:电商网站的“退货”功能
- BDD的核心优势(为什么这么做)
- 最佳实践Tips
- 总结一句话
这是一个关于 BDD(行为驱动开发) 与 用户故事 结合的完整指南,我们将从核心理念、如何编写、到具体例子进行详细说明。
核心概念:用户故事 vs BDD场景
首先需要理清它们的关系:
- 用户故事: 关注的是 “什么” (What),它描述了一个功能从用户角度出发的价值,通常格式是:As a... I want... So that...
- BDD场景: 关注的是 “如何” (How),它描述了用户故事中具体的、可测试的行为,通常格式是:Given... When... Then...
关键点: BDD是用具体的、可执行的例子来补充和细化用户故事,从而确保团队(业务、开发、测试)对需求有一致的理解。
将用户故事与BDD结合的标准结构
一个完整的使用BDD的用户故事应该包含两部分:
- 用户故事标题与主体: 描述用户角色、功能、目标。
- 验收标准(BDD场景): 使用 Given-When-Then 格式编写的、可自动化的测试用例集合。
核心要素:Given-When-Then 语法
这是BDD的基石,请务必深入理解:
- Given(给定): 上下文,系统处于什么样的初始状态?(用户已登录,账户余额为100元)
- When(当): 事件,用户执行了什么操作?(用户点击“提现”按钮,输入50元并提交)
- Then(: 结果,系统应该产生什么样的可观察行为?(用户收到“提现成功”提示,账户余额变为50元)
进阶语法(企业级):
- And(: 连接多个Given、When或Then。
- But(: 用于描述例外、约束或否定情况。
实战案例:电商网站的“退货”功能
让我们通过一个具体案例来看BDD如何驱动测试。
用户故事
用户故事标题: 顾客申请退货refund
- As a 已购物的顾客
- I want to 在订单送达后30天内申请退货
- So that 我可以拿到退款或进行换货
初步的讨论(背景): 团队需要明确细节,运费谁出?商品状态要求?退货运费规则?
转化为BDD场景(验收标准)
我们将上述用户故事分解为多个BDD场景,每个场景都是一个独立的可测试行为。
场景1:成功退货(正常流程)
Scenario: 顾客在允许时间内成功申请退货退款
Given 顾客“张三”已登录
And “张三”有一个已送达的订单“ORDER-001”
And 该订单的商品“蓝牙耳机”状态为“未拆封”
And 当前日期距离送达日期为7天(小于30天)
When 顾客“张三”在订单详情页点击“申请退货”按钮
And 选择退货原因为“商品尺寸不符”
And 提交退货申请
Then 系统显示“退货申请已提交”
And 系统生成一笔退货记录,状态为“待审核”
And 系统发送退货通知给客服团队
场景2:退货失败——超过退货期限
Scenario: 顾客申请退货时,已超过退货期限
Given 顾客“张三”已登录
And “张三”有一个已送达的订单“ORDER-002”
And 当前日期距离送达日期为35天(超过30天)
When 顾客“张三”在订单详情页点击“申请退货”按钮
Then 系统显示错误提示:“很抱歉,该订单已超过退货期限(30天)”
And 系统中该订单的“退货”按钮处于禁用状态
场景3:退货失败——商品已使用
Scenario: 顾客申请退货时,商品已拆封且使用
Given 顾客“张三”已登录
And “张三”有一个已送达的订单“ORDER-003”
And 该订单的商品“蓝牙耳机”状态为“已使用”(不符合退货政策)
When 顾客“张三”在订单详情页点击“申请退货”按钮
Then 系统显示错误提示:“该商品已使用,不符合退货条件”
场景4:退货有运费抵扣
Scenario: 顾客提交非质量问题退货,退款扣除运费
Given 顾客“张三”已登录
And 订单“ORDER-001”配送地址为“北京市”且使用了免运费优惠
And 退货原因为“个人原因”(非质量问题)
When 顾客成功提交退货申请
Then 系统计算的退款金额为:商品价格 - 原订单的运费金额(假设为10元)
BDD的核心优势(为什么这么做)
- 单一真相来源: 这份 Gherkin 文件是业务、开发、测试三方共同维护的“活文档”。
- 可执行需求: 这些场景可以直接使用 Cucumber、SpecFlow 等框架自动化为测试脚本。
- 减少返工: 在编码前就澄清了歧义(不同退货原因的运费规则是什么?)。
- 驱动设计: 开发者会根据 Given-When-Then 来设计代码结构(如状态模式、策略模式处理不同退货条件)。
最佳实践Tips
- 用业务语言,不要使用技术术语。 写“顾客点击‘提交’按钮”,而不是“触发POST /api/return请求”。
- 每个场景只测试一个独立的行为。 不要在一个长长的场景里测试所有情况,分场景3、场景4。
- Given 是“上下文”,不是“操作”。 Given 部分应设置好前置状态,而不是描述用户操作。
- ❌
Given 顾客输入了用户名和密码 - ✅
Given 顾客已登录
- ❌
- 场景数量控制在5-15个以内 针对一个用户故事,太多可能表示故事太大了(需要拆分)。
- 使用
Examples表格(数据驱动): 当场景逻辑相同但输入数据不同时,使用表格减少重复。
Scenario Outline: 计算不同订单金额的运费
Given 顾客的订单总额为 <订单金额>
When 顾客满足包邮条件
Then 应免运费
Examples:
| 订单金额 |
| 200 |
| 0 | # 特殊情况
| 99.9 | # 边界值
总结一句话
一个好的BDD测试用户故事 = 清晰描述价值的用户故事 + 一组用 Given-When-Then 写成的、可直接自动化的验收场景。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播