5.4 BDD 与 ATDD:换一种说法写测试


5.4 BDD 与 ATDD:换一种说法写测试

本节摘要:BDD(行为驱动开发)与 ATDD(验收测试驱动开发)不是 TDD 的替代品,而是它的业务方言:用 Given-When-Then 讲清行为,用验收测试从外向内驱动实现,红绿重构的节律一步没变。本节讲清两者的分工,演示 pytest 环境下的 BDD 写法,并给"要不要引入 BDD 工具"一个务实的判断标准。读完你应能为需求协作重的团队选对措辞层级与工具。

产品经理在评审会上听开发念测试名:test_coupon_stack_cap_v2_final——念完全场沉默,没人知道它在说什么。老周把同一条行为换了个说法:**"假如"会员车里有百元商品,"当"他同时使用平台券与店铺券,"那么"优惠不超过十元。**产品经理立刻接话:"对,就要这个,但黑名单用户除外。"下一秒,一条新用例在对话中诞生了。这就是 BDD 的全部动机:测试语言和需求语言对齐之后,需求评审会直接产出用例。

BDD 与 ATDD 分工

两个词常被混用,分工其实清楚。ATDD 是流程:验收标准先写成可执行测试,从外向内驱动开发——先红(验收不通过),再实现,单元层的红绿循环为它打工,节律是"外红驱动内红"。BDD 是措辞与协作法:Given(前提)、When(动作)、Then(结果)的三段句式把用例翻译成业务方读得懂的话;落到工具上才有 Cucumber、pytest-bdd 这类框架。一句话记牢:ATDD 管"先测什么",BDD 管"怎么说清"——两者经常一起用,但谁也不依赖谁。

pytest 现场写法

Python 生态里 BDD 的主流落地是 pytest-bdd:行为写在特性文件里,步骤映射回普通 pytest 函数,断言、夹具、替身照用不误:

# features/coupon_stacking.feature 功能: 优惠券叠加 场景: 平台券与店铺券叠加封顶 假如 会员车里有价值 100 元的商品 而且 会员不在黑名单 当 他同时使用平台券与店铺券 那么 优惠总金额不超过 10 元
# features/steps/coupon_steps.py from pytest_bdd import scenarios, given, when, then, parsers scenarios("../features") @given(parsers.parse("会员车里有价值 {amount:d} 元的商品"), target_fixture="order") def an_order(amount): return an_order_builder(raw_total=Decimal(amount)).build() @given("会员不在黑名单") def clean_member(): return blacklist_of([]) @when("他同时使用平台券与店铺券") def apply_coupons(order): order.coupons = ["PLATFORM", "SHOP"] @then(parsers.parse("优惠总金额不超过 {cap:d} 元")) def discount_capped(order, cap): assert coupon_discount(order) <= Decimal(cap)

注意步骤函数里发生的事:夹具(target_fixture)在步骤间传递现场,断言还是原生 assert,上一章的替身与假时钟在步骤里照用。BDD 只是换了皮的故事层,底层仍是 pytest 的世界——这层皮的价值在评审会上:特性文件就是需求文档,需求方逐句可读、可改、可认领。

层级全景:一套节律,三种方言

把全书的层级串起来看,BDD 的位置一目了然:

读者 语言 驱动什么
特性文件(BDD/ATDD) 产品、业务、测试 Given-When-Then 验收口径,从外向内
单元测试(前四章) 开发 断言与行为名 实现,红绿重构
契约与集成(5.1、4.3) 开发与协作方 协议用例 拼装真相

三层讲的是同一套行为的三个抽象级——理想状态下,一条特性场景红灯亮起,驱动出若干单元红灯,全部转绿后特性场景跟着转绿。这就是"外红驱动内红"的完整节拍:ATDD 的验收测试先立招牌,TDD 的单元循环填肉。

引不引工具:务实的判断

pytest-bdd 这类工具不是免费的:特性文件与步骤定义是两套资产,维护成本实打实存在。判断标准看协作面:**业务方真的会读、会写、会认领用例吗?**会,语言对齐的收益远超维护成本,值得引入;不会(团队就是几个人,需求靠口口相传),那就退一步用"BDD 风格"——把 Given-When-Then 的精神留在 pytest 里,测试名与断言组织成三段式叙事,同样能收获沟通价值,零额外工具。为工具而工具的 BDD,和为模式而模式的策略一样,都是过度设计。

特性文件的评审检查点

特性文件既然是需求文档,就该进需求评审而非只进代码评审。三个检查点保证它的生命体征:业务方可读——随手拉一位产品同事读一条场景,卡壳的句子就是混入实现词汇的句子;场景独立——每条场景不依赖其他场景的执行顺序,Given 把前提写全,而不是"接着上一条";断言可判定——Then 里不许出现"大概""合理"这类需要人脑判断的词,验收口径必须落到可计算的表述。三个检查点每周花十分钟过一遍新特性文件,BDD 资产就不会像大多数团队的文档那样悄悄烂掉。

⚠️ 最常见的 BDD 失败是"假业务语言":场景里写满字段名与状态码,业务方一个字看不懂。特性文件的语言纯净度是它的生命线——出现实现词汇的那一刻,就退回单元层去表达。

💡 判断 BDD 是否落地有一观察哨:评审会上产品经理是否直接修改过特性文件。修改过,说明需求语言与测试语言真正接轨;从未被业务方碰过的特性文件,只是披着马甲的单元测试。

回到节律

  • ATDD 管流程:验收先行,外红驱动内红;BDD 管措辞:三段句式对齐业务语言。
  • pytest-bdd 只是故事皮,底层仍是夹具、替身与断言的全套功夫。
  • 特性文件是需求文档,语言纯净度高于一切;业务方读不懂即失败。
  • 引不引工具看协作面:业务方参与用 BDD 工具,小团队用 BDD 风格即可。
  • 至此,TDD 在代码层与需求层的手艺都齐了。下一章让机器加入循环:流水线与工具链。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U