Comment by jacquesm

21 days ago

The interesting bit is this: how much of what you wrote over all those years actually did what you wanted it to do, no more, no less?

This is where testing gets interesting: I took some old code I wrote 30 years ago or so and decided to put it literally to the test. A couple of hundred lines from a library that has been in production without every showing a single bug over all that time. And yet: I'm almost ashamed at how many subtle little bugs I found. Things you'd most likely never see in practice, but still, they were there. And then I put a couple of those bugs together and suddenly realized that that particular chain must have happened in practice in some program built on top of this. And sure enough: fixing the bugs made the application built on top of this more robust.

After a couple of weeks of this I became convinced: testing is not optional, even for stuff that works. Ever since I've done my best to stop assuming that what I'm writing actually does what I want it to. It usually does, for the happy path. But there are so many other paths that with code of any complexity, even if you religiously avoid side effects you can still end up with issues that you overlook.

I think you have the correct approach. Tests are signals, not proofs.

I do often hear on HN people advocating for Test Driven Development (TDD) but that I think is a different category of error. It encourages people to write to the tests, not to the spec. They'll claim the test is the spec but not understand that the spec can't be written down in full. The spec is the intent, the written spec is an approximation of that, the tests are an approximation of that.

The problem with TDD is it makes it easy to believe that by passing the tests your code is complete and bug free. It's easy to test tests as proofs.

But just because tests aren't proofs doesn't mean they're not useful. They narrow the space in which errors exist. Tests also are a form of communication. It can tell others about your assumptions, again, making the search space for debugging smaller.

Tests are useful, but no one can write tests that are complete.