TDD Is Not For New Projects

‹ Bob Chase
January 2024

How I Work

When I'm working on a brand new code base, two things are true:

Test driven development—TDD—is a coding practice that promotes writing tests before writing code. When things are changing rapidly and randomly—like in a new code base—then the tests will break frequently and may have to be re-written or thrown away as the code morphs and changes.

I don't want too many tests in this stage of development, because keeping the tests in sync with the changing code base creates unnecessary work.

During this early phase of development, I tend to have a really good understanding of how the code works and how the code base is evolving. This provides me with an intuitive sense of what will work and what might be wrong when it doesn't work. In other words, my brain is a pretty decent test suite.

When TDD Makes More Sense

If a code base is unfamiliar to me—either because I've set it down for a while, or because I've never worked with it—it makes sense to create tests which validate assumptions about the operation of the code and which anticipate the changes that I'm planning to make.

Maybe these new tests are throw-away, or maybe they can be incorporated into an existing test framework Learning the particulars of the automated testing style of a code base in order to write a test so that you can then write the code is sometimes too heavy a lift. Writing the automated test afterwards is often an easier path. I don't think that matters.

What does matter is:

Neither of these things require that a test is written before the change is made. Neither of these things require that the new test is automated.

So, while unfamiliar code is a reasonable place to use TDD, it certainly doesn't mean that TDD is a good approach, or a necessary approach. It's just an approach.

When I Do Use TDD

In practice, So it's fair to say that I don't use TDD. Sometimes I write my tests while I'm writing my code—particularly when I want to validate the new code against a number of situations. Most of the time I write tests to lock-down the expected behavior of code that I've mostly—or completely—finished.