While using nBehave on projects especially those where we collaborated with external partners I created/shared the following list of guidelines/tips which might save you some time too. So here I am sharing it to a broader audience… maybe :)
1. All declarations/instantiations must be placed after the narrative
2. All code that can fail must be inside an actionstep delegate or lambda
3. How to execute and debug using nBehave Console Runner
4. Improving execution and debugging by integrating with nUnit
All declarations/instantiations must be placed after the narrative
The first two solve the same problem. When code fails that’s not inside an actionstep it is unhandled (especially with the nbehaverunner, look at 4 for a different runner) and the whole thing just stops with an exception. What’s even worse invalid/incomplete xml is written that will break any xslt transformation or processing which I found out the hard way while maintaining a CI (hudson). How to integrate nBehave (or rather how I integrated it) with Hudson is worth a post on it’s ownn that will follow.
nBehaveuses the Story class to execute and listen to output of the specification. A very important consequence is that if code that is not part of an actionstep (inside a lambda or delegate as a parameter of an actionstep) the complete test fails with no or invalid output.
A lot of us would write a spec in this way (since we are used to put our declarations at the beginning of a code block:
IRepository repository = Service.Get<IRepository>();
Story storeObjectStory = new Story("Store and retrieve an object in the repository");
When the Service.Get fails the story will never be created and we have no output on why or which test failed.
Our first guideline is to move all declarations past the story narrative. We created a modified nBehave runner build that produces valid output even when the code throws an exception (if you’re interested let me know).
Let's look at our modified example:
Story storeObjectStory = new Story("Store and retrieve an object in the repository");
storeObjectStory.AsA("service in the platform")
.IWant("to persist data")
.SoThat("I can retrieve this later");
IRepository repository = Service.Get<IRepository>();
storeObjectStory.WithScenario("the single level data object does not implement IStorable")
All code that can fail must be inside an actionstep delegate or lambda
nBehave will nicely catch and report exceptions in code that are part of an actionstep. Code failing outside an actionstep will result in unexpected behaviour.
To improve our previous example we should place the initialization of the repository component inside an actionstep. Since it is part of the setup the appropriate place is the “Given”-actionstep (or a subsequent “And”-actionstep).
Story storeObjectStory = new Story("Store and retrieve an object in the repository");
storeObjectStory.AsA("service in the platform")
.IWant("to persist data")
.SoThat("I can retrieve this later");
IRepository repository = null;
object dto = null;
storeObjectStory.WithScenario("the single level data object does not implement IStorable")
.Given("the data object is a $type", "singleLevelDto", dtoType => { dto = DtoFactory.GenerateDto(dtoType); })
.And("a IRepository service", () => repository = Service.Get<IRepository>())
.When("I store the object under $id and the default datastore", "SimpleDtoTest", objectId => { repository.Store(string.Empty, objectId, dto); })
.Then("I should be able to retrieve it by supplying $id and the type", "SimpleDtoTest", objectId => { repository.Retrieve<SingleLevelSimpleDto>(string.Empty, objectId).PropertyValuesAreEqual(dto); });
How to execute and debug using nBehave Console Runner
A major pain point of nBehave is the difficulty of testing it on a local machine. One way of executing these is by creating or re-using the batch scripts used by your CI-server (in our case it’s hudson). We use a tools/scripts folder in our source tree.
We have a nBehaveRunAll.cmd which will execute all component specs. It accepts an output directory parameter relative to the different project folders. By default it uses the output of the debug (anycpu) configuarion (the configuration chosen in visual studio). The following example shows how to specify the release configuration:
... >Tools\Scripts\nBehaveRunAll.cmd bin\Release
To debug you can specify the nbehave console runner in your project properties:

In Start External Program fill in the path to the NBehave console runner.
The command line arguments consist of 2 arguments:
- The assembly you want to run
- xml=<xml output> parameter. This one is important. Without it you are not executing the tests.
Now you can set breakpoints and start debugging by pressing F5 :)
Keep in mind that these settings are configuration dependent! This means that whenever you change the build configuration (for instance to release or x86 instead of any cpu) you’ll need to reenter these values. Is there no better way you ask? Read on to find out how…
Improving execution and debugging by integrating with NUnit
The above is fine if you are a build server but a lot of developers use resharper or the NUnit (or the Galio Icarus) GUI to run and debug tests. Changing my specs into this made such an impact on the usage of NBehave with our partners, that I created a seperate blog post explaining this. Before a lot of the partners “forgot” to execute, update or correct the executable specifications (BDD tests) because they perceived them as being hard and time consuming. By changing them into NUnit tests this problem was solved.