We, developers, work hard. Software developing is not always intuitive or fun. It can drain our energy from thinking hard trying to solve different problems we are facing during our daily tasks. There are so many other things that affect our work for better or for worse.
Whether if it’s a mood change or small/big routine changes that affect us. Why would one add additional work to their already- hectic routine? By additional work, I mean, Unit tests.
I have gathered information from different sources over the internet targeting the question: Why we should not be unit testing.
Major arguments of why not- to are:
- Writing/coding unit tests for your app increases the development time.
- Unit Tests are sometimes more complex than the actual code.
- Unit tests might make our programmers lazy.
- Unit tests are just a cult.
I found the article of James O Coplien the most informative and interesting against unit testing. It’s the kind of article that sums it up all. The main idea in his article is that integration tests are better than unit tests. So much better that he claims we should eventually replace unit tests with integration tests.
In this blog post, I’d like to dispute his reasoning one at a time. According to his article, unit testing was a staple in the FORTRAN days, then sank and came back again when OOP stormed into our world. The reason it came back once again is that we could not determine the behavior of class function members at a run time. We had to run the program in order to see how it performs. Alright, then where did unit testing go wrong?
James O Coplien writes a lot about the coverage level/percentage. He reports that most developers claim that they provide complete or almost complete coverage which turns out to be false. In fact, most developers don’t admit that they only provide partial coverage. In order to give complete coverage, we would have to write many more lines of code, more than the codebase itself. By many I mean huge numbers. So obviously, I tend to agree with it. There is no such thing as complete coverage, it makes no sense, but it applies both for integration and unit tests.
However, there are several ideas presented in the article I don’t agree with.
Laziness or lack of skill
“If your coders have more lines of unit tests than of code, it probably means one of several things. They may be paranoid about correctness; paranoia drives out the clear thinking and innovation that bode for high quality. They may be lacking in analytical mental tools or in a discipline of thinking, and they want the machine to do their thinking for them.”
Yes, it might be that the developers are lacking in analytical mental tools or discipline of thinking. They might feel more comfortable “relying” on unit testing, but the truth is, that writing unit tests alone requires a lot of analytical skills which leads us to a contradiction. Additionally, what’s wrong with being a little “paranoid”? if it boosts your perfectionism trait, nothing’s wrong with that, the opposite.
“If you want to reduce your test mass, the number one thing you should do is look at the tests that have never failed in a year and consider throwing them away. They are producing no information for you — or at least very little information. “
If a unit test fails, then it fails as you are developing the code. You will fix it immediately as it is similar to the compilation process. By applying your fix, the tests are no longer old and useless as he claims.
The Green reward
“Perhaps the most serious problem with unit tests is their focus on fixing bugs rather than of system-level improvement. Too often I have seen coders, heads down, trying to get the test to pass and the Green Bar To Come Up.”
The problem presented here is not about the unit tests, but the programmers and/or team leaders. Unit tests have important key points and guidelines that we should follow in order to make them useful and not just green. It might be a problem though, when your team leader demands a high level of coverage, you will probably do anything to make it.
Your team leader must understand that quality> quantity. The importance of Unit tests when it comes to system-level improvement is also doubtless, as opposed to the writer’s opinion and I’ll evaluate it soon.
System & Integration tests will do it for you
“Turn unit tests into assertions. Use them to feed your fault-tolerance architecture on high-availability systems. This solves the problem of maintaining a lot of extra software modules that assess execution and check for correct behavior; that’s one half of a unit test. The other half is the driver that executes the code: count on your stress tests, integration tests, and system tests to do that. “
Asserts are not a substitute for unit tests. It is only a half of a unit tests as he mentions there. If an assert fails, there is a failure in the production system. But we can also assert something that can also be unit tested. It’s better to find the problem when testing and not in production and it is clear to us why.
Moreover, we can’t always count on our stress/integration/system tests. When we test the complete system or application, it is to our advantage to use well-tested parts.
Think of a car. Say you have just purchased the most prestigious, good looking, comfortable car you could ever effort for yourself. It can technically speed up to 250 km/h in seconds and its engine is so quiet. Wonderful, isn’t it? Say it is a new model. What if the manufacturer company has failed to recognize a tiny defect with the screws of the wheel and it doesn’t match perfectly? Your car is unstable and more importantly, won’t be safe to drive on. Speed, appearance or comfortability aren’t worth anything now.
In this case, it might not be hard to find where the problem is, but in other complex systems it might take us a lot of time (and money) to find where to bug comes from, if we gave up unit testing and only used integration/system tests.
Unit Testing doubles the development time
Writing tests is definitely slower than writing no tests at all if you only count the total time of typing our code. However, if we take in conclusion all the time spent trying to find and debug errors that occur later in our code (and in a later phase of development) due to lack of unit tests, we understand that unit testing is always worth the time and effort. Additionally, it would cost us much more to find out & fix a bug in a later phase of our software development rather than it would have cost while it’s still in the programmer’s hand (as unit tests applies to them).
Last, I would like to mention additional arguments to why should we give unit testing a second chance, hoping to have you convinced by the importance of unit testing ?
So why Unit Tests?
Rapid feedback – Sometimes the complete feature you are working on might require other parts of it to be done first, or else it takes some time to respond or finish. Integration tests are not always available to us. Unit tests fives us fast feedback as it tells us if we made a mistake while coding.
Confidence – Having unit tests gives our developers confidence when applying fixes to different bugs or adding new features to the product.
Documentation – By writing unit tests we provide another type of documentation for ourselves and others.
Faster development – As mentioned earlier, the whole developing process is faster in the long run due to early feedback (early bug discoveries).
We must remember that as long as we call ourselves programmers, we must be always learning new things and be updated with new technologies and methodologies. Having a bad experience with X doesn’t imply that X is bad. You may not have used it the right way according to the manual. Same with Unit tests.
Give it a second chance!
Use the right tools that make unit testing easy: