Reputation: 5047
I'm studying the difference between these and cannot understand the difference. It seems the same to me. Arent they the same? The risk is coming from short-circuiting, isnt it?
Statement coverage does not call for testing logical operators. In C++ and C these operators are &&, ||, and ?:. Statement coverage cannot distinguish the code separated by logical operators from the rest of the statement. Executing any part of the code in a statement causes statement coverage to declare the whole statement fully covered. When logical operators avoid unnecessary evaluation (by short circuit), statement coverage gives an inflated coverage measurement.
void function(const char* string1, const char* string2 = NULL);
...
void function(const char* string1, const char* string2)
{
if (condition || strcmp(string1, string2) == 0) // Oops, possible null pointer passed to strcmp
...
}
Decision coverage - A disadvantage is that this metric ignores branches within Boolean expressions which occur due to short-circuit operators. For example, consider the following C/C++/Java code fragment:
if (condition1 && (condition2 || function1()))
statement1;
else
statement2;
Upvotes: 0
Views: 2385
Reputation: 2052
As far as I see, the risk in those examples is coming from the short-circuiting and they are indeed kind of equivalent. In some other case there could be a difference. For example consider the following case:
if (a>5)
b = 6
if (a<20)
c = 4 + b
For statement coverage it would be enough to test with a=10
(all lines will get executed) and the test would pass.
For decision coverage, it would be necessary to evaluate all the if statements to both true and false. The 100% decision coverage can be achieved for example with two tests a=30
and a=0
. The latter will fail as variable b
has not been set in that case.
So, decision coverage is more powerful; actually 100% decision coverage guarantees 100% statement coverage, but not vice versa. However, it is still possbile to construct examples where decision coverage is not enough to expose bugs, regardless whether the language has short-circuiting.
Let's consider a situation where there wouldn't be short-circuiting
if (a>0 || b>0)
c = 5 / b
Let's test this with input data a=0; b=1; a=0, b=0. The first one is enough to provide statement coverage. Both together provide decision coverage. But neither exposes the division by zero inside the if.
Upvotes: 1
Reputation: 8358
They are slightly different but both require short-circuit operations to demonstrate the problem as you correctly surmised.
Problem with Statement Coverage
if (complex-condition-evaluation-with-short-circuits)
doAction();
Statement coverage may record that you visited both of the above lines but you may never know if you executed a scenario where only parts of the complex condition were evaluated.
i.e. in your example was strcmp(...)
ever executed?
Issue with Branch Coverage
if (complex-condition-evaluation-with-short-circuits)
doAction();
else
doOtherAction();
Branch coverage may record that you pass through all paths in the (source) code but will ignore the branches that are part of the complex condition evaluation (as stated).
i.e. in your example branch coverage does not consider the ||
as an alternate branch and sees it as only two paths through the code when in fact it is four.
path1 (calls doAction) => condition1 == true, condition2 == true, function1() == ?
path2 (calls doAction) => condition1 == true, condition2 == false, function1() == true
path3 (calls doOtherAction) => condition1 == true, condition2 == false, function1() == false
path4 (calls doOtherAction) => condition1 == false, condition2 == ?, function1() == ?
I hope this helps
Upvotes: 1