Daniel Palme

Daniel Palme

.NET consultant from Germany.

Blog > MSBuild - Code Coverage Analysis with PartCover and ReportGenerator

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

SampleApplication_VS2010.zip
SampleApplication_VS2008.zip


Subscribe to RSS Feed

 

Related posts

 

New comment

:

:

:

:

 

Comments

#1
DaEarl

DaEarl

02/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

 
#2
Daniel

Daniel

02/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
 
#3
rybolt

rybolt

04/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.
 
#4
Rybolt

Rybolt

04/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" />
 
#5
Daniel

Daniel

04/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.
 
#6
Rybolt

Rybolt

04/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.
 
#7
Daniel

Daniel

04/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.
 
#8
Rybolt

Rybolt

04/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.
 
#9
Daniel

Daniel

04/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.
 
#10
Dmytro

Dmytro

07/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
 
#11
Laimis

Laimis

09/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!
 
#12
suma

suma

11/06/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.
 
#13
Daniel

Daniel

11/06/2014

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

Suma

11/07/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:+[*]*




 
#15
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.