I wanted to take some time to put down my thoughts and findings about the framework, BDD in general and some other stuff I have ran into.
BDD – Behaviour driven design
I don’t want to go into explaining BDD since it's been done several times before (I can really recommend the last Steven Sanderson post – excellent!) in a much better ways than I could ever do. Go on and read them if you want – I’ll wait right here.
But I can share some aha-moments and experiences that has surfaced for me when preparing and doing the workshop.
It’s not in the tool
First, as a colleague told me yesterday: “It’s not in the tool”. First and foremost I think that BDD is a great way to discus and formalize the requirements together with your customer. I know that Gojko Adzic has formalized this into workshops where you flesh out the acceptance criteria together and I really like that idea.
That promotes an ubiquitous language and helps you to preserve that language when turning requirements into code.
A great way to get hold of behavior is to ask for example scenarios. These fit very well as the scenarios we’re writing when doing our features and scenarios in BDD. That is so much clearer and crisper than sending documents back and forth.
Implementing outside in
Finally when it comes down to implementing the scenarios you get a nice outside-in approach to your testing. Of course this was where I started. Being a programmer I was eager to see how to use this to write code. And as you might know that was where I started glancing on SpecFlow and BDD.
Starting from the acceptance criteria's or scenarios I was amazed how a design was pulled from the text and turned into code. Just-in-time so to speak
SpecFlow is supporting Gherkin 100 %. Gherkin is the language that is used in the Ruby BDD framework Cucumber. And SpecFlow is a great way to use standard Cucumber/Gherkin BDD-style on the .NET platform. That mean that you can read and understand any Cucumber literature be if for the Ruby, Java or the .NET platform.
Gherkin is a DSL (Domain Specfic Language) for writing user stories and scenarios, with the well know trio of: Given/When/Then. And as it is a formal language it has it’s own best practices and trick that you’ll need to pick up before being productive. Here is a great article series that take you from basic to advanced:
Earlier on I said “It’s not in the tool” but of course you will need one. The tool I have used is SpecFlow. The thing that I like with SpecFlow is that is 100% Gherkin compatible and doesn’t introduce any funky syntax to go to code. Ok, it’s cool – but come on: “= () => “ – who reads stuff like that?
Just as in standard Cucumber you also get stub code for your steps, when you run the scenarios the first time. I love that feature since it helps you along in a very nice way.
The binding between your scenarios and the code is done in a class with step definitions. The methods are decorated with attributes (Given/When/Then) that instructs SpecFlow which method to run for a certain step.
Here we found out some problems and opportunities:
- The steps can be located in any class with the Binding-attribute. There is no connection between the scenario and the binding. It just a bunch of steps. If more than one attribute match a step in a scenario SpecFlow will throw and exception and inform you about it.
- SpecFlow supports that you can have more than one attributes (two different [When]’s for example) on the same method. Using this technique you could have very specific strings in the attributes and still have them call the same method.
- In the attributes for the steps you can use regular expressions to be able to send different data to the same step. This could also be a bit confusing since some regular expressions will match a “bigger” portion of a string than you first might have guessed. This feature is standard Gherkin.
- Another, and maybe better way, to send data is the table construct in Gherkin. I found this a much better way to keep your scenarios clean and less sensitive for change.
The syntax for tables are a bit special though:
- You need to have space after the pipe (|) sign.
- The table (of course) need headers, so that you can reference different columns in your code. The first line is the header.
- A thing that confused me, but is the way it has to work, is that a pending step will stop the execution of the rest of the scenario.
All in all I think SpecFlow is an excellent choice when doing BDD on the .NET platform.
A bumpy ride – bugs and embarrassing moments
As me and Måns Sandström created the code and lab for the workshop we ran into more bugs in tools and frameworks than I ever seen… None of them had to do with SpecFlow and some of them had to do with me…
- We used Resharper 5.0 Beta (different versions). I cannot imagining Visual Studio without Resharper, but this time I started to soon. Thanks to some great support some of the issues were solved during the weeks we developed the code.
- I still cannot get Resharper to run the test from the .feature-file. “No test found in file” is the response that I get from Resharper for that… That worked for a while but has disappeared now. I haven’t reported a bug for that yet – not sure if it’s in Resharper or in SpecFlow.
- I also reported a bug in Moq – but that was completely my fault. And I have to endure the embarrassing “user fault” in the report…
That had to do with me using an overload and forgetting do an Verify for the overload.
So all in all – I’m hooked. I will sure try to get some more BDD approach to the project I’m in. I up to now I haven’t seen a better tool than SpecFlow for the job.