Reverse the V Model and Test First
- By Jeff Levinson
Test-first development is an approach to software development that focuses on results: Tell me the expected outcome, not the requirements. A number of tools and sub-processes help implement this concept at the technical level. For some development teams, the approach is embodied by test-driven development (TDD) or behavior-driven development (BDD), or at the functional level by tools that use the Framework for Integrated Testing, or Fit. These tools and techniques all try to achieve the same thing -- know what the definition of "done" is before you begin.
An important aspect of test-first development is being able to trace your test cases to your requirements. Team Foundation Server (TFS) 2010, Visual Studio 2010 and Microsoft Test Manager 2010 all play a role in helping implement test-first development because the process breaks down walls between team members.
Software Development Today
Development practices are always evolving, but the V model of software engineering continues to represent the traditional relationship between the development lifecycle and testing phases. As it stands, the V model starts with subjective development goals on the left side of the model and then objectively verifies those goals going up the right side of the model: Unit Tests, Function Tests, and System and Integration Tests. The problem is that requirements -- and our breakdown of requirements -- are open to interpretation. But what if we were to reverse the V model: test first and then verify that the development goals are met? This approach solves the problem of ambiguity in software requirements because tests either pass or fail -- there are no maybes.
In order to successfully reverse the V model, you must have complete traceability. This capability has to include traceability from all work items (requirements, tasks and test cases), and traceability to code. Where do you start? While forming high-level requirements, you start by creating acceptance criteria. Acceptance criteria are high-level test cases without detail. The idea is that, if the software or feature meets the criteria, it will be accepted by the customer. This approach helps to alleviate the first problem teams run into: poorly defined business goals and features, or some that can't be tested.
In TFS this is trivial: Create a Requirement or User Story Work Item Type, and then immediately afterward create a linked Test Case and fill in the title, which should describe the test. Optionally, you can capture the acceptance criteria in the description of the requirement (because the criteria are the description) and then create detailed test cases to support the criteria.
Customers can either say that the acceptance criteria are OK or not -- and if they aren't, they need to be revised until they are OK. This is the start of your traceability structure. It's also the start of getting customers to commit to testable features. These high-level requirements need to be expanded upon so that the actual details of the acceptance criteria are understood.
From Scenarios to Tasks
The next step is breaking down the scenarios into tasks and working on those tests. The best examples of this are TDD and BDD. Each of these methodologies makes developers think about the end outcome before they start writing code. This lets you break down the scenario modularly and ensure that each piece of it is testable. Whether you do TDD or BDD -- or even write unit tests after the fact -- you need to start thinking in terms of testability. Once you figure out what the software has to do to pass the test cases, creating a task list is easy -- and it ensures that you don't add code you don't need.
Visual Studio supports a variety of unit-testing frameworks, including its own built-in testing framework, and you can trace your unit tests back to your requirements (see "Take Unit Testing to the Next Level," March 2011). Testers can actually execute any type of test a developer creates without ever having to open up Visual Studio. Whether these are coded UI tests, Web performance tests, load tests or unit tests, the tester can execute them. Writing unit tests first does have advantages in some circumstances, but the important part is making sure you understand what the software has to do.
Where You Will Be Tomorrow
With the Reverse V model, you can follow the process or steps down one side of the model and be done when you hit the bottom: There's no need to go back up the other side. You still have to go through the process of testing, but the chances that a tester will find bugs are greatly decreased because all of the criteria for a successfully built method, scenario or business goal are known by the developer up-front.
Test-first development allows you to do the minimal amount of work to get the job done: no gold-plating, no poorly written requirements and a definitive definition of "done." Quality is built-in -- you don't write code until you know what it has to do.
Jeff Levinson is the Application Lifecycle Management practice lead for Northwest Cadence specializing in process and methodology. He is the co-author of "Pro Visual Studio Team System with Database Professionals" (Apress 2007), the author of "Building Client/Server Applications with VB.NET" (Apress 2003) and has written numerous articles. He is an MCAD, MCSD, MCDBA, MCT and is a Team System MVP. He has a Masters in Software Engineering from Carnegie Mellon University and is a former Solutions Design and Integration Architect for The Boeing Company. You can reach him at Jeff.Levinson@nwcadence.com.