21

我刚刚进入 BDD 的概念,并听取了 Scott Bellware 与 Herding Code 人员的谈话。我一直在玩 SpecFlow 并且非常喜欢它。

我理解 ATDD 和 TDD 之间的区别,如博客文章Classifying BDD Tools (Unit-Test-Driven vs. Acceptance Test Driven) 和一些 BDD 历史中所述,但这让我想到了一个问题。

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

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

4

5 回答 5

30

The Quick Answer

One very important point to bring up is that there are two flavors of Behavior Driven Development. The two flavors are xBehave and xSpec.

xBehave BDD: SpecFlow

SpecFlow (very similar to cucumber from the Ruby stack) is excellent in facilitating xBehave BDD tests as Acceptance Criteria. It does not however provide a good way to write behavioral tests on a unit level. There are a few other xBehave testing frameworks, but SpecFlow has gotten a lot of traction.

xSpec BDD: NSpec

For behavior driven development on a unit level, I would recommend NSpec (inspired directly by RSpec for Ruby). You can accomplish BDD on a unit level by simply using NUnit or MSTest...but they kinda fall short (it's really hard to build up contexts incrementally). MSpec is also an option, there has been a lot of work put into it, but there are just somethings that are just simpilier in NSpec (you can build up context incrementally in MSpec, but it requires inheritance which can become complex).

The Long Answer

The two flavors of BDD primarily exist because of the orthogonal benefits they provide.

Pros and Cons of xBehave (GWT Syntax)

Pros

  • helps facilitate a conversations with the business through a common dialect called (eg. Given ...., And Given ...., When ......, And When ..... , Then ...., And Then)
  • the common dialect can then be mapped to executable code which proves to the business that you actually finished what you said you'd finish
  • the dialect is constricting, so the business has to disambiguate requirements and make it fit into the sentences.

Cons

  • While the xBehave approach is good for driving high level Acceptance Criteria, the cycles needed to map English to executable code via attributes makes it infeasible for driving out a domain at the unit level.
  • Mapping the common dialect to tests is PAINFUL (ramp up on your regex). Each sentence the business creates must be mapped to an executable method via attributes.
  • The common dialect must be tightly controlled so that managing the mapping doesn't get out of hand. Any time you change a sentence, you have to find method that directly relates to that sentence and fix the regex matching.

Pros and Cons of xSpec (Context/Specification)

Pros

  • Allows the developer to build up context incrementally. A context can be set up for a test and some assertions can be performed against that context. You can then specify more context (building upon the context that already exists) and then specify more tests.
  • No constricting language. Developers can be more expressive about how a certain part of a system behaves.
  • No mapping needed between English and a common dialect (because there isn't one).

Cons

  • Not as approachable by the business. Let's face it, the business don't like to disambiguate what they want. If we gave them a context based approach to BDD then the sentence would just read "Just make it work".
  • Everything is in the code. The context documentation is intertwined within the code (that's why we don't have to worry about mapping english to code)
  • Not as readable given a less restrictive verbiage.

Samples

The Bowling Kata is a pretty good example.

SpecFlow Sample

Here is what the specification would look like in SpecFlow (again, this is great as an acceptance test, because it communicates directly with the business):

Feature File

The feature file is the common dialect for the test.

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
Step Definition File

The step definition file is the actual execution of the test, this file includes the mappings for 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

Here is a NSpec example of the same bowling kata:


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);
    }
}

So Yea...SpecFlow is cool, NSpec is cool

As you do more and more BDD, you'll find that both the xBehave and xSpec flavors of BDD are needed. xBehave is more suited for Acceptance Tests, xSpec is more suited for unit tests and domain driven design.

Relevant Links

于 2011-04-11T19:49:45.487 回答
11

真正的行为驱动工具应该是 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

于 2010-07-29T03:43:40.283 回答
2

我不能只使用普通的单元测试工具吗? 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,需要一些简单易懂的东西。

于 2010-08-02T19:10:34.293 回答
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.

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

于 2010-07-29T03:44:06.647 回答
0

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

根据这篇关于 TDD、BDD 和 ATDD 之间差异的博客,我想说至少有三种不同风格的 BDD工具:

  1. 单元测试框架

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

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

几个人试图让自动化测试更容易理解,因为单元测试并不是真正可读的。最初的尝试之一是解析单元测试并提供简明摘要,非开发人员也可以阅读。例如,TestDox / AgileDox从 JUnit 测试类的方法名称创建简单的文档,或者Pickels基于用 Gherkin 编写的功能文件生成文档。

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

  1. 场景测试框架

为了在开发周期的早期让利益相关者参与进来,创建了更多关注可读输入的新工具。Cucumber利用纯文本文件为自动化测试提供人类可读的输入。文本文件包含基于 given-when-then 结构的特殊结构化语言编写的场景。这些框架是支持协作定义验收标准的出色工具。

  1. 验收测试框架

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

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

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

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

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

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

在此处输入图像描述 在此处输入图像描述

是的,SpecFlow 很酷,NSpec 很酷……

FitNesse 和 Concordion 也很酷

于 2014-10-23T08:54:01.290 回答