I\'m using dotCover to analyze code coverage of my unit tests, and I\'m getting some strange results... I have an iterator method for which the coverage is not complete, but the
In addition to your question and the in detail answer, I had the following behaviour.
// less than 100% coverage
public static IEnumerable<T> ForEachYieldDo<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var x in source)
{
action(x);
yield return x;
}
}
// 100% code coverage
public static IEnumerable<T> ForEachSelectDo<T>(this IEnumerable<T> source, Action<T> action)
{
return source.Select(x =>
{
action(x);
return x;
});
}
Both functions have the same behaviour. The action is only executed, if the item is processed. If the retrieval of the items is stopped, the action is not executed.
One of the problems with iterator methods is that the compiler generates a rather large and complex state machine to manage the deferred execution of the code within the iterator method. This usually generates a class or two. These classes are meant to deal with the general case and not your specific case, so there's likely at least a bit of code in there that is never used. You can look at what is generated by looking at your assembly with tools like ILSpy, JustDecompile or Reflector. It will show the classes in your assembly generated by the C# compiler (usually class names containing '<', etc.)
What the profiler knows about is how the PDB associates to your code and despite the possibility that all of the code you wrote possibly being executed, there's still a possibility that not all of the code generated by the compiler got executed. The profiler probably doesn't know this and simply says that a certain percentage (less than 100) of a particular iterator method got executed.
One of the things likely getting generated is exception handling code. Because the compiler doesn't know your code won't or possibly can't generate an exception it will still generate code to compensate for an exception--it needs to keep it's state from becoming corrupt. I bet if you included a way to throw an exception in various places in your iterator method based on some flag and ran the method twice (once without exceptions and once with exceptions in the same run) that the percentages would be different--likely higher because the generated exception handling code would then be exercised.
The fact that the end of the method "seems" to not be executed is likely because that code is part of a different method in the state machine that gets executed and the compiler never generates an association from that generated code to the code in your class.
UPDATE: to get a better understanding of what the compiler is doing and see an example of the type of code it generates see section 10.14 Iterators in the C# spec (http://www.microsoft.com/en-us/download/details.aspx?id=7029)