A closer look at TDD

The evolution of TDD

TDD is one of the technical practices of eXtreme Programming. The invention of TDD is usually attributed to Kent Beck; one of the first “extreme programmers”.

  • This practice shook the common sentiment of programmers at the time.

  • The practice of testing was already widespread, but no one before had ever suggested writing tests before writing the actual code that needs testing.

  • This act is itself counterintuitive if one thinks of TDD as a testing practice.

TDD was not born as a testing practice but as a software design practice!

TDD as a design practice

  • TDD thus began as a practice related to testing, but it soon turned out that the resulting tests were just a nice side-effect.

  • The point of writing tests before code had much more to do with the design of the code itself than its testing.

  • Writing the test before the code helps the programmer put himself in the shoes of the user, making it easier to create clear software APIs.

  • Using TDD helps make you more comfortable with circumscribing the scope of your code, writing shorter but more focused code, and producing easily composable modules.

Writing the test before the code helps the programmer put himself in the shoes of the user, making it easier to create clear software APIs!

Test-driven development cycle

A graphical representation of the test-driven development lifecycle The following sequence is based on the book Test-Driven Development by Example:[2]

  1. Add a test

  2. Run all tests. The new test should fail for expected reasons

  3. Write the simplest code that passes the new test

  4. All tests should now pass

  5. Refactor as needed, using tests after each refactor to ensure that functionality is preserved

What is done in refactoring?

Some examples of refactoring:

  • moving code to where it most logically belongs

  • removing duplicate code

  • making names self-documenting

  • splitting methods into smaller pieces

  • re-arranging inheritance hierarchies

The simplest thing that works

  • 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.

  • Extensive testing is no longer necessary to determine if the code works correctly because there are already tests in place to ensure just that.

TDD allows the developer to focus on concrete cases, avoiding premature generalizations and optimizations!

One step at a time, nothing more & nothing less!

Another exciting feature of TDD is the more or less veiled constraint that leads programmers to take smaller and smaller steps. 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 code than is sufficient to make the currently failing test pass.

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.

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 show positive ROI.

Objection your honor!

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.

Last updated