Are Unit Tests worth the effort?

Unit Tests are popular item in a programmer’s toolbox. Most languages have libraries for them, they are well integrated into IDEs, continuous integration and delivery. Despite having it’s place among other tools, programmers are sometimes not very enthusiastic of using them. I’ll try to add my view on Unit Tests.

  1. Unit Tests are not a dogma

    Unit Tests emerge on the huge wave of agile movement, that proclaims to the world that movement followers like to do develop software specific way. Along that specific way comes certain practices that need to be involved to satisfy the agile way of software development. One of them are Unit Tests. For good or for bad many developers follows, integrating, often ridiculously, agile principles and make it a ‘dogma’ of software development. Unit testing and being agile is not the same category though. Unit Test is just a tool that allows some agile principle to be realized, although a tool can be used good, can be used bad. Some developers will make it their ritual and dogma, others can do without it, yet others will use them when they are necessary to create stable and maintainable software.

  2. Unit Test definition

    From the toolbox perspective unit tests are source files with multiple asserts and conditions with customized logging, that are compiled and run independently from main execution paths. Sometimes they are bound to a class or a method or a function, but they are not enforced to treat the ‘unit’ as a defined thing. We can think of a unit as some module with multiple classes, we can treat it as the smallest possible piece of testable software. There is a popular approach of treating unit test as a test code for each method in each class, but i wouldn’t like to treat it that way. I like the more relaxed definition of treating the unit as a ‘box’ within code with inputs and desired outputs or errors.

  3.  Advantages

    Most of software developers will agree that well integrated unit tests will benefit software production. One might have objections whether the benefit will return the cost that should be invested. These are two main benefits of unit tests.

    1.  Faster and less error prone changes

      This is the number one. With big code base, lots of legacy code, maintained over some years, unit tests save hours or days of debugging in case of changes. Rarely code base consists of well separated parts of independent units. Most of the time bigger or smaller, but substantial part of software will be used in most or every other unit. Changes in that part of code might have unexpected results. With good coverage of unit tests across other dependent modules, we have another degree of safety that our code will run well after changes or/and we will locate broken parts fast, and know quite well what and how had been broken.

    2. Carefully designed software unit and yet another way of documenting software.

      Before we go further, i want to say that I don’t believe in SelfDocumentingNamesThatExplainUnitBehaviour. If such thing would be possible mathematics would consist of few words definitions without predicates. Code might be self documenting in some way, but another explanations will make it more approachable. Making things easy or at least making hard problems well visible is important part of programming. Coming back to unit tests, writing them might be a lot faster and easier way of communicating, to yourself and other programmers what a unit is about and what is its desired behavior. It might be beneficial to write them before writing a piece of software to realize corner cases or to prepare conditions your code have to meet, and might be beneficial to have them if you became main developer, the previous one is unreachable and you are left with some heavy code.

  4. Price to pay and problems to handle

    1. Write and rewrite every time the concept changes

      Finding the right representation of a problem is an ongoing challenge. With rapid development with lots of features being packed into software at its initial phase, there are moments when old concepts need to be rewrite or change. Unit tests will remain only if the concept remain, the interface would not change or we will not give it a different meaning or different error handling for example. In such situation unit test will be another thing to change. Suddenly all our hopes that unit test will help ensure us that the code is working will be lost with redeveloping unit test itself.

    2. Sometimes we need a mock up

      Mockups are less painful in languages with ability to change its language structures during execution, but even then writing a mock up is time consuming, another thing, that needs to be prepared in such cases as API handling, timed execution, network or database connection and so on. Writing in, for example C++, where there is no easy way of changing units during execution, mock ups are even more painful than before, requiring substantial effort in development time and changes not only in unit test but in many cases in tested unit itself.

  5. Should we use unit tests?

    I think without a doubt that we should, but i think not everywhere, every time, what might be suggested by ‘(approx.) three letters acronyms written with caps lock’ club. Acronyms may not be the best answer for our problems, but unit tests are a tool that should be used. When working with quality software, that should work for many years without critical errors I think every investment that would raise stability is worth its price. In every other scenario the question is tricky and hard and should be answered by cold mind and years of experience in software development.