unit testing

.NET Musings

Wandering thoughts of a developer, architect, speaker, and trainer


Test Driven Requirements with MSpec

There is a lot of great information on the blogosphere on how to use MSpec (including a very basic intro in this post on this blog) for driving the line of business code from the specifications.  All great stuff, and imho the best way to develop code.  But before you can start developing that code, the specifications need to be defined at an appropriate level of detail.  This post discusses how to do that with MSpec so that the process isn’t wasted on a word document or WIKI that still needs to be translated into specifications in code. 

Everyone knows about the disconnect between the people that write requirements documents and the people that have to turn the requirements into working software.  Typically, there’s not much love lost between these groups.  It’s not that one side is better than the other, but the fact that those groups inherently speak a different language that is the root of the problem.

This is not new.  I have been promoting TDD as a method to facilitate this communication, going through great hoops to convert unit tests into documentation that could then be passed on to the analysts and quality groups.  It works, but it’s a PITA.

Last year, at the St. Louis Day of .NET, I sat in on a great talk by my friend, Lee Brandt, on getting started with BDD, and used MSpec in his demos.  I must say, I was instantly hooked.  The concept that reeled me in completely is the ability to retain the user’s voice in the code through the specifications.  This also has been covered well in other blog posts, so I’m not going into that detail.  What I am going to cover is how this great code feature can be used to facilitate communication and reduce the feedback loop between the developers and the users.

Initial Requirements

This post uses some of the content of the Hands-On lab that I taught for the CodeMash 2010 Pre-Compiler last week in Sandusky Ohio. (Side note: if you’ve never been to CodeMash, you are doing yourself a disservice). The application that the “business” has requested is a small utility to copy references from different locations into the current solution folder.  The requirements come across as the following:

  • The Application will take the target directory and a list of tools as command line arguments
  • The Application will look up the files that are included with each tool from the data
  • The Application will copy the files needed for each tool into a sub directory under the target directory named after the tool

Not nearly enough detail for a developer to fully product an application complete with tests.  Yet not an unusual level of detail for requirements coming from a BA or Product Owner.  Again, I’m laying blame here.  The role of BA is responsible for developing a deep understanding of the business processes, not the technology that will develop the application.  Oh sure, they need to have some understanding, but they should not be expected to be software architects or lead developers.

The agile methodologies all discuss short iterations, cross functional teams, and other methods to reduce the feed back loop for software development.  These are all great things to do, but it still results in code being developed then the differences resolved out, then more coding.

What if we resolve the questions without writing code?

MSpec to the Rescue!

Before the team starts working on the project, I start working with the BA on refining the requirements.  Not unusual, but instead of haggling over a word document, I now use MSpec.  The HTML Report feature is a perfect vehicle for communicating with the business (as long as the It delegates are named appropriately!)

Representing The Core Requirements

For a simple application like this, I start with the given requirements and build a specification class to hold the given requirements.  For more complex applications, each feature gets a specification.  For the Subject, I use a naming convention that allows for the given requirements to bubble to the top of the report.  For this example, I used “0 – Complete Application Concerns”.  For real applications, I use the requirement number and feature name (as identified by the BA).  Why the number before the content of the subject?  For sorting.  When the HTML report is created, it guarantees the order of the Specifications to make it more readable. 

Nothing earth shattering here, except that I don’t use those specifications for writing any line of business code.  They are placeholders for the requirements as they have been given to us.

[Subject("0-Complete Application Concerns"), Tags("0-Complete Application Concerns")]
public class When_Setting_Up_Third_Party_References
//        Establish context;
//        Because ACTION;
    It Should_Get_Target_Directory_And_List_Of_Tools_From_Command_Line;
    It Should_Look_Up_Files_Required_For_Each_Tool_From_Database;
    It Should_Copy_Missing_Or_Updated_Files_Into_Correct_Directories_For_Each_Tool;

Flushing Out The Details

MSpec defines a specification as a single Context (the When implemented as the class name), one Establish (Arrange) delegate, one Because (Act) delegate and one or more It (Assert) delegates.  The idea is that each specification will deal with one actionable unit of code, and each “It” will assert an expected results (or non-result) of that action. I totally agree with this from a pure BDD aspect.  For dealing with BAs and other non developers it can be too much, so I use a slightly different approach for the point-counter-point of refining requirements.  (I then tend to refactor these into more traditional files later in the development cycle.) 

For each of the sketchy requirements in the core, I create one (or more) specification file.  For the first requirement I create a Specification with the Subject “1-Command Line Concerns” and Context “When Validating Command Line Arguments”.  Then (mostly through stream of consciousness) I flush out all of the use cases that I can conceive as It delegates.

[Subject("1-Command Line Concerns"), Tags("1-Command Line Concerns")]
public class When_Validating_Command_Line_Arguments
    Establish context;
    Because ACTION;
    It Should_Return_Help_Text_With_No_Parameters;
    It Should_Return_Help_Text_With_Dash_Help_Or_Dash_H_As_First_Parameter_Case_Insensitive;
    It Should_Return_Help_Text_With_Error_Message_If_Less_Than_Two_Parameters_And_Help_Not_Requested;
    It Should_Return_Help_Text_With_Error_Message_If_Tool_Parameters_Are_All_Empty_Strings;
    It Should_Return_Help_Text_With_Error_Message_If_First_Parameter_Is_Not_A_Directory_And_Help_Not_Requested;
    It Should_Contain_One_Or_More_Tool_Names_Starting_With_Second_Parameter;

I continue to do this for all of the requirements that need to be further defined. Depending on the client, I either put the generated HTML reports on a project web server or print a PDF version and email it to the respective parties.  This provides an effective way to show our understanding of the requirements as the deeper details are evolved, and a rapid method to reproduce the artifacts that most Business Analysts and Project Managers require/desire.

Developing The Application

Once the requirements for the sprint are flushed out, the code gets released to the developers who now have a full suite of specifications to work with in developing the application.  At that point, the files can be split or flushed out as is.  Splitting it out allows for refinement of the specifications to reduce them to one action.  In the format above, the Act and Assert would both occur in the It delegates.  Apply Critical Thought to determine the best approach for this.  I find that for teams that are new to T/BDD it helps to keep the specifications as above and gradually introduce them to the finer points of separating out the Action from the Assertions.  For teams already experienced, go ahead and split the specifications down into the fine grained level that the MSpec framework was designed to handle.

This process has been very effective for me. I’ve only had it in play for a few months and a couple of clients, so things might need to be tweaked moving forward.  But with any process, you need to work on continuous improvement and refinement.  As I discover different or better techniques, they will get posted to the blog as they are vetted.

Happy Coding!

Managed Windows Shared Hosting by OrcsWeb