Test Driven Development promises serious results for teams, organizations, and customers, including improved quality and faster delivery. The promises of TDD, or any of the other variants of test-first development techniques, are at least partially offset by costs and potentially tragic side effects when it is done poorly.
The positive impacts explored in earlier articles on TFD and TDD include:
- Fewer Delivered Defects: Testing finds defects; more timely testing is apt to find defects before they get delivered, and better testing tends to find more defects.
- Communication: The process of developing tests requires conversation, which is at the heart of Agile techniques. Better communication yields software better targeted to the organization’s needs.
- Better Tests: TDD (or any of the test-first techniques) ensures that the tests are reviewed early and often, which helps to ensure only what is needed is tested.
- Code Quality: By only writing as much code as is needed to pass the test, TDD will ensure that functionality remains as simple as possible. This will yield higher code quality because there will be fewer chances to embed defects.
- Less Dead Code: Refactoring the code and design is a tool to remove dead code-making programs more readable and therefore easier to maintain.
In addition to the improving quality, reducing and removing defects more effectively, TDD delivers a number of additional positive psychological and quantitative benefits that include:
- Improves Motivation: Teams that deliver higher quality functionality are often more motivated. Giovanni Asproni in his paper Motivation, Teamwork, and Agile Development (also published in Agile Times, Vol. 4, February 2004) shows a link between the standards of excellence Agile requires and supports using techniques such as TDD produce more highly motivated teams. Simply put, when teams feel they are delivering higher quality products they are more motivated and therefore deliver more high-quality product in a virtuous cycle.
- Facilitates Being Agile: TDD is effective when teams break work into smaller chunks, define what done looks like, develop something tangible and then get feedback. The empirical cycle built into effective TDD is at the heart of learning to practice Agile. There has been a long-running argument in the Agile literature about the difference between doing Agile (just following the ceremonies and practices) and being Agile (getting and feeling the benefits from doing Agile). TDD provides those that are “doing” Agile with the feedback that provides a connection to tangible benefits from Agile pushing them up Maslow’s Hierarchy towards self-actualization.
- More Effective than Classic Debugging. Back in the dark ages, developers would develop code for some period of time and then assume the code compiled or built (the act is a rudimentary form of debugging) would determine how to unit test the work and then test it. Right after the “test it” steps the fun of pouring through code that may have written weeks or months in the past would begin. Debugging was usually painful and fraught with its own errors (I have blotted most of the pain from my memory). TDD and other TFD techniques start with defining how the code will be tested and leverage Agile shorter cycle times to reduce the potential of both not testing everything AND not remembering what you actually did and where when you changed the code.
- Functionality Can be Delivered Sooner. TDD ensures that functionality we are writing is tested and can be demonstrated and potentially delivered. The goal of most Agile techniques is to get the functional code in front of customers so they can provide feedback and potentially use the functionality. TDD makes sure that developers know what they are building and know how they will prove it works before they write the first line of code.
TDD is part requirements development, part testing technique and all the while a collaboration tool to ensure the team focuses on delivering high-quality functionality.
Next, we visit the other side of the TDD discussion.