In part one, I introduced the PlaylistShare project, created some initial user stories, defined the acceptance criteria and created a template for writing executable specifications. In this part, I am going to write some executable specs for viewing playlists and implement the behaviour to make them pass. You can download the source code at the end of this post.
There a couple of approaches you can take when writing specs for an ASP.NET MVC user interface. Either you can run them directly against the UI from inside a browser, using a tool such as WaitiN. Or, you can drop in just below the UI and run the specs against the controllers. I prefer running them against the controllers as they run much faster and are not susceptible to changes to the HTML elements. However, you may find some aspects are better specified using a UI testing tool, such as behaviour that relies heavily on client-side scripting, which the controllers know nothing about.
I will be starting with the executable specification template I created in part one:
The first scenario we are going to implement is:
Story: Listener views playlists
As a playlist listener, I can view a list of playlists that have been submitted, so that I can find a playlist I might enjoy.
Scenario 1: Viewing a list of playlists
Given a list of playlists
When the listener views the playlists
Then should display a list of playlists
And playlists should be ordered by date submitted from newest to oldest
First, lets create a new ASP.NET MVC application and add a PlaylistController to give us a subject to work with.
Now that we have a controller, let’s specify the first outcome of the scenario.
The outcome states that a list of playlists should be viewed on the page.
the_view_model is a property on the spec base class that wraps calls to ProductsController.ViewData.Model. This makes the code slightly more readable. We can use ViewData.Model on the controller to pass data back to the view. In this case we want to pass back a list of Playlist objects.
You will notice I have used a method called should_be_equivalent_to to verify that the_view_model contains the same elements as playlists. This is an extension method defined in a SpecificationExtensions class I have added to the project. This class contains some helpful extension methods that wrap-up calls to NUnit assertions. This enables us to assert conditions directly on the objects, producing slightly more readable outcomes. Again, this is a personal preference and you can use ordinary Assert calls if you wish.
Running this spec should result in a failure, as we are not yet returning any playlists from the Index() controller method. We need to provide the controller with our list of playlists. To do this, we need to somehow pass a list of Playlist objects to the controller. The best way to do this is to use Dependency Injection and Mocking to pass a Repository containing our Playlist objects into the controller. Woah! Sounds complicated. But, it’s actually quite simple…
Let’s modify the PlaylistController to take an IPlaylistRepository and initialise a field in the constructor.
Now we need to pass an instance of this repository when we create the PlaylistController in our specs. To do this I am going to generate a stub using RhinoMocks. This creates a runtime implementation of the IPlaylistRespository that we can pass into the controller.
The setup_scenario method gets called right before create_subject, so we can use this to create any dependencies before the PlaylistController gets instantiated. Any scenarios can create additional context by overriding the setup_scenario method.
Now we need to add a GetAll() method to IPlaylistRepository that allows the PlaylistController to retrieve a list of Playlist objects.
Back in our specs, we can now tell the stubbed playlist_repository to return some Playlist objects whenever the GetAll() method is called.
Our spec should now be passing! We have now confirmed the controller is passing a list of playlists to the view to display on the page.
So, let’s write an assertion for our next outcome: “playlists should be ordered by date submitted from newest to oldest”. Here we verify that the Playlist objects sent to the view are ordered by date-submitted in a descending order.
For this to compile we need to add a DateSubmitted property to the Playlist object.
I have created a helper method called should_be_ordered_by_descending that will verify that the playlists are ordered correctly. It’s really useful to create extension methods for complicated assertions to better explain what is being verified.
We can now make this spec pass by using LINQ to order the list of Playlist objects in the controller action before they are returned to the view.
Here is the output from the Resharper test runner:
Using these naming conventions means that if a spec fails, it’s easy to identify what behaviour is causing the problem. You also get clear, concise, executable documentation that describes how your application behaves.
You might have noticed that I have been implementing the playlist controller without even running the web site. By implementing the controller first, we can focus on the core behaviour of the application without being concerned about how it is presented. In the next part, we will create the view that displays the playlists on the page.