Tuesday, March 02, 2010

ALM Practices Part 3: Unit Testing & TDD

What is it?
In essence, Test Driven Development (TDD) is a practice in which the interface and the behavior of a component is designed while writing a unit test. In other words, you typically start writing a test case and define the exact members, behavior and names on the fly. In fact, the word Test in TDD is misleading at the least, because the whole practice is really a design methodology that promotes creating testable loosely coupled software. And since this is going to be a difficult endeavor without applying the right design principles, you usually end up with a maintainable and extensible system which by incidence also includes a high code coverage. Without TDD, these same goals are very difficult to reach.
Why would you do that?
  • Because a seemingly small chance might have unexpected side effects caused by errors in the design or an solution that is too complex.
  • Because the simple practice of writing a readable unit test forces you to create code that is testable.
  • Because you will discover new scenarios while writing those tests that you usually do not find until you start running into bugs while testing the actual system.
  • Because a readable unit tests helps other developers to understand how to use the component’s API.
  • Because a set of well written comprehensible unit tests prevent you from long hours into the Visual Studio debugger, both during initial development as well as during an extensive system test.
  • Because you will be the first user of your component’s API which should stimulate you to really think carefully about how other users should use the API.
  • Because having a high coverage should encourage you to proactively refactor and improve your code base while adding new features.
What’s the bare minimum you need to do?
  • Write Intention revealing unit tests for all business critical functionality, technically complex code, components that are reused often and parts that are difficult to test manually.
  • Make sure that test code complies to the same high standards as production code. Test specifications are first class citizens as well.
What’s the usual thing to do?
  • Use TDD for everything you create and apply the red-green-refactor mantra rigorously.
  • Use the tests as your starting point for Peer Reviews. Every TFS task, user story or other functional work item should be associated with a set of tests that define the expected behavior of a component. As a reviewer you first review those tests to make sure the behavior matches your expectations, before you move on to the actual production code.
How do you do that?
  • Read all TDD-related articles pointed to from this blog post written by Jeremy D. Miller, and the article Principes of Test Automation from the book xUnit Patterns. These should give you a kick start on unit testing and TDD.
  • On your project site or dashboard, explicitly state which projects within your Visual Studio solution should be fully covered by unit tests and why (not).
  • Active Code Coverage and strive for a minimum of 90% coverage.
  • Configure a Daily Build that runs all unit tests and use the Quality Indicators report from the TFS MSF Agile process template to monitor the code coverage and the success rate of your tests over time. This report also shows the amount of code that still changes, which is very helpful when the team approaches an important deadline.
  • Configure your build in such a way that it automatically creates a bug upon any test failure and make sure the first team member that enters the office feels responsible for fixing that.
  • Automatically deploy test data required by your integration tests (unit tests that require a database) using a Database Project.
  • Consider reading the entire xUnit Patterns book. It contains invaluable resources on the organizational, technical and practical aspects of unit testing in large teams.

No comments: