ATDD与BDD以及框架的正确使用

时间:2010-07-29 03:39:59

标签: tdd bdd specflow

我刚刚进入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,为什么我不应该?这里似乎仍然有一些模糊的线条,我觉得我不太了解。

5 个答案:

答案 0 :(得分:29)

快速回答

一个非常重要提出的观点是两种风格的行为驱动开发。这两种风格是 xBehave xSpec 即可。

xBehave BDD:SpecFlow

SpecFlow(非常类似于Ruby堆栈中的cucumber)非常适合将xBehave BDD测试作为验收标准。然而,它并没有提供在单元级别编写行为测试的好方法。还有一些其他xBehave测试框架,但SpecFlow已经获得了很大的吸引力。

xSpec BDD:NSpec

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

长答案

两种口味的BDD主要存在,因为它们提供了正交的好处。

xBehave(GWT语法)的优点和缺点

赞成

  • 通过一种叫做的公共方言帮助促进与企业的对话(例如,给定......,给定......,当......,和......时,...... ..,然后)
  • 然后可以将普通方言映射到可执行代码,这可以向企业证明你实际完成了你说你已经完成的事情
  • 方言是收缩的,所以企业必须消除要求的歧义并使其适合句子。

缺点

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

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

赞成

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

缺点

  • 业务不容易接近。让我们面对现实,企业不喜欢消除他们想要的东西。如果我们给他们一个基于上下文的BDD方法,那么这句话只会是“Just make it work”。
  • 一切都在代码中。上下文文档在代码中交织在一起(这就是我们不必担心将英语映射到代码的原因)
  • 鉴于限制性较低的措辞,不具备可读性。

样品

Bowling Kata是一个很好的例子。

SpecFlow样本

这是规范在SpecFlow中的样子(再次,这是一个很好的验收测试,因为它直接与业务沟通):

特征文件

要素文件是测试的常用方言。

Feature: Score Calculation 
  In order to know my performance
  As a player
  I want the system to calculate my total score

Scenario: Gutter game
  Given a new bowling game
  When all of my balls are landing in the gutter
  Then my total score should be 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 Sample,xSpec,Context / Specification

这是同一个保龄球kata的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更适合单元测试和域驱动设计。

相关链接

答案 1 :(得分:11)

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

http://cukes.info/

有一个名为NStep的.net实现,它通过有线协议连接到黄瓜,它允许你使用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

答案 2 :(得分: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.

没有理由不在更细粒度级别对您的存储库进行单元测试。我认为两者都是有用和适当的。

答案 3 :(得分:2)

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

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

像Cucumber这样的面向故事的工具非常适合从客户/用户角度谈论行为。它可以让您制作出非常容易接近的规格。但是,使用这些工具描述大量或复杂的状态可能会很繁琐。

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

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


顺便说一句,对于刚刚进入BDD的.NET人来说,SpecFlow真的很好用,也很平易近人,但最终你会想要毕业于成熟的Cucumber + nStep。黄瓜生态系统是巨大而有益的。 SpecFlow的尺寸要小得多。

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

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

答案 4 :(得分:0)

有趣的是,这篇关于BDD工具分类的博客讨论了TDD和ATDD。正如Liz Keogh指出:BDD is about conversation and exploration。所有参与者都更容易做出贡献,沟通意见,分享想法,了解其他人等等,我们能够更快地获得适当的解决方案以及我们构建的更好的软件。当我们最终遵循工具路径时,哪些工具最能支持软件项目利益相关者之间的协作?

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

  1. 单元测试框架
  2. JUnit改变了我们对开发和测试的看法。它的优势之一是测试可以用与应用程序本身相同的编程语言编写。因此,我们可以利用我们在交付团队中已有的知识。当测试甚至用于推动开发时,我们就达到了TDD的天堂。

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

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

    MSpec等框架有助于编写更易读的测试,并提供可读输出。这些BDD工具的注重力集中在人类可读的输出上,这使得非开发人员能够在开发人员完成工作后参与其中。

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

      1. 验收测试框架
      2. 与BDD理念并行,已经开发出另一种工具,其中FIT是早期的代表。此Framework for Integrated Test允许在表中指定嵌入到与示例相关的文档中的示例。要编写这些文档,不需要开发技能,非技术人员可以轻松阅读和审阅这些文档,因为它们纯粹是基于文本的。此外,文本可以结构化,因为文档不是纯文本文件,而是丰富编辑器的输出。

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

        Concordion提供了很大的灵活性,因为您可以使用段落,表格和正确的标点来用正常语言描述您的要求。描述的任何部分都可以用作自动测试的输入和被测系统输出的验证。由于它基于HTML,您可以构建文档并集成图像。简单地说,您有网络的表现力来描述预期的行为。

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

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

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

        enter image description here enter image description here

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

        FitNesse和Concordion也很酷