我只是进入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使用相同的工具,为什么不呢?这里似乎仍然有些模糊的线条,我觉得我不太了解。
最佳答案
快速解答
值得一提的非常重要的要点是行为驱动开发有两种风格。 两种口味是 xBehave 和 xSpec 。
xBehave BDD:SpecFlow
SpecFlow(非常类似于Ruby堆栈中的cucumber)在促进xBehave BDD测试作为验收标准方面非常出色。但是,它不能提供在单元级别编写行为测试的好方法。还有其他一些xBehave测试框架,但是SpecFlow吸引了很多人。
xSpec BDD:NSpec
对于单位级别的行为驱动开发,我建议使用NSpec(由Ruby的RSpec直接启发)。您可以通过简单地使用NUnit或MSTest在单元级别上完成BDD ...但是它们有点不足(确实很难逐步建立上下文)。 MSpec也是一个选项,已经投入了很多工作,但是在NSpec中有些东西只是简单的(您可以在MSpec中逐步建立上下文,但是它需要继承,而继承会变得很复杂)。
长答案
BDD的两种味道主要是因为它们提供的正交利益而存在。
xBehave的优缺点(GWT语法)
优点
缺点
xSpec的优缺点(上下文/规范)
优点
缺点
样品
Bowling Kata是一个很好的例子。
SpecFlow样本
这是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 flavor 都是必需的。 xBehave更适合于验收测试,xSpec更适合于单元测试和域驱动设计。
相关连结
关于tdd - ATDD与BDD以及框架的正确使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3359327/