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

发布于 2024-09-11 17:18:39 字数 468 浏览 4 评论 0原文

我刚刚开始了解 BDD 的概念,并且已经听了 Scott Bellware 与 Herding Code 人员的演讲。我一直在尝试使用 SpecFlow,并且非常喜欢它。

我理解博客文章 对 BDD 工具进行分类(单元测试驱动与验收测试驱动)以及一些 BDD 历史,但这让我想到了一个问题。

如上所述,使用 BDD 工具(例如 MSpec)不就是另一种单元测试框架吗?在我看来确实如此。

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

I am just getting into the concept of BDD and have listened to Scott Bellware's talk with the Herding Code guys. I have been playing around with SpecFlow some and like it pretty well.

I understand the distinction between ATDD and TDD as described in the blog post Classifying BDD Tools (Unit-Test-Driven vs. Acceptance Test Driven) and a bit of BDD history, but that leads me to a question.

As described, isn't using a BDD tool (such as MSpec) just another unit testing framework? It seems to me that it is.

Furthermore, this seems to suggest that using SpecFlow to spec out the lower level components (such as your repositories and services) would be wrong. If I can use the same tool for both ATDD and TDD of lower level components, why shouldn't I? There seems to still be some blurry lines here that I feel like I'm not quite understanding.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦幻的心爱 2024-09-18 17:18:39

快速回答

需要提出的非常重要的一点是,行为驱动开发有两种风格。这两种风格是xBehave >x规格

xBehave BDD:SpecFlow

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

xSpec BDD:NSpec

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

长答案

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

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

  • 有助于通过一种称为(例如,Given ....、And Give ....、When ......、And When ..)的通用方言促进与业务的对话 ...,然后...,然后)
  • 然后可以将常见方言映射到可执行代码,这向业务证明您实际上完成了您所说的
  • 方言是收缩的,因此业务必须消除歧义要求并使其适合句子。

缺点

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

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

允许

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

缺点

  • 不太容易被企业所接受。让我们面对现实吧,企业不喜欢明确他们想要的东西。如果我们为他们提供基于上下文的 BDD 方法,那么句子将只是“Just make it work”。
  • 一切都在代码中。上下文文档在代码中交织在一起(这就是为什么我们不必担心将英语映射到代码)
  • 鉴于限制性较少的措辞,可读性较差。

示例

Bowling Kata 是一个很好的例子。

SpecFlow 示例

以下是 SpecFlow 中的规范(同样,这非常适合作为验收测试,因为它直接与业务进行通信):

Feature File

功能文件是测试的常用方言。

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

的映射


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

步骤定义文件是测试的实际执行,该文件包括 SpecFlow NSpec Sample、xSpec、Context/Specification

这是一个 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 更适合单元测试和领域驱动设计。

相关链接

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

风吹雨成花 2024-09-18 17:18:39

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

http://cukes.info/

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

A true behavior driven tool would be something like Cucumber. We use it at my job against .NET code. This allows us to write features that define behavior of the system as a whole and we can then execute the features and verify that the system does what we expect. The whole process works very well for us.

http://cukes.info/

There is a .net implementation called NStep that connects to cucumber via the wire protocol, it allows you to write step definitions in C# using lambdas...its pretty awesome.

Step definitions look like this:

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

栖竹 2024-09-18 17:18:39

我想你的理解和我的一致。 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.

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

I think your understanding is in line with mine. BDD is more suited for integration testing and generally tests your system as the end user, eg:

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.

There is no reason to not to unit test your repositories at a more granular level. I think both are useful and appropriate.

月亮邮递员 2024-09-18 17:18:39

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

Can't I just use normal unit testing tools?
BDD is a process and mentality and so, yes, you can do it with any tools (or not, you can write your own without a tool if you want). However, the TDD tools had certain assumptions which cause some friction when trying to do things in a BDD way. For instance, TDD assumes you are testing an architectural unit of the software; class, module, service. Whereas BDD assumes you are specifying some functional portion of the system.

Should I use SpecFlow/Cucumber to describe lower-level components?
First of all, I think the question is a bit misguided. You wouldn't tend to describe components unless those components directly represent behavior. I'll still answer what I believe the spirit of the question is.

Story oriented tools like Cucumber are great for talking about behavior from a customer/user perspective. It can allow you to make specifications that are easily approachable by laymen. However, it can be tedious to describe large amounts or complex state with those tools.

Unit testing, or more code oriented specification tools like rSpec and Machine.Specification, can be a lot more convenient when dealing with complex or large state setups. You can use the various tools available to the languages to manage the state. Things like inheritance and fakes/mocks. Machine.Specification has some good approaches to this for the .NET minded.

So, should you use Cucumber to specify lower-level behavior? I'd say only if its important to have high levels of visibility for that particular behavior. On my current project, we've developed an architectural component to represent certain business-rule intensive portions of the system. Those components are specified with Cucumber, but the majority of system is covered with NUnit.


Btw, SpecFlow is really nice and approachable for .NET folks just getting into BDD, but eventually you'll want to graduate to full-blown Cucumber+nStep. The Cucumber ecosystem is HUGE and helpful. SpecFlow's is much smaller.

Also, the lambda syntax offered by nStep is quite a bit nicer than having to decorate methods a la SpecFlow or Cuke4Nuke.

Disclaimer/Background:
I did some of the original development on nStep but I'm using SpecFlow on my current project. I'm working to introduce BDD here and needed something simple and approachable.

Bonjour°[大白 2024-09-18 17:18:39

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

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

  1. 单元测试框架

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

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

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

MSpec 等框架有助于编写更具可读性的测试,并另外提供可读输出。这些 BDD 工具侧重于人类可读的输出,这使得非开发人员能够在开发人员完成工作后参与进来。

  1. 场景测试框架

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

  1. 验收测试框架

与 BDD 理念并行的,另一种工具也被开发出来,其中 FIT 是早期的代表。这个集成测试框架允许在嵌入到与以下内容相关的文档中的表格中指定示例例子。编写这些文档不需要任何开发技能,非技术人员可以轻松阅读和审阅它们,因为它们纯粹基于文本。此外,文本可以结构化,因为文档不是纯文本文件,而是丰富编辑器的输出。

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

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

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

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

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

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

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

FitNesse 和 Concordion 也很酷

It is interesting that this blog on Classifying BDD Tools talks about TDD and ATDD. As Liz Keogh points out: BDD is about conversation and exploration. The easier it is for all involved guys to contribute, communicate intension, share ideas, understand the others, etc. the faster we get to an adequate solution and the better software we build. When we finally follow the tool path, what are the tools that support collaboration between stakeholders of software projects best?

Based on the this blog on the differences between TDD, BDD, and ATDD I would say that there are at least three different flavors of BDD tool:

  1. Unit Testing Frameworks

JUnit changed our view on development and testing. One of its strengths is that tests can be written in the same programming language as the application itself. Thus, we can build on the knowledge we already have in the delivery team. When the tests are even used to drive the development we reach the heaven of TDD.

Programming languages have been optimized to reduce redundancy, which is according to Ron Jeffries one of the worst sins of developers. Therefore, we often rely on these tools when we do technical testing to build the product right as they help us to be most efficient.

Several guys tried to make automated tests more understandable, as unit tests aren't really readable. One of the first attempts was to parse unit tests and provide a concise summary that is also readable to non-developers. For example TestDox / AgileDox creates simple documentation from the method names of JUnit test classes or Pickels generates documentation based on feature files written in Gherkin.

Frameworks such as MSpec help to write tests that are better readable and additionally provide readable output. These flavor of BDD tools focuses on human readable output, which enables the involvement of non-developers after the developers did their job.

  1. Scenario Testing Frameworks

To involve stakeholders earlier in the development cycle, new tools were created that focus more on readable input. Cucumber utilizes plain text files to provide human readable inputs for automated tests. The text files contain scenarios written in a specially structured language based on the given-when-then structure. These frameworks are great tools that support collaborative definition of acceptance criteria.

  1. Acceptance Testing Frameworks

In parallel to the BDD idea, another flavor of tools has been developed, where FIT was an early representative. This Framework for Integrated Test allows to specify examples within tables that are embedded into a documentation related to the examples. To write these documents no development skills are required and they can be easily read and reviewed by non technical guys as they are purely text based. Additionally, the text can be structured as the documents are not plain text files but the output of rich editors.

FitNesse allows to specify the expected behavior collaboratively based on a wiki. As wikis are easy to access and use, it has a low entry and learning curve, which propels the common work of the entire team. Many agile proponents emphasize that the best way for collaboration is face-to-face communication. But, if you write down what you have thought and discussed, it should be as rich and well structured as possible.

Concordion provides a lot of flexibility as you can describe your requirements in normal language using paragraphs, tables and proper punctuation. Any part of your description can be used as input to your automated tests and for the validation of the outputs of your system under test. As it is based on HTML you can structure your documents and integrate images. Simply, you have the expressiveness of the web to describe the expected behavior.

BDD should help to build the right product

You could implement BDD with all three flavors of tools, but each has its strengths and weaknesses. Unit testing frameworks and xSpec like tools perfectly use the strengths of programming. As they are tools from developers for developers, they are a perfect choice if you try to get the technical part right.

When you want to communicate the intention of the application you are probably better off with a tool that is strongly related with tools that editors use for their work. If a specification contains only inputs and expected outputs, anyone who reads it will have to reconstruct your ideas from the relation of inputs to expected outputs. A short description explaining the goal of a specification in the header helps the reader understand the structure of the specification. Documents based on specification-by-example could look like:

enter image description here
enter image description here

Yes, SpecFlow is cool, NSpec is cool ...

FitNesse and Concordion are cool as well

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文