When I am writing tests I find it useful to have a coverage tool. Since NCover is no longer free I have started to use OpenCover I like OpenCover, it is a mature product that works well and as a free open source project its great for my personal projects. I also use the excellent ReportGenerator to format the output from OpenCover.

I recently needed to use a coverage tool to work with some xUnit tests and I knocked together some scripts but it turned out to be a bit more complex than I thought.

For this example I used an example app “MyApp” which contained a class called ObjectUnderTest and I wrote some tests in MyApp.Tests. I’ve installed OpenCover to its default location in C:\Users\derek.wilson\AppData\Local\Apps\OpenCover and ReportGenerator does not really install so I have just copied it into a folder called ReportGenerator in the same location as OpenCover. xUnit is also installed in its default location.

The command script to run the tests that I first put together looked like this

C:\Users\derek.wilson\AppData\Local\Apps\OpenCover\opencover.console -output:coverage.xml -target:"C:\Program Files (x86)\xUnit\xunit.console.clr4.exe" -targetargs:"MyApp.Tests\bin\Debug\MyApp.Tests.dll" -filter:"+[*]MyApp.* -[*.Tests]*"
C:\Users\derek.wilson\AppData\Local\Apps\ReportGenerator\bin\reportgenerator coverage.xml .\coverage
start .\coverage\index.htm

The mechanism here is that I get “opencover.console” to use “xunit.console.clr4.exe” to run the tests in the MyApp.Tests.dll, however all we see is this

xUnit.net console test runner (64-bit .NET 4.0.30319.269)
Copyright (C) 2007-11 Microsoft Corporation.

xunit.dll:     Version 1.8.0.1549
Test assembly: C:\POC\MyApp\MyApp.Tests\bin\Debug\MyApp.Tests.dll

3 total, 0 failed, 0 skipped, took 0.251 seconds
Committing...
No results - no assemblies that matched the supplied filter were instrumented (missing PDBs?)

In the documentation for OpenCover it does recommend that the profiler be registered so I registered the 64bit version as I was running on a 64 bit OS.

regsvr32 C:\Users\derek.wilson\AppData\Local\Apps\OpenCover\x64\OpenCover.Profiler.dll

However it still did not work. It turns out that I needed to specify the xUnit noshadow switch, I did this in an xunit project file as I was going to need one anyway as soon as I had more than a few DLLs, like this

<?xml version="1.0" encoding="utf-8"?>
<xunit>
  <assemblies>
    <assembly filename="MyApp.Tests\bin\Debug\MyApp.Tests.dll" shadow-copy="false" />
  </assemblies>
</xunit>

I then changed the script to use the xunit project file like this

C:\Users\derek.wilson\AppData\Local\Apps\OpenCover\opencover.console -output:coverage.xml -target:"C:\Program Files (x86)\xUnit\xunit.console.clr4.exe" -targetargs:"MyApp.xunit" -filter:"+[*]MyApp.* -[*.Tests]*"
C:\Users\derek.wilson\AppData\Local\Apps\ReportGenerator\bin\reportgenerator coverage.xml .\coverage
start .\coverage\index.htm

And it started to work – like this

xUnit.net console test runner (64-bit .NET 4.0.30319.269)
Copyright (C) 2007-11 Microsoft Corporation.

xunit.dll:     Version 1.8.0.1549
Test assembly: C:\MyApp\MyApp.Tests\bin\Debug\MyApp.Tests.dll

3 total, 0 failed, 0 skipped, took 0.546 seconds
Committing...
Visited Classes 1 of 1 (100)
Visited Methods 1 of 1 (100)
Visited Points 9 of 9 (100)
Visited Branches 4 of 4 (100)

==== Alternative Results (includes all methods including those without corresponding source) ====
Alternative Visited Classes 1 of 1 (100)
Alternative Visited Methods 6 of 6 (100)

C:\MyApp>C:\Users\derek.wilson\AppData\Local\Apps\ReportGenerator\bin\reportgenerator coverage.xml .\coverage
Loading report 'coverage.xml'
 Initiating parser for OpenCover
  Current Assembly: MyApp
Analyzing 1 classes
 Creating report 1/1 (Assembly: MyApp, Class: MyApp.ObjectUnderTest)
Creating summary
Report generation took 0 seconds

Not only did it work I did not have to run the script as an administrator