Software Testing is hard. The intention of unit testing is to make it easier through automation. In practice however, unit testing often causes even more pain than software testing. Learn how to cure this pain in this article!
The Pain
A created unit test can be executed as many times as you want. With the additional benefit of getting feedback early in the development process. At least in theory. However, practice shows that unit testing simply shifts the pain of testing from a professional software tester to the developer, whose profession is to write code, not tests. In it’s essence, this pain of unit testing can be broken down into three problems:
1. Divide & Conquer gone wrong As an economy, whe have progressed in the last century by dividing tasks into different work profiles. As one result, when we identified the crucial issue of testing software, software testers emerged to focus on fix this issue. They have developed many practices (see ISTQB) over the years, and most testers are trained in doing the best in their job, full-time. However, with unit testing, we shift this responsibility of software testing back to the developer. Whereas this develoeper might know the underlying code the best, her job is to write code, not tests. As a result, most unit tests are developed with poor methodology, and even poorer motivation – simply because the person writing the test wanted to get over with this burden to continue writing code.
2. Code Coverage – so what? Too often, developers write unit tests to satisfy some code coverage constraints. Which makes sense in theory, because code coverage tells you. So if you have 100 % code coverage, you know that your system works. In practice however, the only thing that 100 % code coverage produces is a whole bunch of unnecessary test cases that noone will maintain, thus will be burried in some code graveyard that noone wants to have a look at once the underlying software changes. The calculation of code coverage has many flaws (see an example here:
Limits Code Coverage), which means that it essentially doesn’t tell you what it promises to. Whereas code coverage gives you a good first impression of whether you should still write some more tests, it does not tell you whether your tests actually cover enough (or all) desired functionality of your software.
3. Never change a tested system. One trap that many developers fall into is believing that once a unit test is written, they can re-execute it for the rest of their (or at least the software’s) life. However, a unit test is code, which compares the functionality of your software code with the expectations derived from the requirements of the software. But what if the requirements change? Or the structure of your software code changes? Both cases require you to adapt all of the relevant unit tests. In agile environment with frequently adapting requirements, this is the actual pain in unit testing! Usually, it leads to unit tests not being updated after some time, and again switching to manual testing (or no testing at all) for legacy parts of your software.
The Cure
3. Agile Unit Testing. The best way to cope with constant change is to expect things to change from the beginning. Whereas this mindset is starting to get accepted in software development in general, it is still non-existing for unit testing. But what does expecting change even mean for writing unit tests? You could consider that when writing your unit test code, by applying an architecture that optimizes for adaptability (if you do, have a look at this checklist first:
The Ultimate Checklist for Better Unit Testing). You can also simply use tools that help you manage test cases, by taking over the whole coding part. The right tools provide you with an interface that is optimized for finding and adapting unit tests.
What do you think of the pain in unit testing? What are your experiences in curing it? Let me know in the comments section below!
Daniel Lehner