All About Code Coverage – A White Box Testing Technique
Let us firstly try to understand as to what is Code coverage.
It is a sort of metric meant for the measurement of the testing effort applied to the software application.
It is aimed at inspecting the code directly and is therefore a form of white box testing.
How do we capture the metrics of code coverage?
The process involves Instrumentation of the program and execution of the tests. This way we can identify the code which had been executed & which had been left out. We can see that unit Testing & code coverage are complementary to each other. Unit testing confirms the compliance of program performance with respect to the requirements, whereas code coverage reveals the areas left out of the testing.
The process of development of software is aimed to have coverage measurement by way of defining the number of branches or statements covered under the test. Even after having complete branch coverage or the statement coverage, there is no surety of absence of some key bugs in the code. Hence 100% branch coverage or the statement coverage remain quite illusive & does not provide any surety of perfection to both developers and the managers
Now the key point of discussion remains that having complete coverage remains inadequate. Reason being branch coverage as well as statement coverage do not provide any confirmation of execution of the logic of the code. Both branch coverage and statement coverage are helpful in identifying major problems in portion of the code left out of execution.
However Path coverage technique is comparatively much more rugged & helps us in revealing the defects during the early stages. Before we go deeper into path coverage, let us analyze some of the drawbacks of branch coverage and statement coverage techniques.
Major benefit of statement coverage is that it is greatly able to isolate the portion of code, which could not be executed. Statement coverage criteria call for having adequate number of test cases for the program to ensure execution of every statement at least once. In spite of achieving 100% statement coverage, there is every likelihood of having many undetected bugs.
Thus s coverage report indicating 100% statement coverage will mislead the manager to feel happy with a false temptation of terminating further testing which can lead to release a defective code into mass production. Thus we can not view 100% statement coverage sufficient to build a reasonable amount of confidence on the perfect behavior of the application.
Since 100% statement coverage tends to become expensive, the developers chose a better testing technique called branch coverage.
Branch Coverage or Decision Coverage:
Branch coverage is more impressive since it tends to go deeper into the code as compared to the statement coverage technique. Branch coverage is a metric for measurement of outcomes of decisions subjected to testing. Branch coverage criteria call for having adequate number of test cases for every program to ensure execution of every decision or branch at least once. In majority of the products branch coverage is viewed as the bare minimum coverage. Thus this is better than statement coverage, still it is not adequate for applications needing higher integrity.
It is easy to determine as to how many branches a method shall have. Simple method of working out the decision outcomes, a method can have, is counting the quantity of branches expected to be covered along with addition of one more entry branch in it.
It has been seen that even 100% attainment of statement coverage as well as branch coverage is not sufficient. Moreover for complex methods, it is practically not feasible to perform testing of each & every path. This calls for a need for a better alternative of testing ie basis path coverage.
Basis Path Coverage:
A path is nothing but the way execution proceeds across a method right from its beginning to its end. Paths, which are Independent, are known as basis sets as well. In other words, basis set is the smallest group of paths grouped together to form all possible combinations of paths across the method.
Path coverage criteria call for having adequate number of test cases for every feasible path, basis paths to ensure execution of every path at least once in the program segment.
If there are say N number of decisions in a method, then it could have 2 ^ N number of paths. However in case of a method having loop, the number of paths can become infinite. Due to extremely large number of paths in the application, path coverage also tend to become difficult. To reduce the number of paths for testing, we can take the help of the metric known as Cyclomatic Complexity. The question as to how much path coverage is needed is answered depending upon the complexity or the risk factor involved in the application under test.
Basis path coverage is similar to branch coverage in a way that it ensures testing / execution of every decision outcome. Still there is a point of difference compared to branch coverage in a way that every decision outcome is tested independent of each other. It involves flipping of the decision executed just before it, while leaving remaining executed branches intact. Since basis path coverage takes care of all statements as well as branches across a method, this is an effective substitute of branch coverage as well as statement coverage. This is the reason of basis path coverage being viewed as much more robust as compared to the branch coverage.
How to Create Data for Testing:
In simple examples it may be is easy to achieve full basis path coverage, whereas in real world scenarios full testing of basis paths becomes extremely challenging, may be even impossible. One of the reasons of this is, the necessity of having test data, which should be able to execute a particular path by testing the interaction between various decisions across a method. It is not a simple process to introduce some data which could further lead to execution of a particular path.
However following best coding practices can be helpful for simplifying the process of testing.
1) Keep a simple code.
2) Try not to use methods having Cyclomatic complexity more than ten.
3) Do not have more basis paths in number.
4) Have less number of decisions for every path.
5) Do not have duplicating decisions.
6) Try not to have data dependency
Statement coverage as well as branch coverage criteria though being simple for execution but have a drawback that some of the major defects tend to remain undetected, due to which project managers, developers and testers are liable to draw erratic conclusions of perfection, while the fact might be something else.
Whereas basis path coverage is a more rugged approach which is able to identify such defects which otherwise could have gone unnoticed.