Why my coverage didn't reach 100%
Some time ago I encountered an interesting feature (!) of the test engine within Visual Studio 2005. I had written a couple of unit tests for some code I had developed. After running the tests I reviewed the coverage results. I'd expected to reach 100% coverage. Instead, the coverage results showed me that I had missed a code block.
By clicking on the method name containing the non-covered code block, I went straight to the code. It looked like this:
private object GetTypedValue(string type, string value)
{
// Return the correct type.
switch (type)
{
case "bigint":
return Int64.Parse(value);
case "bit":
return bool.Parse(value);
case "char":
case "nchar":
case "ntext":
case "nvarchar":
case "text":
case "varchar":
return value;
case "datetime":
case "smalldatetime":
return DateTime.Parse(value);
case "decimal":
return decimal.Parse(value);
case "float":
case "real":
return float.Parse(value);
case "int":
return int.Parse(value);
case "money":
case "smallmoney":
return SqlMoney.Parse(value);
case "smallint":
return Int16.Parse(value);
case "xsd:base64Binary":
return Convert.FromBase64String(value);
default:
throw new NotSupportedException("…");
}
}
At first glance I noticed nothing strange. All my code paths seemed to have been executed during the tests. Then I noticed that the begin (“{“) and end (“}”) tags of my method were marked as covered but the same tags specifying the beginning and end of the switch statement were not.
A college of mine (thanks Ka Wai) pointed me to the Microsoft forums where this problem is discussed. It seems this problem can occur when using a foreach or switch statement. (The problem with the switch statement will only occur when you have 6 or more case statements.)
When using the coverage capabilities of Visual Studio 2005, some code is compiled with your source code. The CLR is generating some extra code under the covers that is used for the foreach and switch statements. This has to do with some optimization the CLR makes.
So some extra code is run when the tests are executed. The code coverage tool is therefore actually telling the truth. Some of the IL code isn’t actually covered by the unit tests. Unfortunately the not covered IL code doesn’t correspond with a specific statement in your code so it won’t show up in Visual Studio.
If you really want to achieve 100% coverage you can use a for loop instead of a foreach statement and a nested if-else construction instead of the switch statement. But I don’t recommend it. In my opinion, you should never change your code in favor of a test or coverage. You should rather favor readability and maintainability of the code.