Stop being frantic about code testing

Published on 2021-03-31. Modified on 2021-04-01.

Code testing is not only great, it is a must as you cannot develop software without testing your code. However, there is something which I prefer to call "frantic code testing", which is what needs to be avoided.

It is no secret that I am not a fan of paranoid unit testing. There are examples out there where people have more code in their tests than in the actual code base, and they spend more time on writing tests than any code, they even think more about testing that coding.

In such cases you might think that unit testing helps avoid technical problems, but the fact is that for many people unit testing is more about getting a psychological effect rather than a technical one, it's a way to make you feel better about yourself - yes, I said it.

I am not against testing, I do vigorous testing myself during development, but I mostly prefer manual testing. During development every functionality is tested each time a minor change is made. The method I use is a rigorously usage of inserted breaks, where you halt the application at specific places during runtime and then check that the values and data is correct, all the time. At the same time you try to break the software, do things that you're not supposed to do. It is a very effective way to discover bugs early during development, because it not only quickly becomes a natural part of the development process, it is also better related to the way the software is intended to work. It is especially useful if you get into the habit of feeding the system the wrong kind of data. It is a method that requires patience and experience, but it is very effective. And no, it's not more time consuming that writing test, it's a more direct and natural part of the development process.

I also do unit testing, but mostly without a framework because they are simply too slow (PHPUnit e.g. is absolutely horrible), and I only test code I worry about.

Unit testing is mostly relevant in relation to code refactoring, which is when you re-organize or re-structure your code to make it easier to add features or fix bugs (refactoring is never about adding features or fixing bugs!).

Imagine you have some old software, software that has been running well for years and it is working perfectly, but now you suddenly need to change something in order to add a new feature, and you can hardly remember anything about what does what and why. Even if the code is well structured, you might make a mistake by assuming something that is wrong. If you have unit tests in place, they will help you validate if the changes you make might break something.

Automated testing and automated monitoring is very useful, especially on critical parts of a system, but only when it truly makes sense, and not as a rule carved in stone.

Sadly, as with the so many other things in this industry, many people have become frantic about testing. It is seriously tiresome how all this "best practice" keeps being taken to the extreme. Some people feel superior because of their testing and they look down upon someone if that person haven't got a good test coverage.

Naturally your code already has comprehensive test coverage so I don't need to tell you that X is a bad idea right!?

That was a quote from someone (not naming any names) who has made it his mission in life to make sure that everyone else knows just how cool he is with his testing practices.

In my humble opinion, and with all due respect, it's borderline stupid how much weight is being put on testing nowadays. So much so that it can actually have the opposite effect. Rather than focusing on the problems that the software is supposed to solve, people spend more time developing tests and getting the code to pass.

Unless you're developing mission critical software you're much better of concentrating on the programming and problem solving. Then release early and release often. Don't worry too much about software failure as it is bound to happen no matter what you do. Plan ahead instead. Have a solid strategy for how you deal with failure, when it happens. And stick to testing the most critical parts of the system, the code that you worry about. Never test code that is obviously correct - that's just a waste of time.

You should never aim for a 100% test coverage, if you do that then you're doing testing wrong! Major parts of the software are obviously correct and requires absolutely no test coverage, don't waste your time on that part. Focus on the parts of the software that are complex, then before you begin writing any tests, consider if there are ways in which you can simplify the complexity. Perhaps you can divide the code into even smaller pieces, and perhaps you can delegate responsibility to other functions. However, some parts of the software needs to be complex and you simply cannot avoid it! And no amount of testing will do you any good! Not everything can or should be broken down into teeny tiny pieces. And don't even get me started on TDD being the driving force for the design of a program - a programmer should be focused on the data, not on the code!

When you get tied up in developing software for testing, and in design patterns and best practice, all your enthusiasm is lost and you lose precious energy that could have been spend creatively coming up with better and more efficient ways to deal with the problems you're facing.

When you're "in the zone" you can hardly stop thinking about ways to improve stuff and find new and better ways to do things. You might be in the shower or taking a walk and suddenly you get a bright idea and can hardly wait to try it out. All that is strangled to death when 90% of your time is spend worrying about writing tests, fulfilling the demands of the design patterns and "best practice" fanatics.

In any case, don't feel bad about yourself if you're not writing any code tests. The value of writing code tests is highly exaggerated. The more critical a system is, the more justified unit testing and automated testing becomes.

Update 2021-04-01: I just want to comment on a few emails and comments I have gotten regarding this article.

I have been in the industry for 34 years (as of writing) and I am not talking about toy software or software that you only work on for a short time.

I have developed huge applications as well as minor ones, both as single developer and in cooperation with others. I have software that has been running at clients for more than 13 years with a huge customer base and tons of daily activity, still doing great.

A pattern emerged very early in my experience that coincides very well with the Linux kernel model of development.

By not focusing too much on patterns or "best practice", you are actually able to focus on the problems the software is supposed to solve. This doesn't mean that you should not care, or build crap that other developers would consider a nightmare to deal with, but you need to be practical. This is based upon pragmatic experience, not upon what other people (mainly the majority, or actually always the majority for some reason) are shouting loud about.

Whatever the majority is doing, and whatever people seem to be frantic about, is usually the wrong way to do things. I believe it is because people who tend to become religious about such matters are often very insecure and emotional, as soon as they see someone going against the current, they become afraid because this jeopardizes their own position in life. They stand where they stand, not because they themselves have been thinking deep and hard about the stuff they do, but simply because they are "blind followers".

Much of the so-called "best practice" is all about specific people making themselves feel important, selling their books, and being payed a lot of money to talk a lot - this is how they make money. You have to think for yourself.

Oh, and by the way, yes I am serious.