GithubHelp home page GithubHelp logo

danielpalme / reportgenerator Goto Github PK

View Code? Open in Web Editor NEW
2.4K 50.0 271.0 108.03 MB

ReportGenerator converts coverage reports generated by coverlet, OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov or lcov into human readable reports in various formats.

Home Page: https://reportgenerator.io

License: Apache License 2.0

C# 82.24% JavaScript 0.41% PowerShell 0.85% F# 0.20% Batchfile 0.10% CSS 10.63% Java 0.15% TypeScript 5.28% HTML 0.07% Shell 0.04% C++ 0.02%
code-coverage testing tdd-utilities reporting dotnet-core

reportgenerator's Introduction

ReportGenerator
ReportGenerator

Powerful code coverage visualization

GitHub license CI-CD

ReportGenerator converts coverage reports generated by coverlet, OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov, or lcov into human readable reports in various formats.

The reports show the coverage quotas and also visualize which lines of your source code have been covered.

ReportGenerator supports merging several coverage files into a single report.

Browse example HTML report

Input and output

License

Getting started

ReportGenerator is a commandline tool which works with full .NET Framework and .NET Core.
Use the online configuration tool to get started quickly.

Install the package matching your platform and needs

Package Platforms Installation/Usage
ReportGenerator

NugetNuget
.NET Core >=6.0
.NET Framework 4.7
Use this package if your project is based on .NET Framework or .NET Core and you want to use ReportGenerator via the command line or a build script.

Usage
dotnet $(UserProfile).nuget\packages\reportgenerator\x.y.z\tools\net8.0\ReportGenerator.dll [options]
$(UserProfile).nuget\packages\reportgenerator\x.y.z\tools\net8.0\ReportGenerator.exe [options]

$(UserProfile)\.nuget\packages\reportgenerator\x.y.z\tools\net47\ReportGenerator.exe [options]
dotnet-reportgenerator-globaltool

NugetNuget
.NET Core >=6.0 Use this package if your project is based on .NET Core and you want to use ReportGenerator as a (global) 'DotnetTool'.

Installation
dotnet tool install -g dotnet-reportgenerator-globaltool

dotnet tool install dotnet-reportgenerator-globaltool --tool-path tools

dotnet new tool-manifest
dotnet tool install dotnet-reportgenerator-globaltool

Usage
reportgenerator [options]
tools\reportgenerator.exe [options]
dotnet reportgenerator [options]
ReportGenerator.Core

NugetNuget
.NET Standard 2.0 Use this package if you want to write a custom plugin for ReportGenerator or if you want to call/execute ReportGenerator within your code base.

Plugin development
Custom reports
Custom history storage
Azure DevOps extension

Visual Studio Marketplace VersionVisual Studio Marketplace Installs - Azure DevOps Extension
.NET Core >=6.0 Add the Azure DevOps extension to your build pipeline.
Learn more
GitHub Actions .NET Core >=6.0 Add the GitHub Action to your build pipeline.
Learn more

Usage / Command line parameters

Use the online configuration tool to get started quickly.

Parameters:
    ["]-reports:<report>[;<report>][;<report>]["]
    ["]-targetdir:<target directory>["]
    [["]-reporttypes:<Html|HtmlSummary|...>[;<Html|HtmlSummary|...>]["]]
    [["]-sourcedirs:<directory>[;<directory>][;<directory>]["]]
    [["]-historydir:<history directory>["]]
    [["]-plugins:<plugin>[;<plugin>][;<plugin>]["]]
    [["]-assemblyfilters:<(+|-)filter>[;<(+|-)filter>][;<(+|-)filter>]["]]
    [["]-classfilters:<(+|-)filter>[;<(+|-)filter>][;<(+|-)filter>]["]]
    [["]-filefilters:<(+|-)filter>[;<(+|-)filter>][;<(+|-)filter>]["]]
    [["]-verbosity:<Verbose|Info|Warning|Error|Off>["]]
    [["]-title:<title>["]]
    [["]-tag:<tag>["]]
    [["]-license:<license>["]]

Explanations:
   Reports:            The coverage reports that should be parsed (separated by semicolon).
                       Globbing is supported.
   Target directory:   The directory where the generated report should be saved.
   Report types:       The output formats and scope (separated by semicolon).
                       Values: Badges, Clover, Cobertura, CsvSummary, 
                       MarkdownSummary, MarkdownSummaryGithub, MarkdownDeltaSummary
                       OpenCover
                       Html, Html_Light, Html_Dark, Html_BlueRed
                       HtmlChart, HtmlInline, HtmlSummary, Html_BlueRed_Summary
                       HtmlInline_AzurePipelines, HtmlInline_AzurePipelines_Light, HtmlInline_AzurePipelines_Dark
                       JsonSummary, CodeClimate, Latex, LatexSummary, lcov, MHtml, SvgChart, SonarQube, TeamCitySummary
                       TextSummary, TextDeltaSummary
                       Xml, XmlSummary
   Source directories: Optional directories which contain the corresponding source code (separated by semicolon).
                       The source directories are used if coverage report contains classes without path information.
                       Globbing is not supported.
   History directory:  Optional directory for storing persistent coverage information.
                       Can be used in future reports to show coverage evolution.
   Plugins:            Optional plugin files for custom reports or custom history storage (separated by semicolon). 
   Assembly filters:   Optional list of assemblies that should be included or excluded in the report.
   Class filters:      Optional list of classes that should be included or excluded in the report.
   File filters:       Optional list of files that should be included or excluded in the report.
                       Exclusion filters take precedence over inclusion filters.                      
                       Wildcards are allowed.
   Verbosity:          The verbosity level of the log messages.
                       Values: Verbose, Info, Warning, Error, Off
   Title:              Optional title.
   Tag:                Optional tag or build version.
   License:            Optional license for PRO version. Get your license here: https://reportgenerator.io/pro

Default values:
   -reporttypes:Html
   -assemblyfilters:+*
   -classfilters:+*
   -filefilters:+*
   -verbosity:Info

Examples:
   "-reports:coverage.xml" "-targetdir:C:\report"
   "-reports:target\*\*.xml" "-targetdir:C:\report" -reporttypes:Latex;HtmlSummary -title:IntegrationTest -tag:v1.4.5
   "-reports:coverage1.xml;coverage2.xml" "-targetdir:report" "-sourcedirs:C:\MyProject" -plugins:CustomReports.dll
   "-reports:coverage.xml" "-targetdir:C:\report" "-assemblyfilters:+Included;-Excluded.*"

.netconfig support

All the above parameters can also be persisted in a .netconfig file, under a [ReportGenerator] section. Examples:

[ReportGenerator]
	reports = coverage.xml
	targetdir = "C:\\report"
	reporttypes = Latex;HtmlSummary
	assemblyfilters = +Test;-Test
	classfilters = +Test2;-Test2

All the plural options can also be specified as multiple singular entries, like:

[ReportGenerator]
	report = coverage1.xml
	report = coverage2.xml
	reporttype = Latex
	reporttype = HtmlSummary
	assemblyfilter = +Test
	assemblyfilter = -Test
	classfilter = +Test2
	classfilter = -Test2
	filefilter = +cs
	filefilter = -vb
	sourcedir = src
	sourcedir = test

Adding/removing values is trivial using the dotnet-config CLI:

# set a single-valued variable
dotnet config reportgenerator.reporttypes Latex;HtmlSummary
# add to multi-valued variable
dotnet config --add reportgenerator.report coverage3.xml
# clear all multi-valued entries for a variable
dotnet config --unset-all reportgenerator.assemblyfilter

Of course it's equally trivial to just edit the .netconfig file by hand.

MSBuild

A MSBuild task also exists:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Coverage" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <ItemGroup>
    <PackageReference Include="ReportGenerator" Version="x.y.z" />
  </ItemGroup>
  <Target Name="Coverage">
    <ItemGroup>
      <CoverageFiles Include="OpenCover.xml" />
    </ItemGroup>
    <ReportGenerator ProjectDirectory="$(MSBuildProjectDirectory)" ReportFiles="@(CoverageFiles)" TargetDirectory="report" ReportTypes="Html;Latex" HistoryDirectory="history" Plugins="CustomReports.dll" AssemblyFilters="+Include;-Excluded" VerbosityLevel="Verbose" />
  </Target>
</Project>

The MSBuild task parameters can be complemented with the .netconfig, if used. That means that parameters can be omitted if they are provided via .netconfig, which is useful when reusing fixed settings across multiple projects in a solution, where the MSBuild task is only provided the dynamic values for the current project:

Given the following .netconfig:

[ReportGenerator]
  reporttypes = Html;Latex
  targetdirectory = report
  historydirectory = history
  assemblyfilters = +Include;-Excluded
  verbosityLevel = Verbose

The above target could be simplified as:

  <Target Name="Coverage">
    <ItemGroup>
      <CoverageFiles Include="OpenCover.xml" />
    </ItemGroup>
    <ReportGenerator ProjectDirectory="$(MSBuildProjectDirectory)"
                     ReportFiles="@(CoverageFiles)" 
                     Plugins="CustomReports.dll" />
  </Target>

Supported input and output file formats

ReportGenerator supports several input and output formats.
The wiki explains the different output formats or you can download sample reports of all supported output formats.
If you need a custom format, you can create a plugin.

Input formats Output formats


  • Html, Html_Light, Html_Dark, Html_BlueRed, HtmlSummary, HtmlChart, HtmlInline, HtmlInline_AzurePipelines, HtmlInline_AzurePipelines_Light, HtmlInline_AzurePipelines_Dark, MHtml
  • Clover
  • Cobertura
  • OpenCover (PRO version only)
  • SonarQube
  • TeamCitySummary
  • lcov
  • Xml, XmlSummary
  • JsonSummary
  • Latex, LatexSummary
  • TextSummary, TextDeltaSummary
  • CsvSummary
  • MarkdownSummary, MarkdownSummaryGithub, MarkdownDeltaSummary
  • SvgChart
  • Badges
  • Custom reports

Screenshots

The screenshots show two snippets of the generated reports:

Screenshot 1

Screenshot 2

Badges
Badges in SVG format can be generated if -reporttypes:Badges is used:

Example: Sample badge

See all badges

Resources

Visual Studio extensions

The following extensions exist to visualize coverage in Visual Studio:

Name Coverage tool Links
Run Coverlet Report VS2022 coverlet GitHub
Marketplace
FineCodeCoverage coverlet, OpenCover GitHub
Marketplace

Links

Download statistics

Nuget Nuget Nuget

Visual Studio Marketplace Installs - Azure DevOps Extension GitHub All Releases Chocolatey

Trends

Nuget downloads
GitHub stars

Contact

Author: Daniel Palme
Blog: www.palmmedia.de
Twitter: @danielpalme

reportgenerator's People

Contributors

304notmodified avatar abbotware avatar acesiddhu avatar ahsonkhan avatar azure-pipelines[bot] avatar danielpalme avatar david-driscoll avatar dependabot[bot] avatar eddynaka avatar elajeunesse avatar hunterjm avatar jeremybeier avatar jm3105 avatar karanjitsingh avatar knom avatar kurattila avatar kzu avatar lancehuang2021 avatar loganek avatar lorilatschki avatar manfred-brands avatar markpflug avatar martincostello avatar meir017 avatar naveensrinivasan avatar petli avatar rjasica avatar sbolotovms avatar suremaker avatar tmulkern avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reportgenerator's Issues

History report only showing earliest coverage

The new history graphs look like they'd be really good, however I can't seem to get them to work.
I've specified the history directory in the command line, and I can see the xml file being created in that folder (and I've run the report generator multiple times, so have multiple xml files in the history folder), but when I look at the graph it only shows the markers for the earliest coverage report.
I've tried deleting out some of the files etc. (to see if it's just a bad file in there), but no matter what I do I still only get the markers on the graph for the earliest coverage data in the history folder.

Report fails when using partial C# classes

Hi,

Great tool. Thank you for providing it.

When developing ASP.Net MVC apps, I have been using a pattern for my viewmodels where I have the main viewmodel class in ControllerViewmodel.cs for a given Controller . Then when I need a specific viewmodel for a particular action of the controller, I use a partial class as an extension and put the new viewmodel class with this extension in ControllerViewmodel_action.cs. This works really well for organizing the code, but what I have found is that the generated coverage report claims that the portion of ControllerViewmodel found in ControllerViewmodel_action.cs is not covered.

I am also using OpenCover.UI to see the coverage in the GUI of VS. That tool properly shows that the partial class of ControllerViewmodel that is found in ControllerViewmodel_action is covered properly. So this must be a problem with the report generation rather than a problem with OpenCover.

Here is a sample of the C# code that represents what I am doing:

In ControllerViewmodel.cs:

public partial class ControllerViewmodel {
    public int X { get; set; }
    public ControllerViewmodel {
          X = 1;
    }
}

Then in ControllerViewmodel_action.cs

public class ControllerViewmodel_action {
    public int X {get; set; }
    public int Y {get; set; }
}

public partial class ControllerViewmodel {
     public ControllerViewmodel_action getY () {
           var returnVM = new ControllerViewmodel_action();
           returnVM.X = X;
           returnVM.Y = 2 * X;
     }
}

I then have unit tests that will test the code in ControllerViewmodel_Action.cs 100%. When I run OpenCover in OpenCover.UI, it correctly shows me that all the code in ControllerViewmodel_Action.cs is covered. But when I run the OpenCover on the same code and generate the report with ReportGenerator, the only lines of code that are shown as being cover are those of the ControllerViewmodel_action class. The getY function is shown as not being covered.

Thanks
Greg

System.IO.PathTooLongException

Hi,
I'm using ReportGenerator 2.1.2.0
When I try generate report for my web site project I get exception System.IO.PathTooLongException
My web site project has karma tests and while installing npm modules I get really long paths, e.g.

C:\VSC\administration\CAT.Administration.Website\Angular\tests\node_modules\karma-phantomjs-launcher\node_modules\phantomjs\node_modules\request\node_modules\form-data\node_modules\combined-stream\node_modules\delayed-stream\lib\delayed_stream.js

Here is stacktrace https://gist.github.com/PavelAgejkin/d0d8977faf302c908dfc
P.s. I found similar issue: http://reportgenerator.codeplex.com/workitem/9671

Is wiki disabled for editing intentionally?

Is wiki disabled for editing intentionally?
I want to add the info about different ReportTypes to FAQ:
HtmlSummary creates a single HTML file summary.htm(without links).
Html creates the index.htm that has summary (with links) and detailed reports for each class.

FR: default value of grouping specified at generation time

HI

I don't see a way to set the default value of the grouping slider on the html report. It would be very useful to have the grouping slider start all the way to the right as that is my preferred method of looking at the report.

I would be happy to specify this on the report generation command line.

Thanks
Greg

Turn ReportGenerator into a single EXE with no dependent assemblies.

Reference:
http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application

  1. Move everything from ReportGenerator into ReportGenerator.Core.dll
    a. Expose a new entry point Main Method.
  2. Simplify ReportGenerator.exe to
    a. Reference ReportGenerator.Core.dll
    b. Extent of source code in ReportGenerator.exe
internal static int Main(string[] args)
{
   return ReportGenerator.Core.Main(args);
}

This will keep your stuff at status quo, as RerportGenerator.exe still exists for everyone, with the addition of a new ReportGenerator.Core.DLL.

This will allow me to make my own FatReportGenerator.exe that has all the assemblies embedded as resources, thus making deployments my build servers less error prone. It turns into a single exe.

https://github.com/ghstahl/ReportGenerator

Generated report is empty

NUnit test results output has data populated however ReportGenerator is generating an empty report.

Could be a user error but haven't been able to see where I'm going wrong.

NUnit Version 2.6.4
OpenCover Version 4.5.3522

Results XML

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!--This file represents the results of running a test suite-->
<test-results name="C:\Projects\Test\src\Search.Tests\bin\Debug\Search.Tests.dll" total="12" errors="0" failures="0" not-run="0" inconclusive="0" ignored="0" skipped="0" invalid="0" date="2015-05-28" time="17:20:32">
  <environment nunit-version="2.6.4.14350" clr-version="2.0.50727.5485" os-version="Microsoft Windows NT 6.1.7601 Service Pack 1" platform="Win32NT" cwd="C:\dev\tools\opencover" machine-name="LON03906" user="tim.clifford" user-domain="EMEA" />
  <culture-info current-culture="en-GB" current-uiculture="en-US" />
  <test-suite type="Assembly" name="C:\Projects\Test\src\Search.Tests\bin\Debug\Search.Tests.dll" executed="True" result="Success" success="True" time="42.726" asserts="0">
    <results>
      <test-suite type="Namespace" name="Akqa" executed="True" result="Success" success="True" time="42.717" asserts="0">
        <results>
          <test-suite type="Namespace" name="Test" executed="True" result="Success" success="True" time="42.717" asserts="0">
            <results>
              <test-suite type="Namespace" name="CarLocator" executed="True" result="Success" success="True" time="42.716" asserts="0">
                <results>
                  <test-suite type="Namespace" name="Search" executed="True" result="Success" success="True" time="42.716" asserts="0">
                    <results>
                      <test-suite type="Namespace" name="Tests" executed="True" result="Success" success="True" time="42.716" asserts="0">
                        <results>
                          <test-suite type="Namespace" name="Index" executed="True" result="Success" success="True" time="40.679" asserts="0">
                            <results>
                              <test-suite type="TestFixture" name="IndexerTests" executed="True" result="Success" success="True" time="20.609" asserts="0">
                                <results>
                                  <test-case name="Search.Tests.Index.IndexerTests.Build_ForEmptyList_DoesNotCreateIndex" executed="True" result="Success" success="True" time="2.157" asserts="0" />
                                  <test-case name="Search.Tests.Index.IndexerTests.Build_ForListOfInventory_CreatesIndex" executed="True" result="Success" success="True" time="16.841" asserts="0" />
                                  <test-case name="Search.Tests.Index.IndexerTests.Build_ForListOfPreferredDealers_CreatesIndex" executed="True" result="Success" success="True" time="1.585" asserts="0" />
                                </results>
                              </test-suite>
                              <test-suite type="TestFixture" name="IndexValidatorTests" executed="True" result="Success" success="True" time="20.062" asserts="0">
                                <results>
                                  <test-case name="Search.Tests.Index.IndexValidatorTests.ValidateDealerIndex_ForValidIndex_ReturnsTrue" executed="True" result="Success" success="True" time="9.784" asserts="1" />
                                  <test-case name="Search.Tests.Index.IndexValidatorTests.ValidateVehicleIndex_ForValidIndex_ReturnsTrue" executed="True" result="Success" success="True" time="10.275" asserts="1" />
                                </results>
                              </test-suite>
                            </results>
                          </test-suite>
                          <test-suite type="Namespace" name="Search" executed="True" result="Success" success="True" time="2.030" asserts="0">
                            <results>
                              <test-suite type="TestFixture" name="VehicleSearchTests" executed="True" result="Success" success="True" time="2.030" asserts="0">
                                <results>
                                  <test-case name="Search.Tests.Search.VehicleSearchTests.ConvertSearchParamsToQuery_ForValidSearchParams_ReturnsPopulatedQueryObject" executed="True" result="Success" success="True" time="0.055" asserts="6" />
                                  <test-case name="Search.Tests.Search.VehicleSearchTests.Find_ForAllSearchParam_ReturnsMatchingVehicles" executed="True" result="Success" success="True" time="0.137" asserts="2" />
                                  <test-case name="Search.Tests.Search.VehicleSearchTests.Find_ForColourSearchParam_ReturnsMatchingVehicles" executed="True" result="Success" success="True" time="0.102" asserts="2" />
                                  <test-case name="Search.Tests.Search.VehicleSearchTests.Find_ForDealerSearchParam_ReturnsMatchingVehicles" executed="True" result="Success" success="True" time="0.095" asserts="2" />
                                  <test-case name="Search.Tests.Search.VehicleSearchTests.Find_ForModelSearchParam_ReturnsMatchingVehicles" executed="True" result="Success" success="True" time="0.082" asserts="2" />
                                  <test-case name="Search.Tests.Search.VehicleSearchTests.Find_ForTrimSearchParam_ReturnsMatchingVehicles" executed="True" result="Success" success="True" time="0.088" asserts="2" />
                                  <test-case name="Search.Tests.Search.VehicleSearchTests.Find_ForYearSearchParam_ReturnsMatchingVehicles" executed="True" result="Success" success="True" time="0.088" asserts="2" />
                                </results>
                              </test-suite>
                            </results>
                          </test-suite>
                        </results>
                      </test-suite>
                    </results>
                  </test-suite>
                </results>
              </test-suite>
            </results>
          </test-suite>
        </results>
      </test-suite>
    </results>
  </test-suite>
</test-results>

Report HTML

<!DOCTYPE html>
<html data-ng-app="coverageApp">
<head>
<meta charset="utf-8" />
<title>Summary - Coverage Report</title>
<link rel="stylesheet" type="text/css" href="report.css" />
</head><body data-ng-controller="SummaryViewCtrl"><div class="container">
<h1>Summary</h1>
<table class="overview">
<colgroup>
<col style="width: 135px;" />
<col />
</colgroup>
<tbody>
<tr><th>Generated on:</th><td>28/05/2015 - 5:32:49</td></tr>
<tr><th>Parser:</th><td></td></tr>
<tr><th>Assemblies:</th><td>0</td></tr>
<tr><th>Classes:</th><td>0</td></tr>
<tr><th>Files:</th><td>0</td></tr>
<tr><th>Covered lines:</th><td>0</td></tr>
<tr><th>Uncovered lines:</th><td>0</td></tr>
<tr><th>Coverable lines:</th><td>0</td></tr>
<tr><th>Total lines:</th><td>0</td></tr>
<tr><th>Line Coverage:</th><td></td></tr>
</tbody>
</table>
<h1>Assemblies</h1>
<p>No assemblies have been covered.</p>
<script type="text/javascript">
/* <![CDATA[ */
var assemblies = [
];
/* ]]> */
</script>
<div class="footer">Generated by: ReportGenerator 2.1.4.0<br />28/05/2015 - 5:32:49<br /><a href="http://www.palmmedia.de">www.palmmedia.de</a></div></div>
<script type="text/javascript" src="combined.js"></script>
</body></html>

Allow browsing covered code more easily

Hi Daniel,

We just switched to OpenCover and ReportGenerator with Simple Injector. A really nice combination and I love how nicely the coverage reports look.

What I'm missing though is a way to navigate really quickly through classes and jump directly to methods that are not (fully) covered. In a sense, what I'm missing who the old NCover v3 interface worked, as shown below:

Old NCover interface

The most important part that this UI has (what I'm missing with ReportGenerator) is that:

  • The left panel [5] of the screen has a list with 'elements' that can be clicked, and are shown in the right panel [7].
  • The left panel shows an hierarchical view of classes (with a coverage percentage) and per class its methods with their coverage.

I would really love to see a report type added that would mimic this behavior.

Coverable vs. Uncoverable lines

This is a general question, rather than a direct bug report.

Basically I used the VS perf cmd tools to generate coverage data for a native executable, then converted that into xml using the built in visual studio APIs (wrote a quick custom tool to just save xml from the loaded coverage file).

I'm seeing some level of inconsistency in the report though. It appears that there are times when ReportGenerator lists sections of code as not coverable when the code was simply clearly not covered. I think this stems from the input xml though. When reading methods from the input xml, does ReportGenerator assume that all methods not listed in the input are "not coverable"?

Discrepancy in %coverage shown by report generator vs visual studio 2015

We used report generator to generate html report for coverage generated by VS(Visual Studio 2015 Enterprise).
VS shows different coverage(see snapshot) than report generated by report generator(see snapshot).
The .coverage file is same for both.
VS uses "codecoverage.exe" to generate .xml. So, we use the same to generate .xml (using command line). So, the .xml file is also same for both.

Report Generator Snapshot: (Line Coverage = 60.1%)
capture
VS Snapshot: (Line Coverage = 58.59%)
capture

Please look into the issue.

Reference to js map

Hi,

In ReportGenerator.Reporting/Rendering/resources/chartist.min.js
there is a reference to chartist.min.js.map
(last line: //# sourceMappingURL=chartist.min.js.map )
This reference will cause an error message in Chrome debugger.
It's a minor issue :)

Thanks,

Thomas P.

Files no longer linked in Summary

I have just upgraded from 1.9.1 to 2.1.4 - great work with branch coverage, by the way!

When the report is generated now, all the required files are generated, but they are not linked in the Summary page.
Here's an example with sensitive information crudely removed in paint.
image

I was previously using this call (inside a batch file):

..\packages\ReportGenerator.2.1.4.0\ReportGenerator.exe^
 -reports:.\report\output.xml^
 -targetdir:.\report^
 -reporttypes:Html,HtmlSummary^
 -historydir:.\report\history^
 -filters:-UnitTests*

but had to change -reporttypes:Html,HtmlSummary to -reporttypes:Html;HtmlSummary to get it to work again. Could this be the issue?

Is there something I'm missing here?

Wrong number of branch points with OpenCover

We're having trouble with the number of branch points displayed in the ReportGenerator. The number of branch points total does not seem to match what I execpt or what the OpenCover XML shows. The single 'if' statement in the source code shows 2 out of 8 branches covered, but I expect 2 out of 2.

We're having this in every class, this is just an example of a simple validation. The maximum is 50% branche coverage in a file with a single 'if' statement', which still shows as 2 out of 4.

Source code excerpt;

public class ValidatePeriod : BaseValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        IPeriod relativePeriod = value as IPeriod;

        DateTime startTime = relativePeriod.StartTime;
        DateTime endTime = relativePeriod.EndTime;
        DateTime startDate = relativePeriod.StartDate;
        DateTime endDate = relativePeriod.EndDate;

        if (DateTimeHelper.MergeDateAndTime(endDate, endTime) < DateTimeHelper.MergeDateAndTime(startDate, startTime))
            return new ValidationResult("Startdate is set sooner than the end date.");
        return null;
    }

    public override bool IsValidFor(Type checkType)
    {
        return (typeof(IPeriod).IsAssignableFrom(checkType));
    }
}

XML excerpt;

<Class>
  <Summary numSequencePoints="9" visitedSequencePoints="9" numBranchPoints="4" visitedBranchPoints="4" sequenceCoverage="100" branchCoverage="100" maxCyclomaticComplexity="2" minCyclomaticComplexity="1" />
  <FullName>X.ValidatePeriod</FullName>
  <Methods>
    <Method visited="true" cyclomaticComplexity="2" sequenceCoverage="100" branchCoverage="100" isConstructor="false" isStatic="false" isGetter="false" isSetter="false">
      <Summary numSequencePoints="8" visitedSequencePoints="8" numBranchPoints="3" visitedBranchPoints="3" sequenceCoverage="100" branchCoverage="100" maxCyclomaticComplexity="2" minCyclomaticComplexity="2" />
      <MetadataToken>100665878</MetadataToken>
      <Name>System.ComponentModel.DataAnnotations.ValidationResult X.ValidatePeriod::IsValid(System.Object,System.ComponentModel.DataAnnotations.ValidationContext)</Name>
      <FileRef uid="3073" />
      <SequencePoints>
        <SequencePoint vc="4" uspid="108867" ordinal="0" offset="0" sl="16" sc="4" el="16" ec="46" bec="0" bev="0" fileid="3073" />
        <SequencePoint vc="4" uspid="108868" ordinal="1" offset="7" sl="18" sc="4" el="18" ec="50" bec="0" bev="0" fileid="3073" />
        <SequencePoint vc="4" uspid="108869" ordinal="2" offset="14" sl="19" sc="4" el="19" ec="46" bec="0" bev="0" fileid="3073" />
        <SequencePoint vc="4" uspid="108870" ordinal="3" offset="21" sl="20" sc="4" el="20" ec="50" bec="0" bev="0" fileid="3073" />
        <SequencePoint vc="4" uspid="108871" ordinal="4" offset="28" sl="21" sc="4" el="21" ec="46" bec="0" bev="0" fileid="3073" />
        <SequencePoint vc="4" uspid="108872" ordinal="5" offset="36" sl="23" sc="4" el="23" ec="114" bec="2" bev="2" fileid="3073" />
        <SequencePoint vc="2" uspid="108873" ordinal="6" offset="58" sl="24" sc="5" el="24" ec="79" bec="0" bev="0" fileid="3073" />
        <SequencePoint vc="2" uspid="108874" ordinal="7" offset="69" sl="25" sc="4" el="25" ec="16" bec="0" bev="0" fileid="3073" />
      </SequencePoints>
      <BranchPoints>
        <BranchPoint vc="2" uspid="108875" ordinal="0" offset="56" sl="23" path="0" offsetend="58" fileid="3073" />
        <BranchPoint vc="2" uspid="108876" ordinal="1" offset="56" sl="23" path="1" offsetend="69" fileid="3073" />
      </BranchPoints>
      <MethodPoint xsi:type="SequencePoint" vc="4" uspid="108867" ordinal="0" offset="0" sl="16" sc="4" el="16" ec="46" bec="0" bev="0" fileid="3073" />
    </Method>
    <Method visited="true" cyclomaticComplexity="1" sequenceCoverage="100" branchCoverage="100" isConstructor="false" isStatic="false" isGetter="false" isSetter="false">
      <Summary numSequencePoints="1" visitedSequencePoints="1" numBranchPoints="1" visitedBranchPoints="1" sequenceCoverage="100" branchCoverage="100" maxCyclomaticComplexity="1" minCyclomaticComplexity="1" />
      <MetadataToken>100665879</MetadataToken>
      <Name>System.Boolean X.ValidatePeriod::IsValidFor(System.Type)</Name>
      <FileRef uid="3073" />
      <SequencePoints>
        <SequencePoint vc="1" uspid="108877" ordinal="0" offset="0" sl="30" sc="4" el="30" ec="57" bec="0" bev="0" fileid="3073" />
      </SequencePoints>
      <BranchPoints />
      <MethodPoint xsi:type="SequencePoint" vc="1" uspid="108877" ordinal="0" offset="0" sl="30" sc="4" el="30" ec="57" bec="0" bev="0" fileid="3073" />
    </Method>
    <Method visited="true" cyclomaticComplexity="1" sequenceCoverage="0" branchCoverage="0" isConstructor="true" isStatic="false" isGetter="false" isSetter="false">
      <Summary numSequencePoints="0" visitedSequencePoints="0" numBranchPoints="0" visitedBranchPoints="0" sequenceCoverage="0" branchCoverage="0" maxCyclomaticComplexity="1" minCyclomaticComplexity="1" />
      <MetadataToken>100665880</MetadataToken>
      <Name>System.Void X.ValidatePeriod::.ctor()</Name>
      <SequencePoints />
      <BranchPoints />
      <MethodPoint vc="3" uspid="108878" ordinal="0" offset="0" />
    </Method>
  </Methods>
</Class>

We're running OpenCover 4.5.3723 and ReportGenerator 2.1.3.0. We've updated yesterday, which added the branch coverage to the reports.

I can't see anything obvious in your source code that can help me fix this problem.

Report history is not ordered

First of all, thanks for all the work, really appreciate it!

I have setup NUnit/OpenCover with ReportGenerator to generate a report for our Jenkins jobs. It all works really well, except the ordering of the X axis. I have 5 builds, one from yesterday and four from today. The one from yesterday is shown as the third (middle) dot in the chart.

Exception when Console is printing a file path with braces

Hi Daniel,

First. Thanks for developing ReportGenerator. It is a really great tool!

Now about the issue:
I'm experiencing an exception and I already know the root cause. In my code coverage file I have a file with braces in the path (e.g. MyClass{T}.cs). However, I don't have the source code of this file.
For this reason, the Logger will print that MyClass{T}.cs was not found. As result, Console.Writeline will raise an illegal character exception, because it will parse "{T}".

I think you can escape braces '{' '}' when printing FilePaths. But you know better your project.

Anyway, you should be really proud of ReportGenerator.

Thanks,
Willian.

Classes with all async/await methods are not correctly reported

I have found that if I have a class that only has async/await methods in it, that class always shows up as zero coverage in the ReportGenerator output. I discovered this while working with Web API DelegatingHandler implementations, which basically only have async/await.

Example:

Here's a very simple DelegatingHandler class.

using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace ReportGeneratorRepro
{
  public class ReproHandler : DelegatingHandler
  {
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
      request.Properties.Add("demo", true);
      return await base.SendAsync(request, cancellationToken);
    }
  }
}

Note it only has async/await methods in it, so the compiler is going to generate that magic enumerable state machine to handle the syntactic sugar.

Here's an NUnit test that provides full coverage. (Well, full coverage except for a tiny bit on the generated async/await state machine.)

using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using ReportGeneratorRepro;

namespace ReproUnitTests
{
  [TestFixture]
  public class ReproHandlerTests
  {
    [Test]
    public async void FullCoverage()
    {
      var request = new HttpRequestMessage();
      var expected = new HttpResponseMessage();
      var handler = new ReproHandler { InnerHandler = new EchoHandler(expected) };
      var invoker = new HttpMessageInvoker(handler, false);
      var actual = await invoker.SendAsync(request, new CancellationToken());
      Assert.AreSame(expected, actual);
      Assert.IsTrue((bool)request.Properties["demo"]);
    }

    private class EchoHandler : DelegatingHandler
    {
      private HttpResponseMessage _response;

      public EchoHandler(HttpResponseMessage response)
      {
        this._response = response;
      }

      protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
      {
        return Task.FromResult(this._response);
      }
    }
  }
}

When run with coverage, I see 75% coverage for the handler and 85% coverage in the unit test. (Not that I care a bunch about the coverage on the unit test proper, but it, too, only has async/await methods in it.) The nested EchoHandler class inside the test fixture shows 100% coverage.

Coverage results inside Visual Studio

Taking that .coverage report output and converting it to .coveragexml, I still see that there's correct coverage reported. It's not lost in the translation. For example, I see the generated SendAsync async/await state machine MoveNext() method getting reported with 75% line coverage:

<function id="8272" token="0x6000004" name="MoveNext()" type_name="ReproHandler.&lt;SendAsync&gt;d__0" block_coverage="65.22" line_coverage="75.00" blocks_covered="15" blocks_not_covered="8" lines_covered="3" lines_partially_covered="1" lines_not_covered="0">

All the numbers in the .coveragexml line up.

However, if I run the ReportGenerator to get a report...

ReportGenerator.exe "-reports:CoverageResults.coveragexml" "-targetdir:report"

...then I actually see ZERO coverage for the whole thing:

HTML report showing zero coverage

Not even the nested EchoHandler class in the unit test class is reported, even though it has full coverage and no async/await - the parent class, the unit test fixture, only has async/await so it seems to just ignore everything inside that class including nested classes.

[Feature request] Generate badge graphics

It wold be cool if ReportGenerator additionally generates badge graphics for the total statement / branch coverage, like the following example.
sample

Use case: These graphic files could be uploaded somewhere (or directly hosted by the build server) so that they can be referenced e.g. in a GitHub README page.

Ideally these graphics are generated as SVG to have no problems with background colors / scaling.

Problem installing package with VS 2015 RC

If you try to install ReportGenerator to a project on VS 2015 RC (latest available at the moment) using nuget you get this error message:

Could not install package 'ReportGenerator 2.1.6.0'. You are trying to install this package into a project that targets '.NETFramework, Version=v4.5', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.         0

I think there might be a problem on the way the nuget pkg is structured. Maybe you need a tools folder?

Some references:
https://docs.nuget.org/create/enforced-package-conventions
https://docs.nuget.org/create/creating-and-publishing-a-package

Won't run on linux under mono due to log4net

============Error ============
Under Linux Bash:

Unhandled Exception:
System.EntryPointNotFoundException: GetConsoleOutputCP
at (wrapper managed-to-native) log4net.Appender.ColoredConsoleAppender:GetConsoleOutputCP ()
at log4net.Appender.ColoredConsoleAppender.ActivateOptions () [0x00000] in :0
at Palmmedia.ReportGenerator.Program.Execute (Palmmedia.ReportGenerator.ReportConfiguration configuration) [0x00000] in :0
at Palmmedia.ReportGenerator.Program.Main (System.String[] args) [0x00000] in :0
[ERROR] FATAL UNHANDLED EXCEPTION: System.EntryPointNotFoundException: GetConsoleOutputCP
at (wrapper managed-to-native) log4net.Appender.ColoredConsoleAppender:GetConsoleOutputCP ()
at log4net.Appender.ColoredConsoleAppender.ActivateOptions () [0x00000] in :0
at Palmmedia.ReportGenerator.Program.Execute (Palmmedia.ReportGenerator.ReportConfiguration configuration) [0x00000] in :0
at Palmmedia.ReportGenerator.Program.Main (System.String[] args) [0x00000] in :0

============Cause============
In ReportGenerator/Program.cs:33

var appender = new ColoredConsoleAppender()
{
Layout = new log4net.Layout.PatternLayout("%message%newline")
};
appender.AddMapping(new ColoredConsoleAppender.LevelColors { Level = log4net.Core.Level.Warn, ForeColor = ColoredConsoleAppender.Colors.Purple | ColoredConsoleAppender.Colors.HighIntensity });
appender.AddMapping(new ColoredConsoleAppender.LevelColors { Level = log4net.Core.Level.Error, ForeColor = ColoredConsoleAppender.Colors.Red | ColoredConsoleAppender.Colors.HighIntensity });

Fails as log4net does not support coloured consoles under Linux. See https://issues.apache.org/jira/browse/LOG4NET-453

============ Resolution ============
Could it fall back to a simple appender or allow allow passing a flag to determine the logger/log-setup?

Is it possible to show coverage data in files instead of class?

Hi daniel,

Your tool is really cool. And I have created several code coverage reports using your open source tool. However, I am wondering whether it is possible to show the coverage information in terms of cpp files instead of class.

I am using VS2012 dynamic coverage file to generate the report. Sometimes I would feel more easier if you could list the coverage information for several classes defined in the same cpp file altogether. Now I could only see the coverage information for a specific class in a cpp file. All other classes are grayed out.

Formatting breaks when printing HTML report

Reports look perfect when displayed on screen, however when I print the HTML version of an OpenCover report (archaic, I know) the formatting completely breaks and the print becomes 100+ pages, when it should be 4 or 5.

Report as I'm looking at it:
htmlonscreen

After it is printed:
asprinted

Question about sequenceCoverage, Line coverage and branchCoverage, branch coverage differences

Hey Daniel,

I'm reviewing a report from an OpenCover run and I'm wondering where some of the numbers come from. For example, I have one sequenceCoverage value in the OpenCover xml that's 47.17 and the Line coverage value in the ReportGenerator output is 41.6. I am assuming sequenceCoverage is Line coverage in the report.

In the same class there's a branchCoverage value in the OpenCover xml of 52.94 and Branch coverage value in the ReportGenerator output is 60.

The numbers are close, but not equal. I'm wondering how the numbers in ReportGenerator are calculated. Any chance you could shed a little light? Or point me to the class that does the math and I can figure it out?

ReportGenerator version: 2.3.2.0

Kind regards,
Steve

OpenCover from VS2015 output renders unhandled InvalidCastException

Generating an codecoveragereport.xml with the command:

"C:\Users\<my_user>\AppData\Local\Apps\OpenCover\OpenCover.Console.exe" -register:user -target:"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" -targetargs:"/Logger:trx /inIsolation /Platform:x64 bin/Release/Model.Tests.dll" -filter:"+[*]*" -mergebyhash -output:"codecoveragereport.xml"

And trying to generate a report on the output with

ReportGenerator.exe -reports:codecoveragereport.xml -targetDir:TTS2_Code_Coverage_Report

Gives the following error:

08:48:30 Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'ICSharpCode.NRefactory.CSharp.ReturnStatement' to type 'ICSharpCode.NRefactory.CSharp.BlockStatement'.
08:48:30    at ICSharpCode.NRefactory.CSharp.CSharpParser.ConversionVisitor.Visit(Property p)
08:48:30    at Mono.CSharp.StructuralVisitor.VisitTypeDefinition(TypeDefinition tc)
08:48:30    at ICSharpCode.NRefactory.CSharp.CSharpParser.ConversionVisitor.Visit(Class c)
08:48:30    at ICSharpCode.NRefactory.CSharp.CSharpParser.ConversionVisitor.Visit(NamespaceContainer ns)
08:48:30    at ICSharpCode.NRefactory.CSharp.CSharpParser.ConversionVisitor.Visit(ModuleContainer mc)
08:48:30    at ICSharpCode.NRefactory.CSharp.CSharpParser.Parse(CompilerCompilationUnit top, String fileName)
08:48:30    at ICSharpCode.NRefactory.CSharp.CSharpParser.Parse(ITextSource program, String fileName, Int32 initialLine, Int32 initialColumn)
08:48:30    at ICSharpCode.NRefactory.CSharp.CSharpParser.Parse(ITextSource program, String fileName)
08:48:30    at Palmmedia.ReportGenerator.Parser.Preprocessing.CodeAnalysis.SourceCodeAnalyzer.GetParentNode(String filename)
08:48:30    at Palmmedia.ReportGenerator.Parser.Preprocessing.CodeAnalysis.SourceCodeAnalyzer.FindSourceElement(String filename, SourceElement sourceElement)
08:48:30    at Palmmedia.ReportGenerator.Parser.Preprocessing.ReportPreprocessorBase.<>c__DisplayClass13_0.<SearchElement>b__0()
08:48:30    at Palmmedia.ReportGenerator.Parser.Preprocessing.ReportPreprocessorBase.SearchElement(SourceElement sourceElement, Dictionary`2 filenameByFileIdDictionary, IEnumerable`1 fileIdsOfClass, XContainer reportElement, Action`3 updateReportElement, XContainer filesContainer)
08:48:30    at Palmmedia.ReportGenerator.Parser.Preprocessing.OpenCoverReportPreprocessor.AddCoverageDataOfAutoProperties(XElement module)
08:48:30    at Palmmedia.ReportGenerator.Parser.Preprocessing.OpenCoverReportPreprocessor.Execute()
08:48:30    at Palmmedia.ReportGenerator.Parser.ParserFactory.GetParsersOfFile(String reportFile, ClassSearcherFactory classSearcherFactory, ClassSearcher globalClassSearcher)
08:48:30    at Palmmedia.ReportGenerator.Parser.ParserFactory.CreateParser(IEnumerable`1 reportFiles, IEnumerable`1 sourceDirectories)
08:48:30    at Palmmedia.ReportGenerator.Program.Execute(ReportConfiguration configuration)
08:48:30    at Palmmedia.ReportGenerator.Program.Main(String[] args)

This might as well be an error in the NRefactory code, so maybe I should post there as well?

Integration with CruiseControl.NET

Hi,

Nice product BTW :-)

I have integrated xUnit, OpenCover and ReportGenerator into CruiseControl.NET and the coverage report is being displayed successfully by using this guide

The coverage report works within the dashboard

http://localhost/ccnet/server/local/project/x/build/log20150305102701Lbuild.65.xml/coverageReport.aspx

in its own window

http://localhost/ccnet/server/local/project/x/build/log20150305102701Lbuild.65.xml/RetrieveBuildFile.aspx?file=coveragereport\index.htm

But in both instances I am unable to view the individual detail files for each of the classes

http://localhost/ccnet/server/local/project/x/build/log20150305102701Lbuild.65.xml/x.y.z_DebugTraceCommandHandler_1.htm

I get a yellow screen of death

Unknown object name : x.y.z_debugtracecommandhandler_1
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ApplicationException: Unknown object name : x.y.z_debugtracecommandhandler_1

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[ApplicationException: Unknown object name : x.y.z_debugtracecommandhandler_1]
Objection.ObjectionStore.GetByName(String name) +344
ThoughtWorks.CruiseControl.WebDashboard.MVC.Cruise.CruiseActionFactory.CreateHandler(String actionName) +191
ThoughtWorks.CruiseControl.WebDashboard.MVC.Cruise.CruiseActionFactory.Create(IRequest request) +40
ThoughtWorks.CruiseControl.WebDashboard.MVC.RequestController.Do() +128
ThoughtWorks.CruiseControl.WebDashboard.MVC.ASPNET.HttpHandler.ProcessRequest(HttpContext context) +594
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +599
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +171

It looks to me like I need to get /RetrieveBuildFile.aspx?file=coveragereport\ into the url to change this

http://localhost/ccnet/server/local/project/x/build/log20150305102701Lbuild.65.xml/x.y.z_DebugTraceCommandHandler_1.htm

into this

http://localhost/ccnet/server/local/project/x/build/log20150305102701Lbuild.65.xml/RetrieveBuildFile.aspx?file=coveragereport\x.y.z_DebugTraceCommandHandler_1.htm

Can you help?

How to exclude certain namespaces?

I have read through the document of both OpenCover and ReportGenerator, and no matter what I do I cannot get ReportGenerator to exclude a certain namespace from the reports.

I am using ReSharper and one of the things this excellent tool offers, is to add a file called Annotations.cs which helps with code analysis and so on.
However, there are a lot of micro classes in this namespace, and I would really like to to exclude this namespace.
How do I do that?

OpenCover and ReportGenerator filters don't seem to work.

I am not sure if I am doing this wrong, but when I have open cover run my tests and then have report generator create the report, the report does not seem to filter out any assembly that has a test filer layout. It worked fine when I was using VS code coverage to create the coverage information and then report generator would filter the assemblies. I switched to open cover because some of my tests were causing VS Code Coverage to throw out of memory errors. Open cover works great (a little slower) but the tests then are not filtered out of the data by report generator. I am planning to look into filtering them in open cover, but I expected both sources of data to filter the data the same way and was surprised when they didn't.

ReportGenerator for Mono

I'm using ReportGenerator on Mono with monos coverage tooling.

I can prepare a pull request if it is ok for you to add dependency to Mono.Cecil.

Statement coverage incorrect

Hi,

I just updated my setup from v1.7.3 to v2.1.4 and although it now looks much nicer I noticed huge bump in the coverable/covered lines and realised it now counts things that it shouldn't be / previously wasn't.

Please see screenshots attached:

Previous correct behaviour:
old

The current (suspicious) behaviour:
new

Nested types are getting ignored

ReportGenerator appears to be ignoring nested types:
https://github.com/danielpalme/ReportGenerator/blob/master/ReportGenerator/Parser/OpenCoverParser.cs#L191

We use ReportGenerator on https://github.com/dotnet/corefx, e.g. http://dotnet-ci.cloudapp.net/job/dotnet_corefx_coverage_windows/lastStableBuild/Code_Coverage_Report/ , and the reports are getting skewed due to no nested types showing up. You can see this with things like Enumerators nested in collection types, the interop code we use (the majority of which is in nested types), etc.

Can this be fixed?

Covered classes showing 0% in report

Hi,

We're using OpenCover and we have several classes which are showing 0% coverage in the generated report when they shouldn't.

For example, the BaseWorkItemPersistenceManager class has the following opencover output and shows 100% coverage in OpenCoverUI in Visual Studio but is showing 0% in the ReportGenerator report.

Any pointers would be appreciated,

Thanks.

<Class>
  <Summary numSequencePoints="31" visitedSequencePoints="31" numBranchPoints="51" visitedBranchPoints="43" sequenceCoverage="100" branchCoverage="84.31" maxCyclomaticComplexity="22" minCyclomaticComplexity="1" />
  <FullName>Core.Logic.Managers.Shared.WorkItems.BaseWorkItemPersistenceManager</FullName>
  <Methods>
    <Method visited="true" cyclomaticComplexity="1" sequenceCoverage="100" branchCoverage="100" isConstructor="true" isStatic="false" isGetter="false" isSetter="false">
      <Summary numSequencePoints="3" visitedSequencePoints="3" numBranchPoints="1" visitedBranchPoints="1" sequenceCoverage="100" branchCoverage="100" maxCyclomaticComplexity="1" minCyclomaticComplexity="1" />
      <MetadataToken>100663819</MetadataToken>
      <Name>System.Void Core.Logic.Managers.Shared.WorkItems.BaseWorkItemPersistenceManager::.ctor(Core.Domain.Moose.Interfaces.DataInterfaces.Shared.WorkItems.IWorkItemRepository)</Name>
      <FileRef uid="349" />
      <SequencePoints>
        <SequencePoint vc="24" uspid="15358" ordinal="0" offset="0" sl="23" sc="9" el="23" ec="89" />
        <SequencePoint vc="24" uspid="15359" ordinal="1" offset="6" sl="25" sc="13" el="25" ec="58" />
        <SequencePoint vc="24" uspid="15360" ordinal="2" offset="13" sl="26" sc="9" el="26" ec="10" />
      </SequencePoints>
      <BranchPoints />
      <MethodPoint xsi:type="SequencePoint" vc="24" uspid="15358" ordinal="0" offset="0" sl="23" sc="9" el="23" ec="89" />
    </Method>
    <Method visited="true" cyclomaticComplexity="5" sequenceCoverage="100" branchCoverage="88.89" isConstructor="false" isStatic="false" isGetter="false" isSetter="false">
      <Summary numSequencePoints="9" visitedSequencePoints="9" numBranchPoints="9" visitedBranchPoints="8" sequenceCoverage="100" branchCoverage="88.89" maxCyclomaticComplexity="5" minCyclomaticComplexity="5" />
      <MetadataToken>100663820</MetadataToken>
      <Name>System.Void Core.Logic.Managers.Shared.WorkItems.BaseWorkItemPersistenceManager::SaveItem(Core.Domain.Moose.Entities.Shared.WorkItems.WorkItem,Core.Domain.Moose.Entities.Shared.WorkItems.WorkItem)</Name>
      <FileRef uid="349" />
      <SequencePoints>
        <SequencePoint vc="18" uspid="15361" ordinal="0" offset="0" sl="35" sc="13" el="35" ec="46" />
        <SequencePoint vc="10" uspid="15362" ordinal="1" offset="7" sl="37" sc="13" el="37" ec="38" />
        <SequencePoint vc="5" uspid="15363" ordinal="2" offset="10" sl="40" sc="17" el="40" ec="83" />
        <SequencePoint vc="1" uspid="15364" ordinal="3" offset="42" sl="43" sc="21" el="43" ec="52" />
        <SequencePoint vc="5" uspid="15365" ordinal="4" offset="58" sl="47" sc="17" el="47" ec="47" />
        <SequencePoint vc="4" uspid="15366" ordinal="5" offset="74" sl="49" sc="21" el="49" ec="45" />
        <SequencePoint vc="4" uspid="15367" ordinal="6" offset="81" sl="50" sc="21" el="50" ec="56" />
        <SequencePoint vc="10" uspid="15368" ordinal="7" offset="96" sl="54" sc="13" el="54" ec="48" />
        <SequencePoint vc="10" uspid="15369" ordinal="8" offset="108" sl="55" sc="9" el="55" ec="10" />
      </SequencePoints>
      <BranchPoints>
        <BranchPoint vc="5" uspid="15370" ordinal="0" offset="8" path="0" />
        <BranchPoint vc="5" uspid="15371" ordinal="1" offset="8" path="1" />
        <BranchPoint vc="5" uspid="15372" ordinal="2" offset="24" path="0" />
        <BranchPoint vc="0" uspid="15373" ordinal="3" offset="24" path="1" />
        <BranchPoint vc="1" uspid="15374" ordinal="4" offset="40" path="0" />
        <BranchPoint vc="4" uspid="15375" ordinal="5" offset="40" path="1" />
        <BranchPoint vc="4" uspid="15376" ordinal="6" offset="72" path="0" />
        <BranchPoint vc="1" uspid="15377" ordinal="7" offset="72" path="1" />
      </BranchPoints>
      <MethodPoint xsi:type="SequencePoint" vc="18" uspid="15361" ordinal="0" offset="0" sl="35" sc="13" el="35" ec="46" />
    </Method>
    <Method visited="true" cyclomaticComplexity="22" sequenceCoverage="100" branchCoverage="82.93" isConstructor="false" isStatic="true" isGetter="false" isSetter="false">
      <Summary numSequencePoints="19" visitedSequencePoints="19" numBranchPoints="41" visitedBranchPoints="34" sequenceCoverage="100" branchCoverage="82.93" maxCyclomaticComplexity="22" minCyclomaticComplexity="22" />
      <MetadataToken>100663821</MetadataToken>
      <Name>System.Void Core.Logic.Managers.Shared.WorkItems.BaseWorkItemPersistenceManager::ValidateSave(Core.Domain.Moose.Entities.Shared.WorkItems.WorkItem,Core.Domain.Moose.Entities.Shared.WorkItems.WorkItem)</Name>
      <FileRef uid="349" />
      <SequencePoints>
        <SequencePoint vc="18" uspid="15378" ordinal="0" offset="0" sl="64" sc="13" el="64" ec="54" />
        <SequencePoint vc="1" uspid="15379" ordinal="1" offset="13" sl="66" sc="17" el="66" ec="76" />
        <SequencePoint vc="17" uspid="15380" ordinal="2" offset="24" sl="69" sc="13" el="69" ec="30" />
        <SequencePoint vc="7" uspid="15381" ordinal="3" offset="35" sl="72" sc="17" el="73" ec="58" />
        <SequencePoint vc="1" uspid="15382" ordinal="4" offset="80" sl="75" sc="21" el="75" ec="84" />
        <SequencePoint vc="6" uspid="15383" ordinal="5" offset="91" sl="78" sc="17" el="78" ec="90" />
        <SequencePoint vc="1" uspid="15384" ordinal="6" offset="157" sl="80" sc="21" el="80" ec="106" />
        <SequencePoint vc="10" uspid="15385" ordinal="7" offset="168" sl="86" sc="17" el="86" ec="72" />
        <SequencePoint vc="1" uspid="15386" ordinal="8" offset="185" sl="88" sc="21" el="88" ec="102" />
        <SequencePoint vc="9" uspid="15387" ordinal="9" offset="217" sl="92" sc="17" el="92" ec="87" />
        <SequencePoint vc="1" uspid="15388" ordinal="10" offset="251" sl="94" sc="21" el="94" ec="103" />
        <SequencePoint vc="8" uspid="15389" ordinal="11" offset="262" sl="98" sc="17" el="98" ec="83" />
        <SequencePoint vc="1" uspid="15390" ordinal="12" offset="296" sl="100" sc="21" el="100" ec="81" />
        <SequencePoint vc="7" uspid="15391" ordinal="13" offset="307" sl="104" sc="17" el="105" ec="76" />
        <SequencePoint vc="1" uspid="15392" ordinal="14" offset="378" sl="107" sc="21" el="107" ec="85" />
        <SequencePoint vc="6" uspid="15393" ordinal="15" offset="389" sl="111" sc="17" el="111" ec="58" />
        <SequencePoint vc="2" uspid="15394" ordinal="16" offset="457" sl="113" sc="21" el="113" ec="69" />
        <SequencePoint vc="1" uspid="15395" ordinal="17" offset="502" sl="115" sc="25" el="115" ec="108" />
        <SequencePoint vc="10" uspid="15396" ordinal="18" offset="513" sl="119" sc="9" el="119" ec="10" />
      </SequencePoints>
      <BranchPoints>
        <BranchPoint vc="1" uspid="15397" ordinal="0" offset="11" path="0" />
        <BranchPoint vc="17" uspid="15398" ordinal="1" offset="11" path="1" />
        <BranchPoint vc="7" uspid="15399" ordinal="2" offset="30" path="0" />
        <BranchPoint vc="10" uspid="15400" ordinal="3" offset="30" path="1" />
        <BranchPoint vc="6" uspid="15401" ordinal="4" offset="49" path="0" />
        <BranchPoint vc="1" uspid="15402" ordinal="5" offset="49" path="1" />
        <BranchPoint vc="6" uspid="15403" ordinal="6" offset="62" path="0" />
        <BranchPoint vc="0" uspid="15404" ordinal="7" offset="62" path="1" />
        <BranchPoint vc="0" uspid="15405" ordinal="8" offset="78" path="0" />
        <BranchPoint vc="6" uspid="15406" ordinal="9" offset="78" path="1" />
        <BranchPoint vc="5" uspid="15407" ordinal="10" offset="105" path="0" />
        <BranchPoint vc="1" uspid="15408" ordinal="11" offset="105" path="1" />
        <BranchPoint vc="1" uspid="15409" ordinal="12" offset="152" path="0" />
        <BranchPoint vc="4" uspid="15410" ordinal="13" offset="152" path="1" />
        <BranchPoint vc="10" uspid="15411" ordinal="14" offset="169" path="0" />
        <BranchPoint vc="0" uspid="15412" ordinal="15" offset="169" path="1" />
        <BranchPoint vc="1" uspid="15413" ordinal="16" offset="183" path="0" />
        <BranchPoint vc="9" uspid="15414" ordinal="17" offset="183" path="1" />
        <BranchPoint vc="3" uspid="15415" ordinal="18" offset="232" path="0" />
        <BranchPoint vc="6" uspid="15416" ordinal="19" offset="232" path="1" />
        <BranchPoint vc="1" uspid="15417" ordinal="20" offset="249" path="0" />
        <BranchPoint vc="2" uspid="15418" ordinal="21" offset="249" path="1" />
        <BranchPoint vc="2" uspid="15419" ordinal="22" offset="277" path="0" />
        <BranchPoint vc="6" uspid="15420" ordinal="23" offset="277" path="1" />
        <BranchPoint vc="1" uspid="15421" ordinal="24" offset="294" path="0" />
        <BranchPoint vc="1" uspid="15422" ordinal="25" offset="294" path="1" />
        <BranchPoint vc="1" uspid="15423" ordinal="26" offset="322" path="0" />
        <BranchPoint vc="6" uspid="15424" ordinal="27" offset="322" path="1" />
        <BranchPoint vc="1" uspid="15425" ordinal="28" offset="339" path="0" />
        <BranchPoint vc="0" uspid="15426" ordinal="29" offset="339" path="1" />
        <BranchPoint vc="1" uspid="15427" ordinal="30" offset="376" path="0" />
        <BranchPoint vc="0" uspid="15428" ordinal="31" offset="376" path="1" />
        <BranchPoint vc="6" uspid="15429" ordinal="32" offset="419" path="0" />
        <BranchPoint vc="0" uspid="15430" ordinal="33" offset="419" path="1" />
        <BranchPoint vc="6" uspid="15431" ordinal="34" offset="428" path="0" />
        <BranchPoint vc="0" uspid="15432" ordinal="35" offset="428" path="1" />
        <BranchPoint vc="2" uspid="15433" ordinal="36" offset="455" path="0" />
        <BranchPoint vc="4" uspid="15434" ordinal="37" offset="455" path="1" />
        <BranchPoint vc="1" uspid="15435" ordinal="38" offset="500" path="0" />
        <BranchPoint vc="1" uspid="15436" ordinal="39" offset="500" path="1" />
      </BranchPoints>
      <MethodPoint xsi:type="SequencePoint" vc="18" uspid="15378" ordinal="0" offset="0" sl="64" sc="13" el="64" ec="54" />
    </Method>
  </Methods>
</Class>

Shared folders in command line no loger working, since version 2.3.1.0.

Dear Colleagues,

Since version 2.3.1.0, using shared folders in the command line (argument -reports), stoped to work.
Ex. ... "-reports:\server\share\file.xml" ...
It works in versions 2.3.0.0 and below (tested since 2.1.8.0)

It would be great if we could have this feature working again.
Thanks and Cheers!
Marcel

Remove inline styles and scripts for better Jenkins CSP compliance

Jenkins 1.641 / Jenkins 1.625.3 LTS introduced a new Content Security Policy with a very restrictive default (described at https://wiki.jenkins-ci.org/display/JENKINS/Configuring+Content+Security+Policy#ConfiguringContentSecurityPolicy-Implementation). This breaks the coverage reports generated by ReportGenerator in several ways. Adjusting Jenkins' CSP to allow ReportGenerator's "combined.js" file might be reasonable (via script-src 'self'), but allowing the inline JavaScript and inline style attributes (via script-src 'unsafe-inline' and style-src 'unsafe-inline') that ReportGenerator uses would open too much of a gap in the intended CSP security model.

Could you move the (generated) inline JavaScript into a separate .js file, and define the % widths as classes in a separate stylesheet file (or set the style attributes in a function in the .js file), so that no inline scripts or styles are needed?

Error not shown and invalid coverage file issue

Tried to run analyze command to convert .coverage file to XML file. Command was executed successfully but no XML file was generated. Later on running with event finder it showed "The following coverage file is either corrupt or is not valid" error. Why is error not shown on command prompt. The .coverage file is actually a valid one I was able to open it with Visual Studio and using save as option in VS i am able to store it as XML.

Shut down after the launch

I cloned ReportGenerator from this repository, then compiled it on my VisualStudio 2015 and ReportGenerator just shuting down after the launch.
image

ReportGenerator 2.4.4.0
Copyright c Palmmedia 2015

Parameters:
["]-reports:[;][;]["]
["]-targetdir:["]
[["]-reporttypes:<...>[;<...>]["]]"
[["]-sourcedirs:[;][;]["]]
[["]-historydir:["]]
[["]-assemblyfilters:<(+|-)filter>[;<(+|-)filter>][;<(+|-)filter>]["]]
[["]-classfilters:<(+|-)filter>[;<(+|-)filter>][;<(+|-)filter>]["]]
[["]-verbosity:<Verbose|Info|Error>["]]

Explanations:
Reports: The coverage reports that should be parsed (separated by semicolon). Wildcards are allowed.
Target directory: The directory where the generated report should be saved.
Reporttypes: The output formats and scope (separated by semicolon).
Values:
Source directories: Optional directories which contain the corresponding source code (separated by semicolon).
The source files are used if coverage report contains classes without path information.
History directory: Optional directory for storing persistent coverage information.
Can be used in future reports to show coverage evolution.
Assembly Filters: Optional list of assemblies that should be included or excluded in the report.
Class Filters: Optional list of classes that should be included or excluded in the report.
Exclusion filters take precedence over inclusion filters. Wildcards are allowed.
Verbosity: The verbosity level of the log messages.
Values: Verbose, Info, Error

Default values:
-reporttypes:Html
-assemblyfilters:+*
-classfilters:+*
-verbosity:Verbose

Examples:
"-reports:coverage.xml" "-targetdir:C:\report"
"-reports:target**.xml" "-targetdir:C:\report" -reporttypes:Latex;HtmlSummary
"-reports:coverage1.xml;coverage2.xml" "-targetdir:report"
"-reports:coverage.xml" "-targetdir:C:\report" -reporttypes:Latex "-sourcedirs:C:\MyProject"
"-reports:coverage.xml" "-targetdir:C:\report" "-sourcedirs:C:\MyProject1;C:\MyProject2" "-assemblyfilters:+Included;-Excluded.*"
Press any key to continue . . .

Coverage History dashboard

Hi Daniel,

We've been using ReportGenerator for a while now. Only recently we noticed that it can also generate the history trends which is a very useful feature. But we wanted a way to be able to see the trends for many projects in a dashboard view in Jenkins to get an overall picture.

I was thinking of creating a custom view and embedding the coverage report as an iframe. But the trends chart is using svg and I'm not able to take that out alone from the whole html.

I'm thinking the trends chart alone can be exported out, something like the badges so that it can be plugged in anywhere. Do you have any plans for this?

Feature request: add limit on persistent coverage information

We're running OpenCover and ReportGenerator on each PR and the amount of data is growing to a point it takes a minute plus to parse historical coverage info supplied via -historydir argument.

I propose a set of new arguments that limits how may items are loaded:
-historymax:<maximum items to read>
-prunehistory:<true|false> -- if true, limit file count in historydir to historymax, keep newest

I can write the code change and PR back to this repository but would love to get some information on whether this makes sense or any alternative approach that I should write instead.

Need a report which shows only History Graph

Hi @danielpalme,

Thanks for the nice tool. It shows very pretty coverage view.
I am using this tool for n number of projects in Jenkins. And it shows very impressive and useful reports.
Now I want to collate all the project's history graph reports and want to show only History Trends as a single history monitoring UI. Can you please guide, how can i achieve this?

5

Or It will be fine even I can only show 1 project's History Trend and I will combine multiple projects later.

Multiple classes per file report

Hi,
I've just noticed that the reporting doesn't appear to work when there are multiple Classes per file. Is there something that I'm missing or is this a known limitation. Looking at the Coverage.xml input there is no reference to the file in which the given class was hosted so it might be a problem with opencover?

Guidance on integrating with TeamCity

Hi Daniel,

please can you offer any guidance on how I should integrate a coverage report with TeamCity v9?

I've tried a couple of different things in the artifacts path box in Build Configuration Settings -> General Settings but nothing seems to work particularly well:

..\Artifacts\%build.counter%\Coverage\index.htm

has no css

and

..\Artifacts\%build.counter%\Coverage\index.htm
..\Artifacts\%build.counter%\Coverage\*.*

list all htm files and index.htm only displays the table at the top of the page (I think I fixed this when using Cruise Control by running a power shell script to remove script from the page)

Any help will be greatly appreciated.

Peter

Total Line issue

Hi Daniel,
I had been using report generator to generate my opencover result, but I am getting some uncertainty about the number of total line, it since when merge multiple opencover result will double or triple the total line, in this case in correct total line & coverage percentage is incorrect.

So I had some doubt about it, not sure what is your suggestion, many thanks for the help

Best Regards,
Maxwell

JS Display Issue

Hi,

I'm investigating this issue, but when using lastest version to produce HTML Reports, the index.html page starts to display just fine, and when it's fully loaded, the javascript kicks in and the whole page is destroyed, emptied, and only a "Enable Filtering" button remains
It happens shortly after a console message "Number of classes (filtering disabled): ... " is displayed
I setup a break point in chrome debugger, but could not understand this issue (after that, it is related to code inside AngularJS and jQuery

Thanks,

Thomas P.

Reported branch coverage for OpenCover is miscounted

Each method is an implicit branch, but branches are only counted on expllicit branch points. This leads to an incorrect estimate of the branch coverage. Think of a class containing the following methods

void A()
{
  if(...)
  {
    //do something
  }
  //do something else
}

void B()
{
  //do something
}

A is called in a way that both branches are taken, B is never executed. ReportGenerator would report 2/2 branches covered, since it only counts the explicit branches (the if), whereas the summary in the OpenCover result.xml would state 3/4 branches covered, since we'll have to add 1 branch for each of the methods. Both the OpenCover class summary and the OpenCover method summary report the correct values.

Need help to create history from VS 2013 coverage files

Hi,

Firstly this is great so thanks!

I need help though. I've got a Visual Studio coverage file that I want to share in pretty HTML with others and am using your tool to do that. The bit that would be freaking awesome is a nice history with graphic to show progress (or decline!), but it's not doing anything for me.

So I run the below in a batch file:

.\tools\ReportGenerator.exe ^
-reports:"2016-06-14 16_02_40.coveragexml" ^
-targetdir:".\report" ^
-reporttypes:"Html" ^
-historydir=".\report\history"

And I get is the statistical table HTML page with no history folder :(

Any help?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.