MSBuild - Code Coverage Analysis with PartCover and ReportGenerator

 

Ever since NCover has not been free any more, I use PartCover, which is available under the GNU General Public License (GPL).

In this post I will show how you could generate a nice 'Code Coverage Analysis' report by using ReportGenerator and how you could integrate PartCover and ReportGenerator in your MSBuild script.

Generating the report

First you have to run MSTest (or NUnit, or whatever you use for testing) within PartCover. The command could look this:
PartCover.exe --target "MS_TEST_PATH\MSTest.exe" --target-args "/noisolation /testcontainer:YOUR_ASSEMBLIES" --include "NAMESPACES" --output "partcover.xml"

PartCover generates a XML file containing the coverage information.
ReportGenerator converts this XML file into a readable HTML report. ReportGenerator can transform multiple XML files at once, so you could also merge multiple coverage results into one HTML report. The command could look like this:
ReportGenerator.exe "report1.xml;report2.xml" "OUTPUT_DIRECTORY"

Screenshot

MSBuild

Now lets have a look at the MSBuild target which runs PartCover. Since PartCover uses some COM stuff, we register a DLL before PartCover can be executed. After PartCover has completed, the DLL is unregistered again. That way we don't have to install PartCover.

<Target Name="Test" DependsOnTargets="Clean; Compile">
  <MakeDir Directories="$(ReportsPath)\coverage" />
  <Exec Command="regsvr32.exe /s lib\PartCover\PartCover.CorDriver.dll" />
  <Exec Command="lib\PartCover\PartCover.exe --target "$(MSTestPath)\MSTest.exe" --target-args "/noisolation /testcontainer:$(TestFiles)" --include "$(ReportNamespaces)" --output "$(ReportsPath)\coverage\partcover.xml"" ContinueOnError="true" />
  <Exec Command="regsvr32.exe /u /s lib\PartCover\PartCover.CorDriver.dll" />
</Target>

And the MSBuild that executes ReportGenerator:

<Target Name="Report" DependsOnTargets="Test">
  <Exec Command="lib\ReportGenerator\ReportGenerator.exe "$(ReportsPath)\coverage\partcover.xml" "$(ReportsPath)\coverage\HTML"" ContinueOnError="true" />
</Target>

SampleApplication

I attached a sample application (based on MSTest) which should work without any modifications on Windows Vista and Windows 7 (32 and 64 Bit) with Visual Studio 2008 Professional installed to the default directory. For Windows XP you have to adjust the path to MSTest.

Open a "Visual Studio Command Promt" with administrator privileges and execute the following command to run the MSBuild script:
msbuild build.proj

Updates

28.06.2010: When you use PartCover 4, replace the first script with the following:

<Target Name="Test" DependsOnTargets="Clean; Compile">
  <MakeDir Directories="$(ReportsPath)\coverage" />
  <Exec Command="regsvr32.exe /s lib\PartCover\PartCover.dll" />
  <Exec Command="lib\PartCover\PartCover.exe --target "$(MSTestPath)\MSTest.exe" --target-args "/noisolation /testcontainer:$(TestFiles)" --include "$(ReportNamespaces)" --output "$(ReportsPath)\coverage\partcover.xml"" ContinueOnError="true" />
  <Exec Command="regsvr32.exe /u /s lib\PartCover\PartCover.dll" />
</Target>

Downloads

Feedly Feedly Tweet


Related posts


Comments


Daniel

Daniel

11/10/2014

@Suma: I took a look at the report generated by PartCover. This file contains some data, but not enough to create a full coverage report. Please compare with this sample report: http://reportgenerator.codeplex.com/SourceControl/latest#trunk/ReportGeneratorTest/files/Reports/CSharp/Partcover4.0.10620.xml You could try using OpenCover instead. PartCover is not actively developed any more.


Suma

Suma

11/7/2014

@ Daniel Thanks for the immediate reply. I will try to attach the xml file from Partcover and html file generated. Cmd line used for report generating: "C:\Program Files\ReportGenerator\bin\ReportGenerator.exe" -reports:"C:\CIVIM\IEQFrame\CodeCoverage.xml" -targetdir:"C:\CIVIM\IEQFrame\Reports" -reporttypes:Latex;HtmlSummary -sourcedir:"C:\Program Files\IeQFrame" -filters:+[*]*


Daniel

Daniel

11/6/2014

@Suma: Can you provide me the XML file generated by PartCover?


suma

suma

11/6/2014

Hi All, I am trying to convert the xml file from PartCover to html report. But I am getting a html file with no data inside. When I try to find the Code Coverage from PartCover console,its showing results in(%) in the console. XML file generated using PartCover is also having some data in it. I don't know why the html report becomes blnak with no data. Please help me out.


Laimis

Laimis

9/13/2011

I know this is an old post, but I found it just now and it was very useful on getting running fast with opencover and graphing the results. Thank you very much!


Dmytro

Dmytro

7/25/2010

Hi Danile, great tool! I am not from world of coding, mostly I am making testing, as a result I have several different ideas/problems. 1. It would be convinient if output was generated(serilaised) in some xml. And than to this xml applied html transfomation. 2. Is there way to make generation faster? I don't have enough in partCover working with multyReport, when I have several generated report and only need coverage. Your tool takes more than 20 minutes for parsing two small coverages. Seems it could be faster if this xmls will be merged first, and than analysed source code. Now it looks file parsing is used twice. If I will have twenty or more xml-outputs files, it will be much bigger. 3. Sometimes I am testing already compiled product, and I don't have exatly the same source code. I had FileNotFoundException, until i haven't replaced source pathes in partCover output files. Is the way to use reflactior or other tool for getting this out. Thanks Daniel for really interesting tool. Dmytro


Daniel

Daniel

4/30/2010

@Rybolt: Thanks for your feedback. ReportGenerator reads a source file line by line and determines the coverage for each line from the PartCover report by its line number. That means ReportGenerator does not know about the scope of the current line. To determine the coverage of a specific method, the scope of a line is important, but that would mean some additional parsing. I'm not sure if this is worth the effort.


Rybolt

Rybolt

4/29/2010

Feature request: Something really neat would be, on the results page, displaying the class, you have summary and then the code marked green/red. It'd be super cool if under the summary, you had a method/property summary, with % per method/property. now the really cool part would be to have all the method/property sections actually be href links ( i.e. myfooclass.htm#fooMethod) , that would take you right to method/property in your code view. Just my $.02, by far the best output I've seen for Partcover.


Daniel

Daniel

4/28/2010

@Rybolt: I'm currently working on a workaround. If a unexecuted method occurs I try to get the information from the source files. As described in my blog post this is not possible with some regular expression. Instead I am using the Refactoring Library of SharpDevelop. A new release will be available within the next week. Stay tuned.


Rybolt

Rybolt

4/28/2010

@Daniel Yes, I realized after looking at the code, and it seems your reportgenerator is behaving _well_ , and maybe the .xml output from PartCover can be more explicit about no_exec methods. At any rate, I understand how deep the problem lies now, I'll read your blogpost thx for that link.


Daniel

Daniel

4/28/2010

@Rybolt: A while ago I blogged about this issue: http://www.palmmedia.de/Blog/2010/2/15/partcover-coverage-of-unexecuted-methods It's not that easy to fix.


Rybolt

Rybolt

4/27/2010

I found your problem. It is same problem posted on Partcover SF webpage. You don't account for methods with an empty or no <pt>, and this makes your code coverage data higher than it should be. These methods were never exercised/covered so they should be visit=0 and have 'red' to indicate so. example: (the first method is fine, however, 2nd one will be considered noncoverable code by your program) <Method name="get_EventData" sig="unsigned byte[] ()" bodysize="8" flags="0" iflags="0"> <pt visit="2" pos="0" len="7" fid="2" sl="77" sc="17" el="77" ec="37" /> </Method> <Method name="get_EventMessage" sig="string ()" bodysize="8" flags="0" iflags="0" />


rybolt

rybolt

4/27/2010

your total % coverage is wrong in the files provided in download. you should state that, i know partcover had some erroneous xslt, but may have since been fixed. i.e it said 100% coverage, but obv. green blocks were not on all my coverable code, and i checked tests, and verified code wasn't getting executed.


Daniel

Daniel

2/12/2010

Hi DaEarl, well the name 'TestFiles' is not chosen wisely. But you can use ' /testcontainer' as delimter. See help of MSTest (MSTest /help on the command promt). Regards


DaEarl

DaEarl

2/12/2010

Hi. First thanks for this. It works great. I was just wondering what is the delimiter for TestFiles? Since it is in plural form I assume that I can specify more than one assembly here? I have tried ; and , with no good result. BR