The Importance of Unit Testing, or How Bugs Found in Time Will Save You Money
July 5, 2017 - Software Development
Unit testing still causes controversy among developers and project managers. There are both opponents and supporters of this kind of testing; in this article, we are going to highlight the main advantages of unit testing and explain why it is so important.
What are unit tests, why write them and how they help developers and business owners – find the answers below.
Let’s start with the definition. Unit testing is a kind of software testing where units – individual components of software – are tested. How it happens? Developers can write unit tests for their code to make sure that the code works correctly and protect themselves from bugs in the future.
Sometimes developers write unit tests first and then the code. This approach is also known as test-driven development (TDD). In this case, a developer does not have ready code yet, and through tests determines what each module should do. In this way, they express their thoughts on specific components, and when the code is written, make sure that everything works as planned. Consequently, unit testing allows to modify code without affecting the functioning of other units or the whole product.
Unit tests are usually written in the form of functions and check the value and behavior of these functions in various cases. Let’s look at a simple example: there is a function of division of two numbers. In this situation, we decide to follow the TDD approach and at first write a test with input values 4 and 2 (4 divided by 2) and expect 2 as a result. Apart from this, we may test the behavior in some other cases. For example, when the divisor is zero. In this case, we don’t expect that the function will produce a value – we expect that it will generate an exception. We may also expect that the function will notify some component about an attempt to divide by zero. And thus, we test two cases:
1) in an invalid situation the function will notify us that we are doing something wrong (an exceptional situation);
2) the function will identify this invalid situation and log it.
Some developers tend to underestimate the importance of writing unit tests. Before you form your own opinion on this matter, first get acquainted with the benefits of this approach to development.
The code covered with tests is more reliable when it comes to changes than the code without tests. If someone in the future will change the code and break something in it, they will notice the problem right away.
Good practice implies that when making changes to code to make sure that these changes will not disrupt the existing code, developers run all unit tests or a group of tests locally. However, in this situation, the human factor can influence: a developer can forget to run unit tests after making changes and commit the potentially non-working code to a common branch. To avoid this, many companies apply the continuous development approach. Tools for continuous integration are used for this, allowing to run unit tests in an automatic mode. Thus, any unfortunate changes in the code will be detected by a cold, logical machine.
The speed of detecting the non-working code depends on the settings of tools for continuous integration. It can be either a one-time check at a certain time interval or an immediate check of the changes made.
To sum up, unit tests help to detect problems immediately and fix them in hot pursuit, with minimal resources involved in finding a bug.
…Which saves money for the company.
Steve McConnell in his book Code Complete shares a table with bugs and the cost of fixing them at different stages of the product life cycle. The table shows that the earlier a defect is detected, the lower the cost of its correction.
In the event that unit tests are written, many bugs are found at the software construction stage, which prevents the transition of these bugs to the following stages, including after the release of the product. And that, in turn, according to the table, saves money which would be spent on fixing the bugs, which also brings benefits to end-users.
Unit tests are a prerequisite for this programming methodology.
Extreme programming adheres to a “test everything that can possibly break” strategy. Writing unit tests under this methodology makes development and code refactoring simpler, integration easier and creates living documentation.
Speaking about documentation, unit tests are a kind of living documentation of the product. To learn what functionality is provided by one or the other module and how it can be used, developers can refer to unit tests to get a basic picture about the logic of the module and the system as a whole.
Unit test cases represent indicators that carry information about appropriate or inappropriate use of a software component – and thus, document these indicators.
What test coverage is necessary? For example, Robert C. Martin, also known as Uncle Bob, argues that code coverage with tests should strive for 100%. However, in the community of developers opinions on this issue differ: some support a complete code coverage policy, while others consider this practice redundant – we will not go into this topic deeply. In any case, when writing unit tests, there are very effective tools for determining the total percentage of coverage of a project, separate module, function, etc. These tools are also able to graphically display code sections covered with tests and indicate places in the code for which it makes sense to write unit tests.
Unit tests imply that the individual modules of the product become isolated from one another and have their own area of responsibility. That means that the code becomes more reusable.
And finally, after all mentioned above, there is probably no need to explain why unit testing makes code more reliable.