The act of thinking about how to test code early in the process helps with imagining concrete examples. In addition, this allows the developer to focus on concrete cases, avoiding premature generalizations and optimizations.
âThe simplest thing that could possibly workâ is a phrase you often hear from long-time XP programmers.
Another benefit you get from TDD is rapid feedback on what you produce. Extensive testing is no longer necessary to determine if the code works correctly because there are already tests in place to ensure just that.
eXtreme Programming puts a lot of emphasis on feedback loops. And, among these, shorter cycles that allow you to get quick confirmation are preferable. Of all the XP practices, TDD has the second-fastest feedback loop (second only to Pair Programming), as it provides feedback in a matter of minutes.
Another exciting feature of TDD is the more or less veiled constraint that leads programmers to take smaller and smaller steps. Those who have been doing TDD for a long time surely know the 3 laws of TDD, by Robert C. Martin,, also known as âUncle Bobâ.
In one of his famous articles, Uncle Bob reinforces the TDD process by formulating 3 simple laws:
- You must write a failing test before you write any production code.
- You must not write more of a test than is sufficient to fail, or fail to compile.
- You must not write more production code than is sufficient to make the currently failing test pass.
If you follow this approach, it is clear that you favor incremental development, i.e. writing one test at a time. In this continuous cycle of very short iterations, there is space built in for refactoring. This term is often used as a synonym for âreengineeringâ, but it has a different meaning, at least in the TDD approach.
In this context, in fact, it represents the most important phase of the whole cycle, where the emphasis is on code quality. In eXtreme Programming, thereâs the concept of Simple Design, i.e. the continuous effort to make the code produced simple to evolve.
It is in the refactoring phase that the programmer concentrates on modifying limited portions of code to remove duplication or increase efficiency without changing behavior, which is strengthened by tests that guarantee adequate security. This can be done both in purely practical terms (e.g. introducing a more efficient version of an algorithm), in terms of design, or by modifying or introducing a new abstraction.
TDD was created as a tool for thinking, to increase the focus on small, well-defined portions of code. It helps to proceed in very small steps, adding functionality and value to the software in very small increments in a safe and consistent way. Finally, it enables constant refactoring, one of the most effective practices for keeping software under development in good shape.
TDD as a well-established engineering practice
Today TDD is no longer a novelty. There are many teams and developers who rely on this practice to ensure a sustainable pace in product development. Over time, there have also been several studies that support its validity.
An interesting aspect that frequently emerges is related to the adoption of this practice. The initial learning curve may be more or less steep, but it cannot be ignored. Just as the investment of time in test writing, although several studies shows positive ROI.
The evidence is that once developers have obtained sufficient and necessary preparation to enable the practice, projects end up with good results most of the time. This indicates that they are not successful products that enable TDD, but rather that TDD contributes to the success of projects, products and teams.
Another common objection to TDD is about writing a test first. The usual claim is that there are scenarios where writing tests first doesnât make sense, others where it is very difficult, if not impossible. On the first statement, there is no debate: TDD is not a one-size-fits-all tool, but it has a specific purpose: to support the developer in the design of the software solution.
On the fact that it is difficult -sometimes very difficult- this is also true: oftentimes the defendants here are the underlying code, too rigid to allow the introduction of tests, or the lack of tools. However, both are solvable problems: with a little work, it is possible to facilitate the adoption of the practice with the consequent benefits.
A small example of TDD
How do you get started in TDD? The answer alone would deserve an in-depth study. It is, however, possible to get a brief taste.
Letâs assume that we need to write the software for a cash register. The first functionality requested is related to the item scanner: when a specific item is passed (scanned), e.g. an apple, the system must charge a certain amount, e.g. 50 cents.
The following could be a first User Story: