As part of my preparations for two different presentations on
BDD I found myself in need to create an example. And
I have read loads of them (this is a great one by
Sandersson). I have also read some others that
emphasized the outside-in style that I liked so
much, but nothing in the .NET sphere.
Finally I’ve tried the
story telling approach to writing blog posts before
and it was fun and well-received. So here is a story on outside-in
development with SpecFlow and
(Disclaimer – I will not go in to details on web automation or ASP.NET
Getting the story straight
Marcus entered the office with extra spring in his step. New project and
he would finally get around to try out the outside-in development style
in a real project. It sounded great – but could it really work? He went
straight to Tobias, the project manager:
“I’m ready! Where is the specifications?” – he sounded eager… almost to
”Well, calm down…. For now we have a small side-mission for you. We need
you to extract the tasks at hand from our database. It will be a simple
application but it will be great to start learning the new work
approach” – Tobias did his best to deliver the quite disheartening news
to his eager developer.
“OK… I’ll do it” – Marcus was still eager but not as much
”Great! We simply want a list of all the features in our database that
isn’t done yet. And there is a service that will deliver them to you.
I’ve written the first feature already” – Tobias tried to ride the wave
of enthusiasm. He showed Marcus the feature:
To know which features that are up next
As a developer in the team
I want to see a list of all features that isn’t done
“OK, but what about the done ones? No one ever want to see them?” –
“By George! You’re right! We might need to tweak that story a little….
Hmmm how about:”
In order to see a list of the features of our application and their
As a developer in the team
I want to see a list of the features, sorted on their different status
“That isn’t very clear…” – Marcus said plainly. “Could you talk me
through a scenario?”
”That’s EXACTLY what we will do now”
They talked for a while and came up with this scenario:
When I navigate to the homepage
Then I should see a list of features are not done yet
“We might need to add a scenario for when I show the features that are
done also. How about this?”
Given I am on the homepage
When I click the radio button for “Show done features”
Then I should see a list of features that are done
“That looks alright by me. Now go code! You can get hold of the service
to get the items, from Thomas who created it yesterday” – Tobias sent
Marcus off to get on with more important stuff.
Setting up the feature
Marcus fired up his Visual Studio. Oh the new 2010 already felt like
home, he couldn’t even remember the 2008 version.
The first order of business is to create the solution. Marcus created a
blank solution called “Marcusoft.OutsideIn.FeatureDemo”. He then added a
class library for his Specification. Executable specifications! It still
sent shivers down his spine.
The class library was called Marcusoft.OutsideIn.FeatureDemo.Specs and
has references to TechTalk.SpecFlow.dll and the nunit.framework.dll.
And of course deleted Class1.cs. “Why is that always created?” – he
thought as he hit the delete-button. Hard!
Also Marcus put these reference in a lib-folder, in the top
solution-folder. “That’s always a good think”, he thought, “then
everybody will get the correct version”. Now Marcus created two folders
in the Spec-project; Features and Steps. The Features will contain the
Gherkin-features and the Steps-folder the step definitions.
Now the feature could be added. Marcus added a SpecFlow-feature to the
Features-folder. He called the feature “BrowseHomePage.feature” and
added the following content:
Yeah! That looked good. “Let’s run that and see where it leads us” – he
said to himself and ran the tests.
It failed! Or actually it was inconclusive. Which was no big surprise to
him, although he couldn’t help but to feel that there was a lot of work
### Keep in step all the time
The exception from SpecFlow was very informative and helpful. It even
gave him some code to get started with. This is what it looked like:
“Sooo… I need to create some steps” – Marcus promptly copied the
WhenINavigateToTheHomepage-method and added a new class
“HomePageSteps.cs” to the Steps folder. He then pasted the code into the
class and ran the test again.
But he was very disappointed to see the same failure… “Aaaah the class
of course need to be public… And apparently need that Binding-attribute
on top. Lets add that.” He did so and ran again.
“Yup – that was better” – he paused. “Kinda… I don’t do what the step
definition says…I’m supposed to navigate to the home-page. But I haven’t
got a site yet. So that is my task at hand now.”
automate the browser” – Marcus said and downloaded and referenced
Watin.Core.dll and Interop.SHDocVw.dll.
“And now all I have to do is to navigate to the page in question. Hmmm –
I know how to navigate with Watin… but where to… I start off by ripping
part of Steven Sanderssons blog post to get a working infrastructure
going.” With that Marcus created the following web browser class:
“Great” – Marcus thought to himself “ with this in place I can change
the app.config file to point to the root of my application.” He added an
app.config that contained some settings and a RootUrl-key.
Marcus went on to add navigation in the When-step like this:
And with that in place Marcus ran the tests again. A browser flashed
before his eyes… It was an Internet Explorer but he couldn’t see the
content. Also when he checked the test run results he could see that
they were still inconclusive. But this time the When-step had passed:
But the step passed but didn’t do the right thing. There is no website
there. Hmmm – I’ll better add the website and see that it still works.
### Creating the web
Marcus added a new ASP.NET MVC 2 project to his solution;
Marcusoft.OutsideIn.FeatureDemo.Web. He started by removing all the
membership stuff. That wasn’t needed in this project.
Marcus then picked up the url from the project properties web-tab. The
url pointed to [http://localhost:49323](http://localhost:49323/) which
was confirmed when I started the application and got the well-known
default page for an ASP.NET MVC site:
He stored that setting in the project, by setting the Specific Port
radio button on the Web-properties for the ASP.NET MVC project. He then
added that url to the RootUrl-key in app.config of the Specs-project.
Marcus ran the tests again. The same behavior… The browser flashed and
he could see anything. In order to see it work Marcus commented the
\[AfterScenario\] in the WebBrowser-class. Now the browser stayed open
and Marcus could see the same page being showed. On the same url even.
With a smile on this face he thought: “Progress” and went on to copy the
method for the Then step definition.
### Then! Why not now?
Marcus added the then step he copied from the test result, to the
HomePageSteps and ran the tests again. The test are still pending but
not with a missing step:
Again Marcus needed to add the automation that would actually do the
things that the step said: check that no listed feature has status Done.
The simplest solution to that for now is to search for the phrase
“Status: Done” on the page. Marcus also added some checks that the other
statuses is shown. The code for this became something like this with the
use of the excellent
When the test were ran this time they fail. Yes failure is our friend –
no we can write some production code:
Let’s write an
Now some code was needed in the web application. Marcus needed to get
the page working and listing the features… which in turn meant that he
had to pull the features from the service that Thomas had made.
“Let’s start with the controller. I need to make sure that I can get
hold of the data from the service through the controller to the views".
Let’s write some tests for it” – Marcus said to himself. He added a test
project, referenced nunit.framework.dll, the excellent NSubsiture.dll and the FeatureDBWrapper that he had
got before. The FeatureDBWrapper exposed a simple interface like this:
Marcus started fleshed out the structure of the
HomeController and it’s index-method. Still amazed on how well this
process works he found himself:
- Creating some fake data with NSubsitute
- Passing the IFeatureDBWrapper substitute into the HomeController,
which in turn (and with the help of Resharper in a few keystrokes)
made the HomeController take an IFeatureDBWrapper as parameter
- Verify that the right method was called and returned the faked data
Here is the test and the controller that was test-driven in the
### Better check with the specifications
“Alright – that worked out just fine! Let just run the Specs to be
sure…” – Marcus thought and hit Run for the tests. They failed. But not
in a good way.
“Actually that is quite strange when I think of it” - Marcus thought.
“Because that injected FeatureDBWrapper to the HomeController should
have broken the site.” He tried to run it in the browser. And yes – it’s
broken. It fails with “No parameterless constructor found for this
object”. Just as Marcus suspected.
“But (!) the When-step of my Spec ran just fine. I better add a check
that I have arrived on the right page to that step” – Marcus thought.
Here is the extension:
And now it fails as it should. Marcus went on to add that title to the
View. “I’ll hardcoded into the view. It will never change” – he laughed
to himself when the sentence passed through his head. He left it
Alright – not on to fix the injection problem. I’ll go with Ninject for
this. He added Ninject
and the following code to his Global.asax.cs:
“Back to the specs” – Marcus said out loud. He ran them and they failed
but this time as he expected. On Assertion when not finding the
“Yeah, that’s right! Haven’t created a view yet”
### View – you want to see something?
Marcus muttered to himself… “I am no designer…Pixel shufflers… where are
they when you need them?” And he created this rather ugly view:
that looked like this when rendered in the browser:
Marcus looked at his watch. Not even lunch yet… “Maybe I’ll start
writing the second scenario now. It will probably be faster” – he dived
And with that we leave Marcus and the fantasy world he is in.
In this, very long blog post, I wanted to try out to be driven by the
specifications outside in to working code. It felt very natural and had
a nice “where do we go now… HERE”-feeling to it. I hope that you could
download the code here.