TDD和BDD的区别

57

说实话,我看不出BDD和TDD之间的区别。我的意思是,两者都只是测试是否发生了预期的情况。我见过很详细的BDD测试,它们几乎可以算作TDD测试,并且我见过很模糊的TDD测试,它们对许多代码进行了封装处理。我们可以这样说,我相信同时使用两种测试更好。

但有一个有趣的问题,我该从哪里开始呢?是从高级别的BDD测试开始吗?还是从低级别的TDD测试开始呢?


可能是什么是TDD和BDD的主要区别?的重复问题。 - Raedwald
10个回答

85

我真的看不出BDD和TDD之间有什么区别。

那是因为它们没有任何区别。

我的意思是,两者都只是测试是否发生了预期的事情。

这是错误的。BDD和TDD与测试完全无关。完全没有。没有任何关系。尽管TDD中几乎所有地方都有“测试”这个词(不仅在名称中,还有在测试框架、单元测试、TestCase(通常继承自的类)、FooTest(通常包含您的测试的类)、testBar(测试方法的典型命名模式)以及许多测试相关术语,例如“断言”和“验证”),这导致一些人认为它实际上与测试有关。 因此,一些聪明的人说:“嘿,让我们改个名字”以消除任何潜在的混淆。

这就是BDD。 它只是TDD,其中任何与测试相关的术语都被行为示例相关的术语替换:

  • Test → Example
  • Assertion → Expectation
  • assertshould
  • Unit → Behavior
  • Verification → Specification
  • … 等等

BDD只是用不同的词语表述的TDD。如果您正确实践TDD,那么您也在实践BDD。不同之处在于– 假设您至少相信Sapir-Whorf假说的弱形式– 不同的术语使得正确实践更容易。


感谢@Jörg。语言是BDD中最基本的概念之一。唯一缺少的是在“测试”编写之前关注对话和发现。我会说这确实有所不同;语言和语言引发的问题产生了巨大的影响,这是非常微妙而重要的。 - Lunivore
你能分享一下你的资源,以证明TDD与测试无关吗?我很困惑,因为从软件工程师(Sommerville)那里学到的是:测试驱动开发(TDD)是一种程序开发方法,其中你交替进行**测试**和代码开发(Beck,2002)。基本上,你逐步开发代码,并为该增量编写一个**测试**。只有当你开发的代码**通过了测试**后,才会继续进行下一个增量的开发。测试驱动开发是敏捷方法(如极限编程)的一部分。 - qxlab
将BDD与TDD混淆,就像将宏观经济学与微观经济学混淆一样。它们是不同的。BDD =使用示例构建对需求的理解,并可选择使用它来驱动自动化宏观测试。(https://agilenoir.biz/en/am-i-behavioral-or-not/),TDD =编写微型测试以驱动编写代码。敏捷思维播客也涵盖了这些差异: http://agilenoir.biz/en/agilethoughts/test-automation-pyramid-series/ - Lance Kind
1
因为"That's because there isn't any."是完全错误的,所以请对该答案进行负评。例如,https://cucumber.io/blog/bdd/bdd-vs-tdd/有许多解释区别的参考资料。 - dimmits
因为答案错误,所以我要点踩。BDD和TDD之间有区别。BDD更多地是一个协作过程,其结果是推导出场景,这些场景由开发人员和质量保证人员用于实现和测试解决方案。TDD纯粹是为了让开发人员编写更好的代码。这是我的博客,解释了BDD和TDD之间的区别:https://blog.nocodebdd.com/bdd-vs-tdd/ - Jerome Josephraj
显示剩余2条评论

42

BDD从客户的角度出发,专注于整个系统预期行为。

TDD从开发人员的角度出发,专注于一个单元/类/功能的实现。它可以从更好的架构(设计可测试性、模块之间的耦合减少等)中受益。

从技术角度来看(如何编写“测试”),它们是相似的。

从敏捷的角度来看,我会从一个BDD用户故事开始,并使用TDD来实现它。


2
嗯…BDD实际上始于TDD层面。这是链接:http://blog.dannorth.net/introducing-bdd/ - 应该会有所帮助。 - Lunivore

8
根据维基百科的资料,BDD包括验收和QA测试,这些测试需要利益相关者/用户的输入才能完成。此外,BDD使用自然语言来指定其测试,而TDD通常使用编程语言。两者之间可能存在一些重叠,但我认为主要区别不在于模糊性,而在于BDD的语言。

至于从哪里开始,这实际上取决于您的开发过程,不是吗?如果您是自下而上进行开发,我假设您将首先编写TDD,一旦达到更高级别,将使用BDD测试这些功能是否按预期工作。

正如k3b所指出的:主要区别在于BDD面向问题域,而TDD更加面向解决方案域。


你的评论非常明智,考虑到用户通常接受的关于BDD和TDD的信息以及“流行工具”(例如语言及其开发/交付系统)的背景。真正帮助我“理解”BDD的是当我看到它实际上是Hoare逻辑时,这是设计按合同的基础。一旦我看到了这一点,我很快意识到BDD有一个纯代码版本,可以应用于任何级别的任何代码模块。它也可以应用于人类测试的人类级别(例如QA / QC,业务分析,alpha测试,beta测试,甚至用户文档编写等)。 - Liberty Lover

4

我认为Matthew Flynn的回答更加准确,他的观点是BDD是TDD的扩展和修订。它的目的是帮助系统设计者(即开发人员)确定要编写的适当测试 - 即反映利益相关方所需行为的测试。最终效果相同-先开发测试,然后开发通过测试的代码/系统。BDD的希望是测试实际上在显示系统是否符合要求时有用。

更新

代码单元(单个方法)可能过于精细以代表行为测试所代表的行为,但您仍应使用单元测试对其进行测试以确保其正常运作。如果这就是你所说的“TDD”测试,那么是的,你仍然需要它们。


这有助于突出显示BDD理解通常是偏颇和不完整的。BDD和TDD都关注软件正确性——无论是在用户/系统需求API级别还是在支持它的软件模块的深度分析中。只需考虑“正确”的概念并开始询问:在调用和访问其方法、函数和属性之前和之后,我的类状态是否正确?当调用此方法或函数时,我的类和参数的状态是否正确?这个类属性的状态是否始终正确?整个问题都是关于软件正确性的。句号。 - Liberty Lover
Eiffel和EiffelStudio具有将软件正确性工具正确应用于语言规范、编译器、静态分析工具和测试工具的概念。它们都经过深思熟虑地设计,可以作为一组互补的工具一起使用,以便在任何级别上确保您的软件尽可能正确——无论是在用户/系统要求级别还是在最深层次的库代码级别。 - Liberty Lover

3
我认为BDD相对于TDD或其他方法最大的贡献在于使非技术人员(产品所有者/客户)参与软件开发过程的各个层面。将可执行的场景用自然语言编写,几乎弥合了需求和交付之间的差距。
产品所有者可以运行他所编写的场景,并使用不同的数据集进行测试,以便玩转由开发团队编写的代码的行为。
这太棒了!客户坐在中心位置,不仅能够确切地了解自己需要什么,还可以验证和体验交付成果。

您指出API层级,用户作为软件系统的客户端进行Given-When-Then(即BDD)交互的观点是基本正确的。在这种情况下,BDD正是您所说的——从客户-用户的角度定义前置条件和后置条件。人们未能意识到的是,作为设计合同的BDD超越了客户-用户API的肤浅性,并适用于软件系统的每个类、方法、属性和函数。请参见我在Github上的评论中的更多信息和示例。 - Liberty Lover

3

首先,作者不是以英语为母语的人,因此读者需要谨慎阅读这篇幽默文章,克服糟糕语法的障碍。其次,“测试驱动开发(TDD)与测试几乎没有关系”的观点最好是值得商榷的,最糟糕的情况则是可笑的。当然,TDD确实与测试有关。在TDD范式中,没有人认为、期望或相信TDD代码断言可以取代人类对代码进行测试——尤其不是在alpha、beta或其他预生产测试中。TDD从未站在那个山丘上插旗子。 - Liberty Lover

2

1

术语不同,但在我的工作中,我使用TDD进行详细开发,主要用于单元测试,而BDD更高级,面向客户、QA或非技术人员。


关于TDD/BDD的文档真的很容易被解释。这是我的解释:https://dev59.com/dUfRa4cB1Zd3GeqP6y7H#45971814 - user2288580

0

总体

BDD实际上是使用不同术语的设计契约。一般来说,BDD采用Given-When-Then的形式,这大致类似于前置条件(Given)、检查条件/循环不变量(When)和后置条件/不变量(Then)。

注意事项

请注意,BDD非常类似于Hoare逻辑(即{P}C{Q}或{P}recondition-[C]ommand-{Q}Post-condition)。因此:

  • 前置条件(Given)必须为命令(方法/函数)正确计算而成立。任何违反给定(前置条件)的行为都会导致调用客户端代码出现故障。
  • 命令(When)是在满足前置条件之后发生的。在Eiffel中,它们可以在方法或函数代码中用其他合同标记。将其视为沿着流程装配线的QA/QC检查。
  • 后置条件(Then)必须在命令(When)完成后成立。

寓意

BDD只是以不同的措辞重新包装的DbC(Hoare-logic),这意味着它不是TDD。为什么?因为TDD不是关于将前置条件/检查/后置条件合约直接绑定到方法、函数、属性和类状态上的。TDD是在测试方法、函数、属性和类及其离散状态方面迈向更高阶段的步骤。一旦你看清了这一点,并充分理解了TDD不是BDD,BDD不是TDD,而是彼此独立且互补的软件正确性证明技术,那么你就会正确地理解这些主题。你也会正确地使用和应用它们。

结论

我所知道的唯一一个把BDD(Design-by-Contract)原生融入语言规范和编译器的语言是Eiffel。它不是一个带有限制的Frankenstein附加组件。在Eiffel中,BDD(又名DbC)是软件正确性工具箱中优雅、有用、实用和直接参与的一部分。

另请参阅

Wikipedia可以帮助定义Hoare-logic。请参阅:https://en.wikipedia.org/wiki/Hoare_logic

我已经在Eiffel中创建了一个示例,你可以查看。请参阅:

主类: https://github.com/ljr1981/stack_overflow_answers/blob/main/src/so_73347395/so_73347395.e 测试类: https://github.com/ljr1981/stack_overflow_answers/blob/main/testing/so_73347395/so_73347395_test_set.e

-1
主要的区别在于措辞。BDD使用更冗长的风格,以便几乎可以像句子一样阅读。

冗长不是主要区别。BDD和TDD并不相同,也没有试图成为相同的东西。TDD希望从外部测试对象——也就是使用对象(或模块)的API。另一方面,BDD试图假装成为按合同设计并从内部进行测试。BDD的问题在于它像TDD一样从外部实现,这就是为什么BDD无法跨越Hoare逻辑终点线的原因。请参见我在TDD与BDD、Hoare逻辑和按合同设计下面的评论。 - Liberty Lover

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接