What makes you think your tests are error-free?

Nothing. I don't have any confidence in my ability to write error-free tests.

Under the category of “half-considered Test-Driven Development criticism that actually demonstrates the value of TDD”, I saw this comment on LinkedIn:

If someone can’t write error free code, what makes you think their tests are error free?


All else being equal, I don’t have any confidence in my ability to write error-free tests.

So what I need is some sort of mechanism that helps me validate that my tests are correct.

What would such a mechanism look like?

Well let’s first consider: What is the purpose of a test?

Can we agree that the purpose, or at least a purpose, of a test, is to produce a signal when the code it’s testing doesn’t behave properly? If the code misbehaves, but the test doesn’t give us a signal, then it’s not a very valuable test. If we can agree on this, then one way to gain confidence that a test does the right thing is to see it produce that signal.

How could we do this?

One way would be to introduce a bug into our code, and see if the test catches it. Comment-out some key logic, or change a variable name, or whatever. Mutate your code in some way that causes the test to give us that desired signal. This is a good indication that the test is doing something useful. (You can automate this process, too, using mutation testing).

Well, TDD takes this just one tiny step farther, and writes the test before writing the code. This way we have an indication that our test is valuable even before we write the code.

Of course that test we write before the code could be wrong. But this helps catch that, too. Because if we write a broken test, then write correct code, and the test continues to indicate a problem, we need to investigate.

We might end up writing bad code to match the bad test. I’ve definitely done this before. So it’s not a fool-proof technique. But that doesn’t mean it’s not helpful.

I’ve far more often seen bad tests written to match bad code, than bad code written to match bad tests.

In this sense, TDD serves as a checks-and-balance system; a low-fidelity checksum; a way to validate that code and test match. It’s not sufficient to ensure correct code (or correct tests), but it sure helps me catch a lot of problems.

Interested in seeing TDD on a real project? Join me on today’s live stream. I’ll be adding new features to a real project, using TDD, and Pair Programming. Should be fun!

Share this