BDD has me out of my Gourd with NGourd

As it seems that there is a buzz generating around NGourd on Twitter I figured I really should write a blog post about it. A few weeks ago there was an OzVAN session on Behaviour Driven Development and someone mentioned Cucumber. I found the power of being able to write specifications in plain text and yet execute and verify them using a command line tool very compelling. I promptly set about downloading IronRuby and trying to get Cucumber working against a C# project.

Despite many hours of messing about I couldn’t get that to work. After a few minutes of moping dejectedly about I remembered “Hey I’m a coder! If I want executable text specs then I’ll just make my own.” And so NGourd was born.

NGourd is an open source Behaviour Driven Design framework for .NET which is heavily inspired by Cucumber. I have to warn you that it’s in it’s infancy at this stage but here goes. This is a feature file:

Feature: Search

Scenario: Looking for my blog
Given I am at the home page
When I enter "wolfbyte" into the search box
And I click go
Then I should see a link to http://wolfbyte-net.blogspot.com

Scenario: Looking for weather
Given I am at the home page
When I enter "weather perth" into the search box
And I click go
Then I should see "Weather for Perth WA, Australia"


It should be pretty easy to read. The coolest thing about it is that it is actually executable! In fact this is a file called Search.feature which I just compiled into my pet NGourd test project, a set of Specs to test the behaviour of google.com. When this is run it uses the WatiN library to automate an IE window on my machine and carry out all of the steps in the above two stories. I hope that the sample text is clear enough that you wouldn’t be surprised watching it run.



By default the results are colour coded and dumped to the console. Here is the result of running the above:



NGourd.Google.Search.Output 



Thanks to @liammclennan you can now get an NUnit style XML report out of NGourd as well. Just specify “-o=outfile.xml”. It will also return a status code of –1 on a failed run so it should stop CC.NET (and possibly other Continuous Integration servers) with a broken build.



OK, so I told you it runs the script and offered some kind of proof (albeit in the form of an easily forged screenshot). How exactly does it know how to run the above script? The answer is Step Definitions Containers. A Step Definition Container is a class that defines which steps are available to a scenario and what to do when the step is encountered. Here is the step container which powers the above feature:



public class GoogleSteps : StepContainerBase
{
private IDictionary<string, string> Pages = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
{
{ "home", "http://www.google.com/" }
};

private static IE browser;

public override void BeforeAll()
{
browser = new IE();
}

public override void AfterAll()
{
if (browser != null)
{
browser.Close();
browser.Dispose();
}
}

[Step(@"at the (\w+) page")]
public void GotoPage(string pageName)
{
Assert.That(Pages.ContainsKey(pageName), "Missing Page");
browser.GoTo(Pages[pageName]);
}

[Step(@"enter ""(.*)"" into the search box")]
public void SearchFor(string query)
{
browser.TextField(t => t.Name == "q").Value = query;
}

[Step(@"Press Go"), Step(@"Click Go")]
public void PressGo()
{
browser.Button(b => b.Value == "Google Search").Click();
}

[Step(@"see a link to (.*)")]
public void EnsureLinkExists(string url)
{
Assert.That(
browser.Links.Any(l => l.Url.StartsWith(url)),
"No anchor tags that link to " + url);
}

[Step(@"see ""(.*)""")]
public void ShouldSee(string text)
{
Assert.That(
browser.Text.Contains(text),
"Looking for " + text + " but it wasn't here");
}
}



A Step Container inherits from StepContainerBase (actually it just needs to be annotated with a StepsAttribute but the base class does that for us and adds a few more goodies). Before all of the scenarios are run the BeforeAll method is run which creates a new WatiN IE window. After all of the scenarios are run the AfterAll method is run which disposes of the WatiN window.



The exciting part happens during the scenarios themselves. During each scenario the steps are run in the order provided. NGourd uses the StepAttribute annotations on public methods to select which method to run for each step. The annotations contain regular expressions which are used to identify the correct method to run and extract any parameters out of the original text as well. In this instance each step is only a couple of lines of code (usually one in fact).



If the step throws an exception it is considered to have failed (those Assert.That methods come from the StepContainerBase class and just hide the mechanics of throwing the exception). If one of the steps in a scenario fails then all of the steps after that are skipped and the scenario is marked as failed (which in turn marks the feature as failed). Here is the result if we change the PressGo method to throw an Exception:



NGourd.Google.Search.Failing



You can see the Then steps being skipped in each scenario after PressGo fails. A similar thing occurs if the step cannot be found. If we delete PressGo altogether then we get:



NGourd.Google.Search.NotFound



Again the last step in each scenario gets skipped but the test runner has been able to pick up the fact that the step couldn’t be found. This is great as it means you can start with a feature definition and then create the steps that you need. As you add scenarios to the system you can either add more steps to go with them or annotate existing steps with new regular expressions to make your testing language more flexible.



If you are interested in finding out more you might have to read the source code. If you want to try it out it is hosted on Google Code at http://ngourd.googlecode.com/



There is a quick start on the wiki as well: http://code.google.com/p/ngourd/wiki/QuickStart



Remember that this is not a stable release at this stage so I don’t recommend relying on it for production code. If you have any comments or questions feel free to leave them here, at the NGourd site or drop me an email directly.

bddtoolsasp-netngourdopen-sourcealt-net
Posted by: Mike Minutillo
Last revised: 27 May, 2011 02:42 PM History

Comments

19 May, 2009 07:39 AM @ version 0

Very interesting post, I too tried to look for something similar to cucumber for .net. However ended up using Context/Specification style bdd, when I couldn't find one. I'll be keeping a close eye on your project, it sounds very useful.

Andy

10 Feb, 2012 08:52 AM

Have you looked at http://specflow.org/?

No new comments are allowed on this post.