What needs to be unit tested. How much code coverage is needed.
May 23, 2017
The purpose of this article is to show what you should test and what you should NOT test on your application. No code will be shown here but an abstract view about the topic.
Martin Fowler blog and posts from Stackoverflow community were used as a reference.
Testing is important aspect in programming and can largely determine the fate of an application. When the application is submerged with tests, most of the issues can be catched in an early phase but if not, poor testing invariably leads to failure.
What is unit testing ?
A unit test is a test of a small component or a unit of your application. Because the scope of each individual unit test is so limited, the only way to do it is to write code that tests your code, usually using a framework like JUnit.
Unit tests are written and executed from developers and they are used to test individual code components.
What makes the unit test correct ?
Unit test must be fast because they are runned repeatedly to check whether there are new bugs. Slow unit tests may also indicate that either the system under test, or the test itself, interact with external systems, making it environment-dependent.
The intent of the unit test must be clear and explanatory. The most important thing about a unit test is to explain and show the behavior and logic of the tested component. Some of the developers have the practice to use tests instead of documentation.
Good unit tests should be reproducible and independent from external factors such as the environment or running order. So if the test fails somewhere on the track… fix your code!
Writing unit tests using the principles and information below will be definitely more easy.
Difference between Loose Coupling and Tight Coupling.
Tightly coupled object is an object that needs to know quite a bit about other objects and are usually highly dependent on each other’s interfaces. Changing one object in a tightly coupled application often requires changes to a number of other objects. In a small application we can easily identify the changes and there is less chance to miss anything. But in large applications these inter-dependencies are not always known by all programmers and there is chance of overlooking changes.
Loose coupling is an approach to interconnecting the components in a system or network so that those components, also called elements, depend on each other to the least extent practicable. Loose coupling is a much more generic concept intended to increase the flexibility of a system and make it more maintainable.
To design a code that is really testable many developers are using the SOLID principle.
S – (Single Responsibility Principle) – An object should do exactly one thing, and should be the only object in the codebase that does that one thing.
O – (Open/Closed Principle) – A class should be open to extension, but closed to change.
L – (Liskov Substitution Principle) – A class A, dependent upon class B, should be able to use any X:B without knowing the difference.
I – (Interface Segregation Principle) – An interface should have as few methods as is feasible to provide the functionality of the role defined by the interface.
D – (Dependency Inversion Principle) – Concretization and abstractions should never depend on other concretizations, but on abstractions. (Dependency Injection)
One of the most important stuff that should be done before start writing tests is to decide what to test. Most of the enterprise applications for example can contain lots of code. There is no need to test all that code. When you decide what to test, you need to be focused on what actually matters to your users and your application.
What you should assume is working correctly and does not need to be tested ?
1. External libraries and frameworks
2. Trivial code like getters and setters
3. Code that works only with the UI
What needs to be tested ?
One of the most important rules when talking about unit testing is to test and cover code which is mostly part of the business logic.
1. Code used from a lot of modules
2. Repeatedly changed code
3. Code that is expected to generate a lot of bugs
Most of the developers use some tools or IDE plugins to check the code coverage on the components which already are tested.
Code Coverage is a measurement of how many lines or blocks of the code are executed while the tests are running.
Interesting forum post about code coverage here.
Good idea is to use code coverage as a guide to indicate areas which are not tested. Rather than having a mandate for coverage it is wiser to understand the reason for code not covered. Recording a reason for the shortfall is good discipline that allows the risks to be balanced.
Most of the developers write unit tests on things that are more easily testable. According to this wiki article 20% of most code will run 80% of the time. A code coverage analysis is not very useful unless paired with a call graph to determine what needs to be tested the most. That tells you where your edge cases are likely to be. You may come up with 100 tests just for those edge cases, which constitute less than 5% of the actual code. So, make sure to cover 100% of the 20% that defines critical paths, and at least 50% of the rest.