In software engineering, unit testing refers to testing individual units of source code. They’re part of the application code, written during development. Unit tests are powerful tools for developers, who can use them repeatedly to quickly and automatically fast check if the units of code work as they should.
However, writing them takes time, and since you can deliver an application without unit tests, some entrepreneurs unwisely consider them unnecessary. Time is money after all and some clients and IT companies don’t want programmers to spend time writing tests. They assume that manual tests are sufficient, so they can hire someone who’ll test their system or they can do it themselves — which will reduce short-term costs. Some clients are unaware that unit tests are a thing. In either case, knowing the benefits of unit testing will help you understand that having them actually saves considerable time and money.
Unit tests and why not to skip them in your app development project
Table of contents:
Why unit tests matter
Before I get into the details, I’d like to share a story. I recently worked on a lottery gaming application where my job was to write one of two REST APIs. Work on the first service started about a month earlier than mine. The previous team did not write any automatic tests for the first API.
But the customer was content with the production method because he received the first several features quickly. When work on the second service started, unit and integration tests were part of the code production. Initially, the product owner had to wait longer for results and was not happy. There was some pressure to give up writing tests and leave them for later if there was enough time. I had to convince the product owner that this would be a huge mistake that will cost in the long run — especially when it comes to long-term maintenance.
Over time, the benefits of unit tests — and the contrast between the two APIs grew. In the service with tests, when a developer added a new feature, manual testers detected almost no errors. In this version, the team could do their work systematically. By contrast, the project without tests often came back for corrections, disrupting the flow of the project. Over time, more developers joined the second service team. They could quickly adapt and implemented new features. The client also attempted to enlarge the first team, but it was ineffective and they ultimately abandoned it.
Throughout the whole development process of the second API, the developers were more productive and proud of code they wrote. Even though it took longer to start, jumping into a development project without unit tests leads to major headaches later.
Don’t skimp on unit tests
As I mentioned above, the client wanted to give up writing automated tests, as he thought that manual tests are enough. This is due to the superficial treatment of the testing process. Many people think that once a tester tests an application’s functionality, he can move on. There is no need to do it again unless they need to change the feature behavior. It seems easy, but there are some dangers and gaps in this reasoning.
First of all, many people know exactly what they want and tend to think that there won’t need to be changes. But no matter how detailed the initial app specification is, after receiving the feature and using it, ideas of how to improve it always emerge. This is a normal and healthy part of Agile development. In addition, something that may seem like a small change may actually require changes in many areas. What’s more, the main functions of the system consist of smaller functionalities — and these are often shared. Making changes in one area may affect others — often in places we don’t expect.
A tester may need to test a feature many times as its behavior changes. A developer can use a test repeatedly for months or even years as long as there is a part of the system that it checks. The effort put into writing it will pay for itself in the long run.
How unit tests work
Unit tests usually run for a minute or two, so you can use them very often. Developers can launch them several times when adding a new functionality to the system. Thanks to this, they can detect defects early so they can find and correct them quickly. Manual testers can only test a new function once it goes live. Finding the cause of the error and fixing it at this stage often takes longer and is more difficult because it concerns a larger area of code.
What’s more, manual testers don’t always check the code right after they’ve finished their work. Sometimes a developer can go several days or even weeks without them. To fix this type of error after such a long time requires digging down into the code again — time that could go toward moving the project forward. However, the key question is how can rapid error detection affect the stability of the project? Project complexity always increases over time. The more complex the project is, the more internal code dependencies it has. Introducing new functions often requires changes to the existing code. Errors are inevitable and can often occur in unexpected places.
If we can automatically check if the basic unit functions are preserved, and errors that were found are fixed at the developing stage, total functionality delivery time is much shorter. We reduce the impact that system complexity has on the introduction of new functionalities and changes. We gain greater predictability regarding the time and resources needed to implement new features or to change existing ones.
Unit tests are not only useful for checking the existing units. The very process of writing them also improves the stability of the project. Unit tests affect how developers write the application code. They force the programmer to divide the code into small units with a clearly defined, single responsibility. This process requires the programmer to plan the implementation and reveals edge cases. If individual responsibilities are not separated into units, they cannot be reused. If a unit meets several requirements, it is more difficult to understand which dependencies apply to each one, and that significantly impedes changes.
As one unit test checks one specific behavior of a single unit, information about the error found is very precise. The developer sees exactly what expectation has not been met and which unit has failed. Unit tests can also tell what is the expected result, which makes it easier for the developer to fix the fault. This benefit is particularly important when developing larger applications that more than one person worked on. The person who introduces the new functionality may not know the whole system. Information obtained from the unit tests are then particularly useful. In effect, system development is more efficient.
Unit testing has another important advantage for long-term projects: it’s easier for new developers to join it. This is not a secret, that in the IT industry, employee migrations between companies are common. In some cases, development teams might have to grow as projects grow. Unit tests give them comfort: despite the lack of knowledge of the system, they can test their changes. If an error is detected, the information received is so detailed that in many cases it is possible to fix it quickly without long analysis or asking others for help. Unit tests also give comfort to the project owner — changes in the development team are less time consuming and less stressful.
There is another advantage of unit testing that affects project stability. Assumptions in the project change or evolve over time. Technology itself is also developing: new tools, new versions of libraries as well as new ideas regarding the quality of software development comes out. All these changes make refactoring necessary if we want to maintain code quality.
Unit tests allow us to quickly pre-check whether refactoring changes, often of global scope, negatively affect the functions of the system. The developer immediately receives information about the impact of the change. Based on the list of detected faults, he can make corrections or withdraw changes if he considers that the scope of work is too large and unprofitable.
Refactoring in a project that does not have automated tests is often rejected in advance because it is risky. It’s difficult to estimate its scope and time needed to complete it.
Final thoughts on Unit tests
As we can see, unit tests have many advantages that make them profitable, despite their initial cost. Although those preparations need to be made before developers can start using them. Additional lines of code that always need to be written when adding a new feature, and fact, that just like the main application code, they also need to be modified when requirements change.
We need to remember programmers will use unit tests throughout the development process. They often fire the tests several times a day when they write changes. Unit tests are invaluable tools for programmers to add features and make modifications. These tests may detect errors at an early stage, support maintaining application consistency and code quality.
They are invaluable for long-term projects because they reduce the impact of their complexity on making improvements. The saving of time that we think will be gained by not writing them is apparent. The knowledge of their benefits allows us to understand that thanks to them we save time and our nerves.
- From Idea to working prototype. Startup App development Guide Initial stage
- How to build a successful MVP
- 7 common mistakes when developing an MVP
- How we work remotely! Find out our tips for effective cooperation on software development outsourcing!
- Our product design workshops – how to guarantee the most effective application development process