# ReportGenerator
ReportGenerator is a powerful code coverage visualization tool that converts coverage reports generated by various testing frameworks (coverlet, OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov, lcov) into human-readable reports in multiple formats. It supports .NET, Java, and NodeJS projects, providing detailed line-by-line coverage visualization, risk hotspot analysis, and historical trend charts to track coverage evolution over time.
The tool is available as a NuGet package, .NET global tool, Azure DevOps extension, and GitHub Action. ReportGenerator supports merging multiple coverage files into a single unified report, making it ideal for large projects with multiple test suites. It offers extensive output formats including HTML (with multiple themes), XML, JSON, Markdown, Badges, and integration-specific formats for SonarQube, TeamCity, and other CI/CD systems.
## Command Line Interface
The primary interface for ReportGenerator is its command line tool that accepts coverage reports and generates visualized output in the specified format.
```bash
# Basic usage: Generate HTML report from coverage file
reportgenerator -reports:coverage.xml -targetdir:coveragereport
# Multiple input files with globbing support
reportgenerator -reports:"target\*\*.xml" -targetdir:coveragereport
# Multiple report types with custom title and version tag
reportgenerator -reports:coverage.xml -targetdir:coveragereport -reporttypes:Html;Cobertura;Badges -title:MyProject -tag:v1.4.5
# With source directories for path resolution
reportgenerator -reports:"coverage1.xml;coverage2.xml" -targetdir:report -sourcedirs:"C:\MyProject"
# Filter assemblies and classes
reportgenerator -reports:coverage.xml -targetdir:coveragereport -assemblyfilters:"+Included;-Excluded.*" -classfilters:"+MyNamespace.*;-*Tests"
# Enable history tracking for trend charts
reportgenerator -reports:coverage.xml -targetdir:coveragereport -historydir:coveragehistory
# Use custom plugins
reportgenerator -reports:coverage.xml -targetdir:coveragereport -plugins:CustomReports.dll
```
## .NET Integration with Coverlet
ReportGenerator integrates seamlessly with .NET projects using coverlet for code instrumentation and coverage collection.
```xml
runtime; build; native; contentfiles; analyzers; buildtransitive
all
all
runtime; build; native; contentfiles; analyzers
```
```powershell
# Execute tests with coverage collection
dotnet test --collect:"XPlat Code Coverage"
# Generate HTML report from collected coverage
"%UserProfile%\.nuget\packages\reportgenerator\5.5.4\tools\net8.0\ReportGenerator.exe" -reports:*\TestResults\*\coverage.cobertura.xml -targetdir:coveragereport
```
## .NET Global Tool Installation
Install ReportGenerator as a global dotnet tool for easy command-line access across all projects.
```bash
# Install globally
dotnet tool install -g dotnet-reportgenerator-globaltool
# Install to specific tool path
dotnet tool install dotnet-reportgenerator-globaltool --tool-path tools
# Install as local tool (requires tool-manifest)
dotnet new tool-manifest
dotnet tool install dotnet-reportgenerator-globaltool
# Usage after global installation
reportgenerator -reports:coverage.xml -targetdir:coveragereport -reporttypes:Html;Cobertura
# Usage with tool-path installation
tools\reportgenerator.exe -reports:coverage.xml -targetdir:coveragereport
# Usage as local tool
dotnet reportgenerator -reports:coverage.xml -targetdir:coveragereport
```
## MSBuild Task Integration
Integrate ReportGenerator directly into your MSBuild process for automated report generation during builds.
```xml
```
## .netconfig Configuration File
Persist ReportGenerator settings in a .netconfig file for consistent configuration across team members and CI environments.
```gitconfig
[ReportGenerator]
reports = "coverage.xml"
targetdir = "C:\\report"
reporttypes = "Latex;HtmlSummary"
assemblyfilters = "+Test;-Test"
classfilters = "+Test2;-Test2"
# Multi-valued options using singular entries
[ReportGenerator]
report = "coverage1.xml"
report = "coverage2.xml"
reporttype = "Html"
reporttype = "Cobertura"
assemblyfilter = "+MyApp.*"
assemblyfilter = "-*.Tests"
sourcedir = "src"
sourcedir = "lib"
```
```bash
# Manage .netconfig via CLI
dotnet config reportgenerator.reporttypes "Html;Cobertura"
dotnet config --add reportgenerator.report coverage3.xml
dotnet config --unset-all reportgenerator.assemblyfilter
```
## GitHub Actions Integration
Add ReportGenerator to GitHub Actions workflows for automated coverage reporting in pull requests and builds.
```yaml
name: Build and Test with Coverage
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.x
dotnet-quality: 'ga'
- name: Build and Test
run: dotnet test --collect:"XPlat Code Coverage"
- name: ReportGenerator
uses: danielpalme/ReportGenerator-GitHub-Action@v5
with:
reports: '**/coverage.cobertura.xml'
targetdir: 'coveragereport'
reporttypes: 'HtmlInline;Cobertura;MarkdownSummaryGithub'
assemblyfilters: '+*;-xunit*'
classfilters: '+*'
verbosity: 'Info'
title: 'Code Coverage Report'
tag: '${{ github.run_number }}_${{ github.run_id }}'
- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: CoverageReports
path: coveragereport
```
## GitHub Actions with Coverage History
Track coverage trends over time by persisting history files as artifacts between builds.
```yaml
name: Coverage with History
on: [push]
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.x
- name: Build and Test
run: dotnet test --collect:"XPlat Code Coverage"
- name: Restore coverage history
uses: dawidd6/action-download-artifact@v3
with:
name: CoverageHistory
path: CoverageHistory
continue-on-error: true
- name: ReportGenerator
uses: danielpalme/ReportGenerator-GitHub-Action@5
with:
reports: '*Test*/TestResults/*/coverage.cobertura.xml'
targetdir: 'CoverageReports'
historydir: 'CoverageHistory'
reporttypes: 'HtmlInline;Cobertura;SvgChart'
- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: CoverageReports
path: CoverageReports
- name: Upload coverage history
uses: actions/upload-artifact@v4
with:
name: CoverageHistory
path: CoverageHistory
```
## Azure DevOps Pipeline Integration
Configure ReportGenerator in Azure DevOps YAML pipelines with built-in code coverage publishing.
```yaml
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
disable.coverage.autogenerate: 'true'
steps:
- task: DotNetCoreCLI@2
displayName: 'Build and Test'
inputs:
command: 'test'
arguments: '--collect:"XPlat Code Coverage"'
- task: reportgenerator@5
displayName: 'Generate Coverage Report'
inputs:
reports: '$(Build.SourcesDirectory)/**/coverage.cobertura.xml'
targetdir: '$(Build.SourcesDirectory)/coveragereport'
reporttypes: 'HtmlInline_AzurePipelines;Cobertura;Badges'
assemblyfilters: '-xunit*;-*Tests'
publishCodeCoverageResults: true
title: 'Code Coverage - $(Build.BuildNumber)'
tag: '$(Build.BuildNumber)'
- publish: $(Build.SourcesDirectory)/coveragereport
artifact: CoverageReports
displayName: 'Publish Coverage Artifact'
```
## Azure DevOps with History Storage
Store coverage history in Azure Artifacts Universal Packages for long-term trend tracking.
```yaml
variables:
disable.coverage.autogenerate: 'true'
codecoveragehistory.directory: '$(Build.ArtifactStagingDirectory)\history'
codecoveragehistory.feedName: '$(Build.Repository.Name)-$(Build.SourceBranchName)'
steps:
- task: UniversalPackages@0
displayName: 'Download Coverage History'
continueOnError: true
inputs:
command: 'download'
downloadDirectory: '$(codecoveragehistory.directory)'
feedsToUse: 'internal'
vstsFeed: 'YOUR_FEED_ID'
vstsFeedPackage: '$(codecoveragehistory.feedName)'
vstsPackageVersion: '0.*'
- task: reportgenerator@5
displayName: 'Create Coverage Report'
inputs:
reports: '$(Build.SourcesDirectory)\**\coverage.cobertura.xml'
targetdir: '$(Build.SourcesDirectory)\CodeCoverage'
historydir: '$(codecoveragehistory.directory)'
reporttypes: 'HtmlInline_AzurePipelines;Cobertura;HtmlChart'
title: 'Coverage for $(Build.Repository.Name)'
publishCodeCoverageResults: true
- task: UniversalPackages@0
displayName: 'Publish Coverage History'
inputs:
command: 'publish'
publishDirectory: '$(codecoveragehistory.directory)'
feedsToUsePublish: 'internal'
vstsFeedPublish: 'YOUR_FEED_ID'
vstsFeedPackagePublish: '$(codecoveragehistory.feedName)'
versionOption: 'patch'
```
## GitLab CI Integration
Configure ReportGenerator in GitLab CI pipelines with coverage badge support.
```yaml
stages:
- build
- test
build_job:
stage: build
script:
- 'dotnet restore --packages .nuget'
- 'dotnet publish -c Release .\MyProject\MyProject.csproj'
test_job:
stage: test
script:
- 'mkdir coveragereports'
- 'dotnet test -c Release --collect:"XPlat Code Coverage"'
- '.\.nuget\reportgenerator\5.5.4\tools\net8.0\ReportGenerator.exe -reports:MyProject.Test\TestResults\*\coverage.cobertura.xml -targetdir:coveragereports "-reporttypes:Html;TeamCitySummary" -verbosity:Info -historydir:coveragehistory'
# Regex to extract coverage for GitLab badge
coverage: '/##teamcity\[buildStatisticValue key=''CodeCoverageS'' value=''(\d+\.?\d*)''\]/'
artifacts:
paths:
- '.\coveragereports'
dependencies:
- build_job
```
## Java/JaCoCo Integration
Generate ReportGenerator reports from JaCoCo coverage data in Maven projects.
```xml
org.jacoco
jacoco-maven-plugin
0.8.14
prepare-agent
report
prepare-package
report
```
```powershell
# Run tests and generate JaCoCo report
mvn test jacoco:report
# Install ReportGenerator and generate HTML report
dotnet tool update dotnet-reportgenerator-globaltool --tool-path tools --version 5.5.4
tools\reportgenerator -reports:target\site\jacoco\jacoco.xml -targetdir:coveragereport -sourcedirs:src\main\java -reporttypes:Html;Cobertura
```
## NodeJS/Istanbul Integration
Generate coverage reports from Istanbul/nyc coverage data for JavaScript projects.
```bash
# Install nyc (Istanbul CLI)
npm i nyc --save-dev
# Run tests with coverage collection
nyc --reporter=cobertura mocha
# Install and run ReportGenerator
dotnet tool update dotnet-reportgenerator-globaltool --tool-path tools --version 5.5.4
tools/reportgenerator -reports:coverage/cobertura-coverage.xml -targetdir:coveragereport -reporttypes:Html;MarkdownSummary
```
## Output Format Types
ReportGenerator supports numerous output formats for different use cases and integrations.
```bash
# HTML formats (interactive reports)
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:Html
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:Html_Dark
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:Html_Light
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:Html_BlueRed
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:HtmlInline
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:HtmlInline_AzurePipelines
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:HtmlSummary
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:MHtml
# XML formats (machine-readable)
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:Xml
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:XmlSummary
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:Cobertura
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:Clover
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:OpenCover
# JSON formats
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:JsonSummary
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:CodeClimate
# Markdown formats
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:Markdown
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:MarkdownSummary
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:MarkdownSummaryGithub
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:MarkdownDeltaSummary
# CI/CD specific formats
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:SonarQube
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:TeamCitySummary
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:lcov
# Visual formats
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:Badges
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:SvgChart
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:HtmlChart
# Multiple formats in single run
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:"Html;Cobertura;Badges;MarkdownSummaryGithub"
```
## Coverage Thresholds Configuration
Configure minimum coverage thresholds to fail builds when coverage drops below acceptable levels.
```bash
# Fail if line coverage is below 80%
reportgenerator -reports:coverage.xml -targetdir:report "minimumCoverageThresholds:lineCoverage=80"
# Fail if branch coverage is below 70%
reportgenerator -reports:coverage.xml -targetdir:report "minimumCoverageThresholds:branchCoverage=70"
# Fail if method coverage is below 90%
reportgenerator -reports:coverage.xml -targetdir:report "minimumCoverageThresholds:methodCoverage=90"
# Multiple thresholds combined
reportgenerator -reports:coverage.xml -targetdir:report \
"minimumCoverageThresholds:lineCoverage=80" \
"minimumCoverageThresholds:branchCoverage=70" \
"minimumCoverageThresholds:methodCoverage=85"
```
## Risk Hotspots Configuration
Configure thresholds for identifying and enforcing limits on code complexity metrics.
```bash
# Custom thresholds for risk hotspot identification
reportgenerator -reports:coverage.xml -targetdir:report \
"riskHotspotsAnalysisThresholds:metricThresholdForCyclomaticComplexity=15" \
"riskHotspotsAnalysisThresholds:metricThresholdForCrapScore=30" \
"riskHotspotsAnalysisThresholds:metricThresholdForNPathComplexity=200"
# Fail build if complexity exceeds maximum
reportgenerator -reports:coverage.xml -targetdir:report \
"riskHotspotsAnalysisThresholds:maximumThresholdForCyclomaticComplexity=50" \
"riskHotspotsAnalysisThresholds:maximumThresholdForCrapScore=100"
# Disable risk hotspots analysis entirely
reportgenerator -reports:coverage.xml -targetdir:report "settings:disableRiskHotspots=true"
```
## Advanced Settings
Fine-tune ReportGenerator behavior with advanced configuration options for performance and output customization.
```bash
# Performance tuning: parallel processing
reportgenerator -reports:coverage.xml -targetdir:report \
"settings:numberOfReportsParsedInParallel=4" \
"settings:numberOfReportsMergedInParallel=4"
# Limit history files for faster processing
reportgenerator -reports:coverage.xml -targetdir:report \
"settings:maximumNumberOfHistoricCoverageFiles=50"
# Custom headers for remote file access (e.g., private repos)
reportgenerator -reports:coverage.xml -targetdir:report \
"settings:customHeadersForRemoteFiles=Authorization=Bearer YOUR_TOKEN"
# Create subdirectories for each report type
reportgenerator -reports:coverage.xml -targetdir:report \
-reporttypes:"Html;Cobertura;Badges" \
"settings:createSubdirectoryForAllReportTypes=true"
# Set decimal places for coverage percentages
reportgenerator -reports:coverage.xml -targetdir:report \
"settings:maximumDecimalPlacesForCoverageQuotas=2"
# Default assembly name for gcov/lcov reports
reportgenerator -reports:coverage.xml -targetdir:report \
"settings:defaultAssemblyName=MyApplication"
```
## Custom Report Plugin (IReportBuilder)
Create custom output formats by implementing the IReportBuilder interface and loading as a plugin.
```csharp
// CustomCsvReportBuilder.cs - Create a .NET Standard 2.0 library
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using Palmmedia.ReportGenerator.Core.Parser.Analysis;
using Palmmedia.ReportGenerator.Core.Reporting;
namespace MyCompany.CustomReportTypes
{
public class CsvSummaryReportBuilder : IReportBuilder
{
// Report type name - use with -reporttypes:CsvSummary
public string ReportType => "CsvSummary";
// ReportGenerator injects this context
public IReportContext ReportContext { get; set; }
// Called for each class in coverage data
public void CreateClassReport(Class @class, IEnumerable fileAnalyses)
{
// Implement per-class reporting if needed
}
// Called once with aggregated results
public void CreateSummaryReport(SummaryResult summaryResult)
{
string targetPath = Path.Combine(
this.ReportContext.ReportConfiguration.TargetDirectory,
"Summary.csv");
using (var writer = new StreamWriter(
new FileStream(targetPath, FileMode.Create), Encoding.UTF8))
{
writer.WriteLine("Assembly,Coverage");
foreach (var assembly in summaryResult.Assemblies)
{
var coverage = assembly.CoverageQuota.HasValue
? assembly.CoverageQuota.Value.ToString("f1", CultureInfo.InvariantCulture) + "%"
: "N/A";
writer.WriteLine($"{assembly.Name},{coverage}");
foreach (var @class in assembly.Classes)
{
var classCoverage = @class.CoverageQuota.HasValue
? @class.CoverageQuota.Value.ToString("f1", CultureInfo.InvariantCulture) + "%"
: "N/A";
writer.WriteLine($" {@class.Name},{classCoverage}");
}
}
}
}
}
}
```
```bash
# Build the plugin and use it
dotnet build CustomReports.csproj -c Release
reportgenerator -reports:coverage.xml -targetdir:report -plugins:CustomReports.dll -reporttypes:CsvSummary
```
## Custom History Storage Plugin (IHistoryStorage)
Implement custom storage for coverage history (e.g., cloud storage) by implementing IHistoryStorage.
```csharp
// AmazonS3HistoryStorage.cs - Store history in S3
using System.Collections.Generic;
using System.IO;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.Transfer;
using Palmmedia.ReportGenerator.Core.Reporting.History;
namespace MyCompany.CustomHistoryStorage
{
public class AmazonS3HistoryStorage : IHistoryStorage
{
private readonly string _bucketName;
private readonly AmazonS3Client _client;
public AmazonS3HistoryStorage()
{
// Read from environment or command line arguments
_bucketName = Environment.GetEnvironmentVariable("S3_BUCKET_NAME");
var accessKey = Environment.GetEnvironmentVariable("AWS_ACCESS_KEY_ID");
var secretKey = Environment.GetEnvironmentVariable("AWS_SECRET_ACCESS_KEY");
_client = new AmazonS3Client(accessKey, secretKey, Amazon.RegionEndpoint.USEast1);
}
public IEnumerable GetHistoryFilePaths()
{
var request = new ListObjectsV2Request
{
BucketName = _bucketName,
MaxKeys = 200
};
ListObjectsV2Response response;
do
{
response = _client.ListObjectsV2Async(request).Result;
foreach (S3Object entry in response.S3Objects)
{
yield return entry.Key;
}
request.ContinuationToken = response.NextContinuationToken;
}
while (response.IsTruncated);
}
public Stream LoadFile(string filePath)
{
var transferUtility = new TransferUtility(_client);
return transferUtility.OpenStream(_bucketName, filePath);
}
public void SaveFile(Stream stream, string fileName)
{
var transferUtility = new TransferUtility(_client);
transferUtility.Upload(stream, _bucketName, fileName);
}
}
}
```
```bash
# Use custom history storage plugin
export S3_BUCKET_NAME=my-coverage-history
export AWS_ACCESS_KEY_ID=your_key
export AWS_SECRET_ACCESS_KEY=your_secret
reportgenerator -reports:coverage.xml -targetdir:report -plugins:S3HistoryStorage.dll -reporttypes:Html;HtmlChart
```
## Filtering Coverage Data
Apply filters to include or exclude specific assemblies, classes, and files from coverage reports.
```bash
# Include only specific assemblies (+ prefix)
reportgenerator -reports:coverage.xml -targetdir:report -assemblyfilters:"+MyApp.Core;+MyApp.Services"
# Exclude test assemblies (- prefix)
reportgenerator -reports:coverage.xml -targetdir:report -assemblyfilters:"+*;-*Tests;-*Test;-xunit*"
# Wildcard patterns for assemblies
reportgenerator -reports:coverage.xml -targetdir:report -assemblyfilters:"+MyCompany.*;-*.Tests.*"
# Class filters
reportgenerator -reports:coverage.xml -targetdir:report -classfilters:"+MyApp.Domain.*;-*Generated*"
# File filters
reportgenerator -reports:coverage.xml -targetdir:report -filefilters:"+*.cs;-*Designer.cs;-*.g.cs"
# Risk hotspot filters (separate from main filters)
reportgenerator -reports:coverage.xml -targetdir:report \
-riskhotspotassemblyfilters:"+MyApp.Core" \
-riskhotspotclassfilters:"-*Controller"
# Combined filtering
reportgenerator -reports:coverage.xml -targetdir:report \
-assemblyfilters:"+MyApp.*;-*Tests" \
-classfilters:"+*;-*Generated*" \
-filefilters:"+*;-*.Designer.cs"
```
## Programmatic API Usage
Use ReportGenerator.Core NuGet package to invoke report generation from within your .NET application.
```csharp
// Install: dotnet add package ReportGenerator.Core
using Palmmedia.ReportGenerator.Core;
// Basic programmatic usage
var reportGenerator = new Generator();
var reportConfiguration = new ReportConfiguration(
reportFiles: new[] { "coverage.cobertura.xml" },
targetDirectory: "coveragereport",
sourceDirectories: new[] { "src" },
historyDirectory: "history",
reportTypes: new[] { "Html", "Cobertura", "Badges" },
plugins: Array.Empty(),
assemblyFilters: new[] { "+*", "-*Tests" },
classFilters: new[] { "+*" },
fileFilters: new[] { "+*" },
verbosityLevel: "Info",
title: "My Coverage Report",
tag: "v1.0.0"
);
bool success = reportGenerator.GenerateReport(reportConfiguration);
if (!success)
{
Console.WriteLine("Report generation failed");
Environment.Exit(1);
}
```
## Summary
ReportGenerator serves as the industry-standard tool for code coverage visualization in .NET ecosystems and beyond. Its primary use cases include generating human-readable HTML reports from machine-generated coverage data, tracking coverage trends over time with history charts, enforcing minimum coverage thresholds in CI/CD pipelines, and producing CI-specific outputs for platforms like Azure DevOps, GitHub Actions, GitLab, TeamCity, and SonarQube. The tool excels at merging multiple coverage files from different test projects into unified reports, making it ideal for microservice architectures and monorepos.
Integration patterns typically involve adding ReportGenerator to the test phase of build pipelines, either as a dotnet global tool, NuGet package reference, or platform-specific extension (Azure DevOps, GitHub Actions). For advanced scenarios, the plugin architecture allows custom output formats via IReportBuilder and custom history storage via IHistoryStorage, enabling integration with cloud storage services or proprietary reporting systems. The extensive filtering capabilities allow teams to focus on relevant coverage metrics while excluding generated code, test frameworks, and third-party dependencies from reports.