Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<h1>The Quick Answer</h1> <p>One <strong>very important</strong> point to bring up is that there are <strong>two flavors of Behavior Driven Development.</strong> The two flavors are <strong>xBehave</strong> and <strong>xSpec</strong>. </p> <h2>xBehave BDD: SpecFlow</h2> <p>SpecFlow (very similar to <a href="http://cukes.info/" rel="noreferrer" title="Cucumber">cucumber</a> 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.</p> <h2>xSpec BDD: MSpec</h2> <p>Objectively speaking. Given the context specifications frameworks available, MSpec has been around the longest and is the most widely used context/specification framework in the .Net community.</p> <h2>The other xSpec BDD framework: NSpec</h2> <p>I personally would recommend <a href="http://nspec.org" rel="noreferrer" title="NSpec">NSpec</a> (inspired directly by <a href="http://rspec.info/" rel="noreferrer" title="RSpec">RSpec</a> for Ruby). Full disclosure, I am one of the authors of NSpec. You can accomplish BDD by simply using NUnit or MSTest...but they kinda fall short (it's really hard to build up contexts incrementally). <a href="https://github.com/machine/machine.specifications" rel="noreferrer" title="MSpec">MSpec</a> is also an option and is the most mature context/specification framework for .Net. <em>But</em>, there are just some things that are simpler in NSpec.</p> <h1>The Long Answer</h1> <p>The two flavors of BDD primarily exist because of the orthogonal benefits they provide.</p> <h2>Pros and Cons of xBehave (GWT Syntax)</h2> <h3>Pros</h3> <ul> <li>helps facilitate a conversations with the business through a common dialect called (eg. Given ...., And Given ...., When ......, And When ..... , Then ...., And Then)</li> <li>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</li> <li>the dialect is constricting, so the business has to disambiguate requirements and make it fit into the sentences.</li> </ul> <h3>Cons</h3> <ul> <li>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.</li> <li>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.</li> <li>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.</li> </ul> <h2>Pros and Cons of xSpec (Context/Specification)</h2> <h3>Pros</h3> <ul> <li>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.</li> <li>No constricting language. Developers can be more expressive about how a certain part of a system behaves.</li> <li>No mapping needed between English and a common dialect (because there isn't one).</li> </ul> <h3>Cons</h3> <ul> <li>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".</li> <li>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)</li> <li>Not as readable given a less restrictive verbiage.</li> </ul> <h2>Samples</h2> <p>The <a href="http://codingdojo.org/cgi-bin/index.pl?KataBowling" rel="noreferrer" title="Bowling Kata">Bowling Kata</a> is a pretty good example. </p> <h3>SpecFlow Sample</h3> <p>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):</p> Feature File <p>The feature file is the common dialect for the test.</p> <pre> 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 </pre> Step Definition File <p>The step definition file is the actual execution of the test, this file includes the mappings for SpecFlow</p> <pre> <code> [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); } } </code> </pre> <h3>MSpec Sample, xSpec, Context/Specification</h3> <pre> <code> 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); } } </code> </pre> <h3>NSpec Sample, xSpec, Context/Specification</h3> <p>Here is a <a href="http://nspec.org" rel="noreferrer" title="NSpec">NSpec</a> example of the same bowling kata:</p> <pre> <code> 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); } } </code> </pre> <p>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.</p> <h3>MSpec vs NSpec</h3> <p>Objective metrics like age and stability should be a factor, and I would encourage everyone to take that into consideration. But please also <strong>take into consideration that newer frameworks may provide a more succinct api, better usage of language constructs and build on lessons learned for past frameworks</strong>. MSpec provides constructs of Given, Because, It and Cleanup..but they come at a cost: static initialization for all members, class explosion, and it's syntactically rigid because of its unique use of delegates. You'll find that the simplest MSpec tests are simpler in NSpec. Here is a more complex test suite written both in MSpec and NSpec.</p> <p>A Comparison of xUnit, MSpec and NSpec: <a href="https://gist.github.com/amirrajan/6701522" rel="noreferrer">https://gist.github.com/amirrajan/6701522</a></p> <h3> Relevant Links</h3> <p><a href="https://stackoverflow.com/questions/393622/rspec-vs-cucumber-rspec-stories">RSpec vs Cucumber (RSpec stories)</a></p> <p><a href="https://stackoverflow.com/questions/3736808/bdd-with-cucumber-and-rspec-when-is-this-redundant">BDD with Cucumber and rspec - when is this redundant?</a></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload