Building on our previous post, we can take the coverage information generated by OpenCover and generate a report that shows us where our coverage is lacking.

We’ll use the ReportGenerator tool. In an approach that should be familiar by now, we start by adding a NuGet reference to the project and then writing a psake task that finds the report generator tool:

Task Requires.ReportGenerator {

    $script:reportGeneratorExe =
        resolve-path ".\packages\ReportGenerator.*\tools\ReportGenerator.exe"

    if ($reportGeneratorExe -eq $null)
        throw "Failed to find ReportGenerator.exe"

    Write-Host "Found Report Generator here: $reportGeneratorExe"

We need an empty folder for the coverage report, so we create one with a configuration task:

Task Configure.TestResultsFolder -Depends Requires.BuildDir {

    $script:testResultsFolder = join-path $buildDir testing.results
    Write-Host "Test results folder: $testResultsFolder"

    if (test-path $testResultsFolder) {
        remove-item $testResultsFolder -recurse -force -ErrorAction SilentlyContinue

    mkdir $testResultsFolder -ErrorAction SilentlyContinue | Out-Null

It’s worth noting that we try to remove the report target folder if it already exists, creating a new one each time - this is an easy way to try and ensure the file doesn’t contain any debris from the prior coverage report. By using -ErrorAction SilentlyContinue for both steps, we don’t abort the build if we can’t remove everything - keeping the directory tidy is helpful, but failing to do so shouldn’t be fatal. (I’ve found that sometimes, just sometimes, the script fails to remove one of the HTML files, perhaps because IIS still has the file open.)

Next, we write a Coverage.Report task that accumulates all the coverage reports generated by OpenCover and generates the report:

Task Coverage.Report -Depends Requires.ReportGenerator, Configure.OpenCoverReportFolder,
         Coverage.Tests {

    exec {
        & $reportGeneratorExe -reports:$testResultsFolder\*.opencover.xml

    $openCoverIndex = resolve-path $openCoverReportFolder\index.htm
    & $openCoverIndex

We use the wildcard *.opencover.xml to pick up all the coverage reports and ReportGenerator does the rest. We finish by automatically opening the report in the default browser - you may want to comment out this step if you find it distracting, or if you decide to include the coverage report in your continuous integration build.

The final result is a useful report. The front page summarizes the coverage achieved by our tests:

Even better, you can drill down to see more details of the test coverage, right down to the individual line of code:


blog comments powered by Disqus
Next Post
Sharpen The Saw #14  09 Oct 2017
Prior Post
Sharpen The Saw #13  02 Oct 2017
Related Posts
A Tale of Minification  17 Feb 2018
A Productivity Prompt for PowerShell  10 Feb 2018
Coverage History with Psake  18 Nov 2017
Tracking time with Psake  11 Nov 2017
The day my Psake build broke  04 Nov 2017
NuGet, .NET Core and Psake  28 Oct 2017
.NET Core with Psake  21 Oct 2017
Test Coverage with Psake  30 Sep 2017
NuGet packaging with Psake  23 Sep 2017
Semantic versioning with Psake  16 Sep 2017
More powershell posts »
Related Pages
October 2017 archive