One of the neat things I saw at the Agile conference was a short demo of RSpec and RBehave. Intrigued, I did a quick search and found the .NET equivalents: Behave# and NSpec.
Note: I'm not sure I completely understand the differences between xSpec and xBehave as they both quote Behaviour-Driven Design as their goal. I think that the Behave libraries are just a way to change the nomenclature of xUnit from 'test' to 'behaviour'. The Spec ones are about writing user stories in a sort of DSL that a product owner or PM could understand.
Since developer stories can be user stories, I thought it would fun to use Behave# to implement the Stack example from Jim Newkirk's Test-Driven Development in .NET book. Here's what I ended up with (apologies for the formatting - it's much easier to read inside VS):
Story: Basic stack operations
Narrative: As a developer I want to peform operations with a stack So that I can save my data
Scenario 1: A brand new stack Given a stack I created When I query its state Then it should be empty
Given a stack I created When I push a single object And I query its state Then it should not be empty
Given a stack I created When I push a single object And pop the object And I query its state Then it should be empty
Given a stack I created When I push a known object And pop the object Then the two objects are equal
Given a stack I created When I push three known objects And pop each one Then all three objects are the same
Given a stack I created When I pop an object it throws an exception: System.InvalidOperationException Then
Given a stack I created When I push a single object And call top And I query its state Then it should not be empty
Given a stack I created When I push a known object And call top Then the two objects are equal
Given a stack I created When I push three known objects And call top Then the last item is equal to the top one
Given a stack I created When I push a known object And call top repeatedly Then all objects are equal to what was pushed
Given a stack I created When I call top it throws an exception: System.InvalidOperationException Then
Given a stack I created When I push a null object And I query its state Then it should not be empty
Given a stack I created When I push a null object And pop the object Then the returned object is null
Given a stack I created When I push a null object And call top Then the returned object is null
1 passed, 0 failed, 0 skipped, took 1.15 seconds.
So is it useful? Like most things, there are situations where it's appropriate and others where it's not. I'm starting with a contrived example to begin with, and so not demonstrating its full usefulness. Regardless, there are a few points I'd like to make after playing with it for a while:
On the (possibly) less good side of things:
Top()
[Test]public void PushTopNoStackStateChange(){ string pushed = "44"; stack.Push(pushed); for(int index = 0; index < 10; index++) { string topped = (string)stack.Top(); Assert.AreEqual(pushed, topped); }}
I'd like to see some more real world examples of this being used; this could be a powerful tool in the right circumstances. And of course as the library is enhanced, some of the things I've talked about may become more feasable.