我们一直在使用BDD - 行为驱动开发(来自Dan North的观点)作为记录用户验收测试并推动几个项目开发的机制,取得了不错的成功.到目前为止,我们实际上并没有实际自动化测试.
我现在正在考虑自动化测试,但我不确定要支持哪种行为框架.到目前为止,NBehave似乎是先行者 - 但还有其他我应该关注的吗?目前是否有明确的"赢家"?
提出一个非常重要的一点是,行为驱动开发有两种风格. 这两种口味是xBehave和xSpec.
SpecFlow(非常类似于Ruby堆栈中的黄瓜)非常适合将xBehave BDD测试作为Acceptance Criteria.然而,它并没有提供在单元级别编写行为测试的好方法.还有一些其他xBehave测试框架,但SpecFlow已经获得了很大的吸引力.
客观地说.鉴于可用的上下文规范框架,MSpec已经是最长的,并且是.Net社区中使用最广泛的上下文/规范框架.
我个人会推荐NSpec(由RSpec直接启发Ruby).完全披露,我是NSpec的作者之一.你可以通过简单地使用NUnit或MSTest来完成BDD ...但它们有点不足(很难逐步建立上下文). MSpec也是一个选项,是.Net最成熟的上下文/规范框架.但是,在NSpec中只有一些更简单的东西.
答案很长两种BDD主要存在,因为它们提供了正交的好处.
通过一种叫做的公共方言(例如,给定......,给定......,当......,和当......,然后......),有助于促进与业务的对话.然后)
然后可以将普通方言映射到可执行代码,这可以向业务证明您实际完成了您所说的完成内容
方言是收缩的,所以企业必须消除要求的歧义并使其适合句子.
虽然xBehave方法有利于推动高级接受标准,但是通过属性将英语映射到可执行代码所需的周期使得在单元级别驱逐域不可行.
将普通方言映射到测试是痛苦的(提升你的正则表达式).业务创建的每个句子必须通过属性映射到可执行方法.
必须严格控制普通方言,以便管理映射不会失控.每次更改句子时,都必须找到与该句子直接相关的方法并修复正则表达式匹配.
允许开发人员以增量方式构建上下文.可以为测试设置上下文,并且可以针对该上下文执行一些断言.然后,您可以指定更多上下文(基于已存在的上下文),然后指定更多测试.
没有限制语言.开发人员可以更加表达系统某个部分的行为方式.
英语和普通方言之间不需要映射(因为没有一个).
不像业务那样平易近人.让我们面对现实,企业不喜欢消除他们想要的东西.如果我们给他们一个基于上下文的方法来处理BDD,那么句子只会读作"Just make it work".
一切都在代码中.上下文文档在代码中交织在一起(这就是我们不必担心将英语映射到代码的原因)
鉴于限制性较低的措辞,不具备可读性.
该保龄球卡塔是一个很好的例子.
以下是规范在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 Scenario: Single Pin Given a new bowling game When I've hit exactly 1 pin Then my total score should be 1步骤定义文件
步骤定义文件是测试的实际执行,该文件包含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";
}
[When(@"I've hit exactly 1 pin")]
public void When1PinIsHit()
{
_game.Frames = "10000000000000000000";
}
[Then(@"my total score should be (\d+)")]
public void ThenMyTotalScoreShouldBe(int score)
{
Assert.AreEqual(score, _game.Score);
}
}
public class describe_BowlingKata
{
public static Game game;
public class when_all_balls_land_in_the_gutter : describe_BowlingKata
{
Establish ctx = () => game = new Game();
Because of = () => game.Frames = "00000000000000000000";
It should_have_a_score_of_0 = () => game.Score.ShouldBe(0);
}
public class when_a_single_pin_is_hit : describe_BowlingKata
{
Establish ctx = () => game = new Game();
Because of = () => game.Frames = "10000000000000000000";
It should_have_a_score_of_1 = () => game.Score.ShouldBe(1);
}
}
这是同一个保龄球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);
}
void when_a_single_pin_is_it()
{
before = () => game.Frames = "10000000000000000000";
it["should have a score of 1"] = () => game.Score.should_be(1);
}
}
当您执行越来越多的BDD时,您会发现需要BDD的xBehave和xSpec风格.xBehave更适合验收测试,xSpec更适合单元测试和域驱动设计.
年龄和稳定性等客观指标应该是一个因素,我鼓励每个人都考虑到这一点.但是请同时考虑到更新的框架可能提供更简洁的API,更好地使用语言结构,并建立在过去框架的经验教训上.MSpec提供了Given,Since,It和Cleanup的构造.但它们是有代价的:所有成员的静态初始化,类爆炸,并且由于其对委托的独特使用,它在语法上是僵化的.您会发现最简单的MSpec测试在NSpec中更简单.这是一个在MSpec和NSpec中编写的更复杂的测试套件.
xUnit,MSpec和NSpec的比较:https://gist.github.com/amirrajan/6701522
RSpec与黄瓜(RSpec故事)
使用Cucumber和rspec的BDD - 何时多余?
查看SpecFlow.
它是受Cucumber启发的工具,旨在为.NET项目的验收测试驱动开发和行为驱动开发提供实用且无摩擦的方法.
VisualStudio集成似乎特别有前途.
通过Fluent界面,StoryQ看起来是NBehave的不错替代品.我肯定会检查出来.
我不认为真的有'胜利者'.其他框架包括SpecUnit.NET项目,MSpec也在Gallio适配器的开头展示了承诺.从技术上讲,自IronRuby即将出现以来,rSpec 可能是那些准备进入前沿的人的选择.NBehave + NSpec可能是具有最佳自动化功能的最长框架,但我发现自己正在反对过于冗长的语法.
我会全力检查它们并选择最适合您项目风格的框架.它们都是OSS,所以它很难输,真正的好处只是转向BDD.
我个人会建议BDDfy
哪个在我看来很棒!它是开源的,支持常规和流畅的场景描述,涵盖了很好的接受和单元测试.你可以在GitHub上找到它.
Robot Framework也可以与IronPython一起用于.Net中的ATDD或BDD.我认为Robot Framework的表达能力比例如.SpecFlow或NSpec的.它不会强制您使用某种语法,而是使用关键字驱动的方法.如果您正在测试Web应用程序,它的Selenium2Library提供了对Selenium WebDriver的绑定.
还有Spectre,它定义了Boo中的DSL,使其更加自然.