【问题标题】:ATDD versus BDD and the proper use of a frameworkATDD 与 BDD 以及正确使用框架
【发布时间】:2011-03-22 12:29:36
【问题描述】:

我刚刚开始了解 BDD 的概念,并且已经听过 Scott Bellware 与 Herding Code 人员的谈话。我一直在玩 SpecFlow 并且非常喜欢它。

我了解博文Classifying BDD Tools (Unit-Test-Driven vs. Acceptance Test Driven) and a bit of BDD history 中描述的 ATDD 和 TDD 之间的区别,但这让我提出了一个问题。

如上所述,使用 BDD 工具(例如 MSpec)不只是另一个单元测试框架吗?在我看来是这样。

此外,这似乎表明使用 SpecFlow 来指定较低级别的组件(例如您的存储库和服务)是错误的。如果我可以对较低级别组件的 ATDD 和 TDD 使用相同的工具,为什么不呢?这里似乎还有一些模糊的线条,我觉得我不太了解。

【问题讨论】:

    标签: tdd bdd specflow


    【解决方案1】:

    真正的行为驱动工具应该是 Cucumber。我们在我的工作中使用它来处理 .NET 代码。这使我们能够编写定义整个系统行为的功能,然后我们可以执行这些功能并验证系统是否符合我们的预期。整个过程对我们来说非常有效。

    http://cukes.info/

    有一个名为 NStep 的 .net 实现,它通过有线协议连接到 cucumber,它允许您使用 lambdas 在 C# 中编写步骤定义……非常棒。

    步骤定义如下所示:

    When("^I go to the \"([^\"]*)\" (?:[Ss]creen|[Pp]age)$", (string pageName) =>
    {
        var screen = ParseScreen(pageName);
        GoToScreen(screen);
        World.Browser.Wait(1000);
    });
    

    http://github.com/clearwavebuild/nStep

    【讨论】:

    • SpecFlow 是 Cucumber 的 .NET 实现。
    • 除了它是一个克隆,它有自己的解析器,它将步骤编译成单元测试。无论多么好,克隆永远不会像原来的那样好。 Cucumber 不断添加使 BDD 方法成为编写软件的好方法的功能。你应该看看真正的黄瓜......它非常强大。
    • BDD 工具真正设计用于测试行为。所以它应该包含整个系统。对于存储库等底层核心业务流程,我将使用 NUnit 并使用 SpecFlow 或 Cucumber 进行行为测试。
    • +1 表示 nstep,而不是重新发明轮子。 NStep 实现了黄瓜线协议,因此您可以在使用 ruby​​ 黄瓜运行器时在 .NET 中实现步骤。 SpecFlow 很好而且很漂亮,但是你错过了所有用于黄瓜的工具。您还缺乏混合简单和动态的 ruby​​ 代码(非常适合使用 Selenium 等 API)和 .NET 代码(非常适合使用数据库和服务外观)的能力。
    • 当前版本的 SpecFlow 使用 Cucumber 中也使用的官方 Gherkin 解析器。在工具方面,SpecFlow 正在努力为标准 .NET 开发设置提供良好的体验。 VisualStudio 集成不断改进,使用现有的测试自动化框架(NUnit、MSTest ...)进行执行是一个明确的决定,可以轻松地集成到现有的基础架构中。我们努力不重新发明轮子......
    【解决方案2】:

    我认为您的理解与我的一致。 BDD 更适合集成测试,通常以最终用户的身份测试您的系统,例如:

    Given I am an authorised user
    When I go to the front page
    Then there should be a link to my profile with my username as the link text.
    

    没有理由不对存储库进行更细粒度的单元测试。我认为两者都是有用且合适的。

    【讨论】:

    • 我仍在测试我的存储库、服务等(目前使用 NUnit),但我真正想知道的是,为此目的使用 SpecFlow 是否也被认为是“错误的”。
    • 我认为是这样,SpecFlow 更适合按原样测试大块代码,无需模拟或隔离。
    • 我同意 Igor 的观点,因为使用 BDD 工具的真正优势在于它允许业务用户编写测试(或者,它允许业务用户理解测试)。由于业务只真正关心整个系统,因此 BDD 工具适合于对整个系统进行测试。如果存储库不能与整个系统集成,业务部门并不真正关心它是否工作。因此,对于更多的单元级测试,BDD 更有可能成为阻碍而不是帮助。
    【解决方案3】:

    我不能只使用普通的单元测试工具吗? BDD 是一种过程和心态,因此,是的,您可以使用任何工具来完成它(或者不是,如果您愿意,您可以在没有工具的情况下编写自己的)。然而,TDD 工具有一些假设,在尝试以 BDD 方式做事时会引起一些摩擦。例如,TDD 假设您正在测试软件的架构单元;类,模块,服务。而 BDD 假设您正在指定系统的某些功能部分。

    我应该使用 SpecFlow/Cucumber 来描述较低级别的组件吗? 首先,我认为这个问题有点误导。您不会倾向于描述组件除非这些组件直接代表行为。我仍然会回答我认为问题的精神。

    Cucumber 等以故事为导向的工具非常适合从客户/用户的角度讨论行为。它可以让您制定外行人容易理解的规范。但是,使用这些工具描述大量或复杂的状态可能很乏味。

    在处理复杂或大型状态设置时,单元测试或更多面向代码的规范工具(如 rSpec 和 Machine.Specification)会更加方便。您可以使用语言可用的各种工具来管理状态。诸如继承和假货/模拟之类的东西。 Machine.Specification 对于 .NET 有一些很好的方法。

    那么,您应该使用 Cucumber 来指定较低级别的行为吗?我只会说对于特定行为具有高水平的可见性很重要。在我当前的项目中,我们开发了一个架构组件来表示系统的某些业务规则密集部分。这些组件是用 Cucumber 指定的,但大部分系统都用 NUnit 覆盖。


    顺便说一句,对于刚进入 BDD 的 .NET 人员来说,SpecFlow 非常好用且平易近人,但最终你会想要毕业到成熟的 Cucumber+nStep。 Cucumber 生态系统巨大而有用。 SpecFlow 的体积要小得多。

    此外,nStep 提供的 lambda 语法比必须装饰方法(如 SpecFlow 或 Cuke4Nuke)要好得多。

    免责声明/背景: 我在 nStep 上进行了一些原始开发,但我在当前项目中使用 SpecFlow。我正在努力在这里介绍 BDD,需要一些简单易懂的东西。

    【讨论】:

      【解决方案4】:

      快速回答

      要提出的一个非常重要的一点是,有行为驱动开发的两种风格。这两种风格是xBehavexSpec

      xBehave BDD:规范流

      SpecFlow(与 Ruby 堆栈中的 cucumber 非常相似)在促进 xBehave BDD 测试作为验收标准方面非常出色。然而,它并没有提供在单元级别编写行为测试的好方法。还有一些其他的 xBehave 测试框架,但 SpecFlow 已经获得了很大的关注。

      xSpec BDD: NSpec

      对于单元级别的行为驱动开发,我会推荐 NSpec(直接受 RSpec 的 Ruby 启发)。您可以通过简单地使用 NUnit 或 MSTest 在单元级别上完成 BDD ......但它们有点不足(很难逐步建立上下文)。 MSpec 也是一种选择,已经投入了很多工作,但在 NSpec 中有些东西更简单(您可以在 MSpec 中逐步建立上下文,但它需要继承,这可能会变得复杂)。

      长答案

      这两种 BDD 风格的存在主要是因为它们提供了正交的好处。

      xBehave(GWT 语法)的优缺点

      优点

      • 通过一种称为通用方言(例如 Given ...., And Given ...., When ......, And When ..... , Then .. ..,然后)
      • 然后可以将通用方言映射到可执行代码,向企业证明您确实完成了您所说的完成
      • 方言很窄,因此业务必须消除需求歧义并使其适合句子。

      缺点

      • 虽然 xBehave 方法有利于推动高级验收标准,但通过属性将英语映射到可执行代码所需的周期使得在单元级别推动域是不可行的。
      • 将通用方言映射到测试是痛苦的(增加正则表达式)。业务创建的每个句子都必须通过属性映射到可执行方法。
      • 必须严格控制通用方言,以免映射管理失控。每次更改句子时,都必须找到与该句子直接相关的方法并修复正则表达式匹配。

      xSpec(上下文/规范)的优缺点

      优点

      • 允许开发人员逐步建立上下文。可以为测试设置上下文,并且可以针对该上下文执行一些断言。然后,您可以指定更多上下文(基于已经存在的上下文),然后指定更多测试。
      • 没有限制性语言。开发人员可以更有效地表达系统特定部分的行为方式。
      • 英语和通用方言之间不需要映射(因为没有)。

      缺点

      • 业务不那么容易接近。让我们面对现实吧,企业不喜欢消除他们想要的歧义。如果我们为他们提供基于上下文的 BDD 方法,那么这句话将只是“让它工作”。
      • 一切都在代码中。上下文文档与代码交织在一起(这就是我们不必担心将英语映射到代码的原因)
      • 由于措辞限制较少,可读性较差。

      样品

      Bowling Kata 就是一个很好的例子。

      SpecFlow 示例

      这是规范在 SpecFlow 中的样子(同样,这非常适合作为验收测试,因为它直接与业务沟通):

      特征文件

      特征文件是测试的常用方言。

      功能:分数计算 为了知道我的表现 作为一名球员 我希望系统计算我的总分 场景:天沟游戏 鉴于一个新的保龄球比赛 当我所有的球都落在排水沟里 那么我的总分应该是0 步骤定义文件

      步骤定义文件是测试的实际执行,该文件包含 SpecFlow 的映射

      [Binding] public class BowlingSteps { private Game _game; [Given(@"a new bowling game")] public void GivenANewBowlingGame() { _game = new Game(); } [When(@"all of my balls are landing in the gutter")] public void WhenAllOfMyBallsAreLandingInTheGutter() { _game.Frames = "00000000000000000000"; } [Then(@"my total score should be (\d+)")] public void ThenMyTotalScoreShouldBe(int score) { Assert.AreEqual(0, _game.Score); } }

      NSpec 示例、xSpec、上下文/规范

      这是一个NSpec 相同保龄球模式的示例:

      class describe_BowlingGame : nspec { Game game; void before_each() { game = new Game(); } void when_all_my_balls_land_in_the_gutter() { before = () => { game.Frames = "00000000000000000000"; }; it["should have a score of 0"] = () => game.Score.should_be(0); } }

      所以是的...SpecFlow 很酷,NSpec 很酷

      随着您做的 BDD 越来越多,您会发现 BDD 的 xBehave 和 xSpec 风格都需要。 xBehave 更适合验收测试,xSpec 更适合单元测试和领域驱动设计。

      相关链接

      【讨论】:

        【解决方案5】:

        有趣的是,这篇关于分类 BDD 工具的博客讨论了 TDD 和 ATDD。正如 Liz Keogh 指出的那样:BDD is about conversation and exploration。所有相关人员越容易做出贡献、交流意图、分享想法、理解他人等。我们越快获得适当的解决方案,我们构建的软件就越好。当我们最终遵循工具路径时,最能支持软件项目利益相关者之间协作的工具是什么?

        基于this blog on the differences between TDD, BDD, and ATDD,我想说至少有三种不同风格的BDD工具:

        1. 单元测试框架

        JUnit 改变了我们对开发和测试的看法。它的优势之一是可以使用与应用程序本身相同的编程语言编写测试。因此,我们可以在交付团队已有的知识基础上再接再厉。当测试甚至用于驱动开发时,我们就达到了 TDD 的天堂。

        编程语言已经过优化以减少冗余,根据 Ron Jeffries 的说法,这是开发人员最严重的罪过之一。因此,当我们进行技术测试以正确构建产品时,我们经常依赖这些工具,因为它们可以帮助我们提高效率。

        有几个人试图让自动化测试更容易理解,比如unit tests aren't really readable。最初的尝试之一是解析单元测试并提供简明摘要,非开发人员也可以阅读。例如,TestDox / AgileDox 根据 JUnit 测试类的方法名称创建简单文档,或者Pickels 根据 Gherkin 编写的功能文件生成文档。

        诸如MSpec 之类的框架有助于编写更易读的测试,并额外提供可读的输出。这些 BDD 工具的风格侧重于人类可读的输出,这使得非开发人员能够在开发人员完成工作后参与其中。

        1. 场景测试框架

        involve stakeholders earlier in the development cycle,创建了更多关注可读输入的新工具。 Cucumber 利用纯文本文件为自动化测试提供人类可读的输入。文本文件包含基于 given-when-then 结构的特殊结构化语言编写的场景。这些框架是支持协作定义验收标准的出色工具。

        1. 验收测试框架

        在 BDD 理念的同时,还开发了另一种工具,其中 FIT 是早期的代表。这个Framework for Integrated Test 允许在嵌入到与示例相关的文档中的表中指定示例。编写这些文档不需要任何开发技能,而且它们可以很容易地被非技术人员阅读和审查,因为它们是纯文本的。此外,文本可以结构化,因为文档不是纯文本文件,而是富编辑器的输出。

        FitNesse 允许基于 wiki 协作指定预期行为。由于 wiki 易于访问和使用,它具有较低的入门和学习曲线,这推动了整个团队的共同工作。许多敏捷支持者强调,最好的协作方式是面对面的交流。但是,如果你把你的想法和讨论写下来,它应该尽可能丰富且结构合理。

        Concordion 提供了很大的灵活性,因为您可以使用段落、表格和适当的标点符号以普通语言描述您的要求。您描述的任何部分都可以用作您的自动化测试的输入,并用于验证您被测系统的输出。由于它基于 HTML,您可以构建文档并集成图像。简而言之,您拥有描述预期行为的网络表达能力。

        BDD 应该有助于构建正确的产品

        您可以使用所有三种工具来实施 BDD,但每种工具都有其优点和缺点。单元测试框架和类似 xSpec 的工具完美地利用了编程的优势。由于它们是为开发人员提供的工具,因此如果您尝试正确处理技术部分,它们是一个完美的选择。

        当您想传达应用程序的意图时,最好使用与编辑人员在工作中使用的工具密切相关的工具。如果一个规范只包含输入和预期输出,任何阅读它的人都必须从输入与预期输出的关系中重构你的想法。标题中解释规范目标的简短描述有助于读者理解规范的结构。基于示例规范的文档可能如下所示:

        是的,SpecFlow 很酷,NSpec 很酷...

        FitNesse 和 Concordion 也很酷

        【讨论】:

          猜你喜欢
          • 2011-02-20
          • 2019-10-26
          • 1970-01-01
          • 1970-01-01
          • 2015-02-24
          • 1970-01-01
          • 1970-01-01
          • 2010-09-06
          • 1970-01-01
          相关资源
          最近更新 更多