Unit Testing is an import part of any agile software development process. It was already seen as one of the major practices in the first very popular agile process eXtreme Programming. Nevertheless, for a couple of reasons people find it difficult to write unit tests (from the JUnit mailing list):
- JUnit testing is not efficient enough.
- Database and JSP pages are difficult to JUnit test.
- An exception situation is not so easy to reproduce as JUnit claims.
- Mock objects bring more than double efforts during the whole development process.
- It consumes a lot of time, but it’s hard to find big problems. JUnit does find small problems as we expected.
- For small companies, it’s really hard to choose between JUnit + development and development + functional testing.
- The best JUnit tester is the senior software developer. But senior guys hate to write test cases.
- They planned JUnit testing firstly and they cannot keep it going.
These are just arbitraryly selected arguments not to write unit tests or postpone them to a later project phase. Why should we unit test early, anyway?
The real benefit of automated unit tests arises when the software is in the maintenance phase. With many software systems, the maintenance phase makes up the majority of the life cycle, especially with successful systems. Unsuccessful systems are not used, therefore hardly have any maintenance, or they are never introduced at all, so no maintenance at all. Successful systems are introduced and used, therefore maintenance as well as troubleshooting are important. Successful systems might even be expanded during their lifecycle.
During the maintenance phase, the original development is increasingly far behind. As a result, fewer and fewer of the same developers are working on the system and even the memories of those who were there at the time fade more and more. This makes changes increasingly risky, as not all side effects are recorded intuitively. Documentation that is notoriously out of date and is of no help. Automatically updated documentation (for example object models or data models) usually only covers the static aspects of a system, while side effects of changes often affect the dynamic aspects - the behavior of the system. These models hence do not provide any security either.
On the other hand automatic unit tests validate the behavior of the system in an objective way. The creation and maintenance of the tests is very costly. This effort pays off with every change: By running the automated tests, you can be reasonably certain that the side effects of the change are known. In each individual case, it must then be decided whether the reason for a non-running test is a newly introduced defect or whether the test has to be adapted to match the new requirements. Automatic unit tests are not only used to guarantee the correct functioning of the initial version of software, but rather pay off during the maintenance phase. In this sense, postponing the implementation of tests can be understood as taking out a loan: Generally speaking, there is nothing wrong with taking a loan. In order to reach a goal on time, you might be in need of a loan. Postponing unit tests can be seen as a time credit.
As with any loan, however, there is interest that must be paid so that it does not grow into an exponentially growing mountain of debt and ultimately leads to bankruptcy. In the same way, you can see the additional efforts during the maintenance phase that arise, because unwanted side effects of changes go unnoticed. The compound interest effect of the analogy can also be observed in practice: If the collateral damage of a change is repaired again without the appropriate unit tests being written, the time credit increases accordingly. The time credit can be paid off by re-implementing tests so that the negative consequences no longer arise.
Every analogy which transfers back statements about the analog image to the original state of affairs, is a thing prone to errors. In the financial world, there is a market for loans that ensures that the overall cost of a loan, in particular the future interest burden, does not leave a certain, economically reasonable range. This does not apply to the consideration of the time credits described. It is possible that the cost of these time loans, i.e. the future negative consequences, will be negligible. It is also possible that these consequences are extremely big. Quantitative studies on software projects are very difficult and accordingly few concrete figures are available.
The fact that the term technical debt for postponed refactorings, unit tests and cleanups has established over the years, shows that the credit anology is a good way to explain the consequences of ommiting unit testing, especially towards non-technical decision makers.