4 Prerequisites

You may have stumbled upon TDD By Example by Kent Beck.

If you haven’t read that book, do give it a read. It’s a splendid introduction to the topic of Test-Driven Development. Notably, the author himself taught his daughter to program using this very method - TDD.

I taught Bethany, my oldest daughter, TDD as her first programming style when she was about age 12.

She thinks you can’t type in code unless there is a broken test. The rest of us have to muddle through reminding ourselves to write the tests.

– Kent Beck, “Test-Driven Development: By Example” 4

It does sound a bit like Kent fooled his daughter that you can’t write code until there is a broken test trying to run that code. However, I do trust Kent that he genuinely wanted his daughter to have the best possible habits, and in the case of programming, he did not know of a habit more valuable than writing the test before we write the code.

There was a time in my life when I added another test case to the test suite, and then found it was taking me days to adjust the codebase to make testing that part even possible. I was running late shipping the update, and it made everybody - including me - very uncomfortable.

Perhaps I would have shipped the new feature much sooner had I abandoned the stubborn wish to keep the code well-tested.

Another time, I realized as I added another test case, that I was doing something truly impossible for a non-TDD programmer. I had dozens of unit tests, each going through a part of JavaScript logic of a Web UI. I added the case, then added the code to make it work, ran the test suite, waited a few seconds, and was ready to commit and push the update.

I then marveled: had I not been using TDD all along, I would have had to spend the rest of the day (several hours) going manually through every significant workflow in the application, making sure nothing was broken.

I felt responsible for that UI. Nobody knew it the way I did. To any defect found, the operators would call me personally.

What is more, I did not join that company to build things that work some of the time, when I could make things that work every single time.

Both sides considered, testing is great, but sometimes requires a lot of extra effort.

I think you are much better off having your tests handy and running on every change you make to your program. You can always skip bending the codebase to the needs of your test suite, but you very rarely have time to add tests that should’ve been written long ago.

TDD is valuable even in the age of AI.

AI may be able to write some code for you, but you can still take pleasure in writing code. For that, you need to be able to keep adding meaningful features instead of fixing obvious bugs and regressions. TDD helps prevent bugs and regressions, a lot - and it can be applied in any language.

Even if your coding language is prone to errors - like some say about C, or Python - TDD makes these language weaknesses much less relevant. If there is a possibility of your pointer becoming null and then getting referenced, your tests will catch that. If your Python function returns nothing for a piece of data that should result in something meaningful, your tests will let you know before any user ever runs that code.

That is the strength of TDD, and that is why I think you should learn it, and stick to it - like I do. TDD keeps me sane and progressing steadily - and I wish uninterrupted sanity to us all.