NSpec merges with NBehave!
I am pleased to announce that Tim Haughton has agreed to join his NSpec project with NBehave!
So what does this mean for you the developers? Well it means that you have one OSS project team supporting multiple BDD frameworks for the .Net framework! Think of it more as a centralized project for the many facets of BDD in the .Net community.
But Joe I have invested allot of time in setting up my NSpec test. Not to worry. We are firmly committed to giving the community options!
What we have done is break up the NBehave project into the following assemblies.
- NBehave
- NBehave.Spec <–This is basically the core NSpec assertion framework
- NBehave.Performer <–Contains the fluent interface behavior constructs and references NBehave.Spec (Think JBehave)
- NBehave.Narrator <– Contains the story builder fluent interface and leverages NBehave.Performer and NBehave.Spec
- NBehave.Runner <– Global console runner capable of running any test that uses Spec, Performer, or Narrator.
This is really great because now we get to utilize our own assertion framework in the creation of all these new projects (as seen below). Which is essence should create a better framework for everyone.
using System;
using NBehave.Spec.Framework;
using System.IO;
namespace NBehave.Runner.Console.Specifications
{
[Context]
public class ParseGoodArgumentsSpec
{
const string assemblyName = "NSpec.Console.exe";
const string xmlFileName = "Bob.xml";
const string txtFileName = "Bob.xml";
const string assemblyArg = "/assembly:" + assemblyName;
const string outputArg = "/output:" + xmlFileName;
const string behaviourOutputArg = "/behaviourOutput:" + txtFileName;
Arguments args;
[SetUp]
public void Setup()
{
string[] argArray = new string[] { assemblyArg, outputArg, behaviourOutputArg };
args = Arguments.Parse( argArray );
}
[Specification]
public void ShouldParseAssemblyFileName()
{
Specify.That( args.Assembly ).ShouldEqual( Path.GetFullPath( assemblyName ) );
}
[Specification]
public void ShouldParseOutputFileName()
{
Specify.That( args.Output ).ShouldEqual( Path.GetFullPath( xmlFileName ) );
}
[Specification]
public void ShouldParseBehaviourOutputTextFileName()
{
Specify.That( args.BehaviourOutput ).ShouldEqual( Path.GetFullPath( txtFileName ) );
}
}
[Context]
public class ParseBadArgumentsSpec
{
const string badArg = "badstring";
Arguments args;
[SetUp]
public void Setup()
{
args = Arguments.Parse( new string[] { badArg } );
}
[Specification]
public void ShouldReturnNull()
{
Specify.That( args ).ShouldBeNull();
}
}</p>
This also allows the developers to utilize different aspects of BDD. You can use NBehave.Spec.Framework for you lower level testing and for your Story and Behavioral Domain test you can use NBehave.Narrator.Framework. Look at how by simply adding the Spec framework increased the readability of the Narrator Story framework (see below).
using System;
using NBehave.Narrator.Framework;
using NBehave.Spec.Framework;
namespace TestAssembly
{
[Theme("Account transfers and deposits")]
public class AccountSpecs
{
[Story]
public void Transfer_to_cash_account()
{
Account savings = null;
Account cash = null;
Story transferStory = new Story("Transfer to cash account");
transferStory
.AsA("savings account holder")
.IWant("to transfer money from my savings account")
.SoThat("I can get cash easily from an ATM");
transferStory
.WithScenario("Savings account is in credit")
.Given("my savings account balance is", 100,
delegate(int accountBalance) { savings = new Account(accountBalance); })
.And("my cash account balance is", 10,
delegate(int accountBalance) { cash = new Account(accountBalance); })
.When("I transfer to cash account", 20,
delegate(int transferAmount) { savings.TransferTo(cash, transferAmount); })
.Then("my savings account balance should be", 80,
delegate(int expectedBalance) { Specify.That(savings.Balance).ShouldEqual(expectedBalance); })
.And("my cash account balance should be", 30,
delegate(int expectedBalance) { Specify.That(cash.Balance).ShouldEqual(expectedBalance); })
.Given("my savings account balance is", 400)
.And("my cash account balance is", 100)
.When("I transfer to cash account", 100)
.Then("my savings account balance should be", 300)
.And("my cash account balance should be", 200)
.Given("my savings account balance is", 500)
.And("my cash account balance is", 20)
.When("I transfer to cash account", 30)
.Then("my savings account balance should be", 470)
.And("my cash account balance should be", 50);
transferStory
.WithScenario("Savings account is overdrawn")
.Given("my savings account balance is", -20)
.And("my cash account balance is", 10)
.When("I transfer to cash account", 20)
.Then("my savings account balance should be", -20)
.And("my cash account balance should be", 10);
}</p>
</p>