Nov 27 2011

SpecsFor.Mvc – Acceptance Testing Without Magic Strings

Category: SpecsFor | TestingMatt @ 05:56

Today I published the first preview release of the next member of the SpecsFor family: SpecsFor.Mvc!  SpecsFor.Mvc is a stand-alone library designed to simplify and streamline the creation of acceptance tests for ASP.NET MVC applications.  Read on to find out how easy it is to start crafting automated acceptance tests with SpecsFor.Mvc today!

Test-Driven Development leads to the creation of suites of test cases for a system, but the majority of those tests are likely to be unit tests.  That’s actually a good thing, but it’s still very important to create integration tests to verify the behavior of the fully integrated system.  For ASP.NET MVC applications, you can write tests against your controller actions while providing runtime implementations for required dependencies, but this still won’t fully test your application.  That’s because users are not hitting your controllers directly, they’re going through your UI layer using a browser.  Your integration tests need to exercise the full functionality of the system through your UI.

The Problem With Selenium and Watin

Traditionally, creating automated tests against this outer-most layer of an application has been notoriously tedious and difficult. While tools such as Watin and Selenium will allow you to automate the actions a user performs, they do so in a tightly-coupled way that is neither compile-time safe nor refactor friendly.  This type of coupling often becomes a barrier to making changes in the system, which is the exact opposite of what a good suite of test cases should do.  Tests should give you the confidence to change your system, not serve as yet another point of maintenance friction.  Consider a simple login form for a typical ASP.NET MVC application.  Using Selenium directly, you might craft test cases that look something like this:

There are several problems with these tests.  First, they’re tightly coupled to a particular instance of the application being tested.  Each developer must configure his or her environment to match the expectations of the test cases, otherwise the tests will fail for the wrong reasons.  Second, the tests are filled with magic strings, making the tests quite brittle.  Suppose someone changes the routing in the application.  These tests will now fail because the login action’s URL has changed.  Once again, this is failing for the wrong reason.  The tests will also fail if the login action’s view model is changed.  A common refactoring such as renaming will again cause these tests to fail for the wrong reason.  Ideally, we’d like our tests to only fail when we’ve changed the actual behavior of the login action.

The SpecsFor.Mvc Way

These problems are exactly what SpecsFor.Mvc attempts to solve.  Assuming you are using strongly-typed HTML Helpers (such as EditorFor, TextBoxFor, etc.), you can write strongly-typed tests that are refactor-friendly and that will fail for the right reasons.  The above tests can be rewritten using SpecsFor.Mvc with far less code and far less coupling:

Notice how our tests use a strongly-typed view model for interacting with the page, and how they use strongly-typed expressions both for navigation and asserts.  Also notice what is missing: there is nothing tying the tests to a particular instance of the application.  That’s because SpecsFor.Mvc includes a DSL for configuring your tests.  With this DSL you can host your application in an instance of IIS Express for the duration of the test run.  Here’s the configuration for the above tests:

The examples above all leveraged the core SpecsFor framework, but SpecsFor.Mvc is actually a standalone library that can be used with any testing framework.  While it certainly was designed to play nicely with SpecsFor, you can use it with any other framework as well, including plain-old NUnit or MS Test.

Check it Out!

The current release of SpecsFor.Mvc is tagged version 0.1.0.  It’s still very much a work-in-progress, but I want feedback to help guide its maturation towards the 1.0 release.  Please do me (and yourself!) a favor, and install the NuGet package:

PM> Install-Package SpecsFor.Mvc

(While you’re at it, you really should check out the newest version of SpecsFor, too. Smile )

PM> Install-Package SpecsFor

Here are a few of the things I’m currently considering for the 1.0 release:

  • Documentation. Smile 
  • DSL extensions to support web.config changes.
  • Database/domain configuration and cleanup helpers.
  • Better support for client-side script.
  • Improvements to simplify true test-first acceptance testing.
  • Support for additional browsers.

Leave me a comment below to let me know what else you’d like to see in SpecsFor.Mvc.

Credit Where Credit Is Due…

SpecsFor.Mvc was heavily inspired by a C4MVC session that Jimmy Bogard presented a couple of years back.  I remember thinking about how powerful the ideas he presented were at the time, but I never got around to putting them into practice… until now.  I’ve tried to his approach and enhance it to further streamline and simplify the creation of automated acceptance tests.  I hope the result is useful.

Tags:

blog comments powered by Disqus