Branch coverage on Switch statements broken?
Branch coverage on Switch statements broken?
I've written a small test covering a 'switch' statement in C#, and I would like to understand how the branch coverage is calculated. The code is as follows:
using System;
namespace NCoverTest { public static class Test { public static void DoTestSwitch(int i) { switch (i) { case 0: Console.Out.WriteLine("Zero"); break; case 1: Console.Out.WriteLine("One"); break; case 2: Console.Out.WriteLine("Two"); break; default: Console.Out.WriteLine("Default"); break; } } } }
The code is executed a single time with an argument of 2. The NCover Explorer reports that said execution has covered 100% (1 of 1) branches.
I've verified that the compiled MSIL has the expected jump table for the switch statement, as well as 5 separate br.s instructions.
This was compiled to .NET version 2.0 using Visual Studio 2010SP1 in Debug mode. The version of NCover installed is 3.4.18.6937.
Can anyone explain how the given branch coverage metric is calculated?
If I need to answer any more questions about our setup, please let me know.
Thank you.
RE: Branch coverage on Switch statements broken?
Hi Robert,
Thanks for posting this information.
One of our developers added a similar branch coverage test to the beta of NCover 4, our next major release.
In his branch coverage test, 3 of 6 branch points are covered, and 5 of 11 sequence points are covered.
If the visit count for your method is 1, you should only have one path through the switch statement covered, which isn't accurately represented as 100% coverage.
Thanks for helping us understand this issue.
NCover Support
RE: Branch coverage on Switch statements broken?
Thank you for your prompt reply.
Please be aware that switch
statements can compile into three different MSIL instruction sets, and all three are broken in NCover 3.
The first case was covered above, a small-ish case
set indexed on integers.
The second case is a small-ish case
set indexed on strings. This compiles into a bunch of branching instructions based off the string Equality
operation. Here is some sample code:
public void SimpleStringSwitchStatement(string value)
{
var i = 0;
switch (value)
{
case "TestOne":
i++;
Console.WriteLine("Test1");
break;
case "TestTwo":
i--;
Console.WriteLine("Test2");
break;
case "TestThree":
i++;
Console.WriteLine("Test3");
break;
default:
i--;
Console.WriteLine("Default");
break;
}
Console.WriteLine(i);
}
NCover reports this method as having 5 branches (I count 6). When called with an argument of "TestOne", NCover reports 3 of 5 branches executed (60%). This should be 3 of 6 branches executed (50%).
The third case is a large-ish case
set. The MSIL generated puts all case
values into a Dictionary
object along with an offset, and then uses the offset as a jump index in a switch
MSIL instruction. Here is some sample code:
public void SimpleLargeSwitchStatement(string value)
{
switch (value)
{
case "TestOne":
Console.WriteLine("Test1");
break;
case "TestTwo":
Console.WriteLine("Test2");
break;
case "TestThree":
Console.WriteLine("Test3");
break;
case "TestFour":
Console.WriteLine("Test4");
break;
case "TestFive":
Console.WriteLine("Test5");
break;
case "TestSix":
Console.WriteLine("Test6");
break;
case "TestSeven":
Console.WriteLine("Test7");
break;
case "TestEight":
Console.WriteLine("Test8");
break;
case "TestNine":
Console.WriteLine("Test9");
break;
case "TestTen":
Console.WriteLine("Test10");
break;
default:
Console.WriteLine("Default");
break;
}
Console.WriteLine(value);
}
Here I count 13 branches. Calling with an argument of "TestOne", there should be three branches covered (3 of 13, or 23%). NCover reports 6 of 6 branches covered (100%).
Thank you.
RE: Branch coverage on Switch statements broken?
Hi Robert,
Thanks for the additional info and the sample code.
I'll pass these cases along to the development team, as well.
We appreciate your help in improving our branch coverage!
Regards,
NCover Support