The idea of “untestable code” comes up often when you start implementing any test automation methods, especially unit testing.
Suddenly, you discover that code is not testable. It resists.
Actually, it’s not “untestable”. But it’s damn hard to test, without changing.
Here’s an example. Your code does a calculation and saves the result in the database. You want to check that the code is doing what it is supposed to. But to do it, you need to setup a database, set it up, call the code, call the database to check the result, and wipe it clean before you run the next test. If our code only returned a result we could simply assert on…
It’s not “untestable” code. It is expensive to test. Most code is like that, because most developers, yours truly included, were not taught to build cheaply, testable code.
There are consequences: Most of the time, “untestable code”, which is really hard-to-test code, doesn’t get tested. It’s either too costly to write tests for as-is, or risky to change (without tests), or both.
So we declare the code “untestable” and move on, perpetuating the idea that “untestable code” exists.
There are a few things we need to do for that to change.
First, we need to change our language. Remove “untestable” from our vocabulary. When we start calling it “hard-to-test code”, we state the code is testable, and it can be written differently for easy testing.
Then, we need to acknowledge that code, as it was written until now, is hard to test. And we have options:
- Leave that code and don’t bother to test it
- Test it (with time, effort, blood and tears)
- Change it (with time, effort, blood and tears) and test it more easily
We can also decide to start testing new code, which was written with testability in mind, and will be easier to test. And we should train the developers to do that.
Untestable code doesn’t exist. But we can write better, simpler, cheaply-testable code, and make our testing implementation easier.