Know the Basic White Box Testing Techniques based upon Code Coverage
Some of the basic testing techniques based on code coverage are as under.
1) Statement Coverage
2) Path Coverage
3) Condition Coverage
4) Function Coverage
1) Statement Coverage:
In most of the programming languages, the program construct may be a sequential control flow, a two-way decision statement like if � then � else, a multi-way decision statement like switch or even loops like while, do, repeat until and for.
Statement coverage refers to writing test cases that execute each of the program statements.
We assume that “more the code covered, the better is the testing of the functionality”.
For a set of sequential statements (i.e., with no conditional branches), test cases can be designed to run through from top to bottom. However, this may not always be true in two cases
a) If there are asynchronous exceptions in the code, like divide by zero, then even if we start a test case at the beginning of a section, the test case may not cover all the statements in that section. Thus, even in case of sequential statements, coverage for all statements may not be achieved.
b) A section of code may be entered from multiple points.
In case of if then-else statement, if we want to cover all statements then we should also cover the ‘then’ and ‘else’ parts of the if statement. This means that we should have, for each if-then-else, at least one test case to test the ‘then’ part and at least one test case to test the ‘else’ part.
The multi-way, switch statement can be reduced to multiple two-way if statements. Thus, to cover all possible switch cases, there would be multiple test cases.
A good percentage of the defects in programs come about because of loops that do not function properly. More often, loops fail in what are called “boundary conditions”. So, we must have test cases that
1) Skip the loop completely so that the situation of the termination condition being true before starting the loop is tested.
2) Check the loop for n = 1.
3) Try covering the loop at the boundary values of n i.e., just below n and just above n.
The statement coverage for a program, which is an indication of the percentage of statements actually executed in a set of tests, can be calculated by the following formula
Statement Coverage = (Total Statements Exercised) / (Total Number of Executable Statements in Program) x 100
Thus it is evident that as the type of statement progresses from a simple sequential statement to if-then-else and through loops, the number of test cases required to achieve statement coverage increases. As we have already seen that exhaustive testing or 100% testing is not possible, so also exhaustive coverage of all statements in a program will be impossible for all practical purposes.
Hence even if we get high level of the statement coverage, it does not mean that the program is free from defects.
In a program that implements wrong requirements and if such a code is fully tested with say, 100% coverage also, it is still a wrong program. Hence 100% code coverage does not mean anything.
Let us consider another example here.
i = 0 ;
if (code = = “y”)
{
statement �1 ;
statement �2 ;
:
:
statement – n ;
}
else
result = {marks / I} * 100 ;
In this program, when we test with code = “y”, we will get 80% code coverage. But if the data distribution in the real world is such that 90% of the time, the value of code is not = “y”, then, the program will fail 90% of the time because of the exception-divide by zero. Thus. even with a code coverage of 80%, we are left with a defect that hits the users 90% of the time.
The path coverage technique described below overcomes this problem.
2) Path Coverage:
In path coverage technique, we split a program into a number of distinct paths. A program or a part of a program can start from the beginning and take any of the paths to its completion. The path coverage of a program may be calculated based on the following formula
Path Coverage = (Total Path Exercised) / (Total Number of Paths in Program) X 100
Consider the following flow graph having different paths.
Some of the paths are
Path-1: 1 > 2 > 6
Path-2: 1 > 3 > 5 > 6
Path-3: 1 > 3 > 4 > 5 > 6
Path-4: 1 > 3 > 4 > 2 > 6
Regardless of the number of statements in each of these paths, if we can execute these paths, then we would have covered most of the typical scenarios.
Path coverage provides a stronger condition of coverage compared to statement coverage as it relates to the various logical paths in the program rather than just program statements.
3) Condition Coverage:
In the above example, even if we have covered all the paths possible, it does not mean that the program is fully tested. Path testing is not sufficient, as it does not exercise each part of the Boolean expressions, Relational expressions and so on. This technique of condition coverage or predicate monitors whether every operand in a complex logical expression has taken on every True / False value. Obviously, this will mean more test cases and the number of test cases and the number of test cases will rise exponentially with the number of conditions and Boolean expressions.
For example, in if-then-else, there are 22 or 4 possible True / False conditions. The condition coverage which indicates the percentage of conditions covered by a set of test cases, is defined by the following formula
Condition Coverage = (Total Decisions Exercised) / (Total Number of Decisions in Program) x 100
Thus it becomes quite clear that this technique of condition coverage is much stronger criteria than path coverage, which in turn is a much stronger criteria than statement coverage.
4) Function Coverage:
In this white box testing technique we try to identify how many program functions are covered by test cases. So, while providing function coverage, test cases can be written so as to exercise each of different functions in the code.
Advantages of function coverage technique are:
1) Functions (like functions in C) are easier to identify in a program and hence it is easier to write test cases to provide function coverage.
2) Since functions are at higher level of abstraction than code, it is easier to achieve 100% function coverage.
3) It is easier to prioritize the functions for testing.
4) Function coverage provides a way of testing traceability, that is, tracing requirements through design, coding and testing phases.
5) Function coverage provides a natural transition to black box testing.
Function coverage can help in improving the performance as well as the quality of the product. For example, if in a networking software, we find that the function that assembles and disassembles the data packets is being used most often, it is appropriate to spend extra effort in improving the quality and performance of that function. Thus, function coverage can help in improving the performance as well as the quality of the product.
Conclusion:
Better code coverage is the result of better code flow understanding and writing effective test cases. Code coverage upto 40-50% is usually achievable. Code coverage of more than 80% requires enormous amount of effort and understanding of the code.
The multiple code coverage techniques described above are not mutually exclusive. They supplement and augment one another. While statement coverage can provide a basic comfort factor, path, decision and function coverage provide more confidence by exercising various logical paths and functions.
Many more Articles & Tutorials on White Box Testing
An expert on R&D, Online Training and Publishing. He is M.Tech. (Honours) and is a part of the STG team since inception.