dotnet-coverage code coverage utility
This article applies to: ✔️ .NET Core 3.1 SDK and later versions
Synopsis
dotnet-coverage [-h, --help] [--version] <command>
Description
The dotnet-coverage
tool:
- Enables the cross-platform collection of code coverage data of a running process.
- Provides cross-platform merging of code coverage reports.
Options
-h|--help
Shows command-line help.
--version
Displays the version of the dotnet-coverage utility.
Install
To install the latest release version of the dotnet-coverage
NuGet package, use the dotnet tool install command:
dotnet tool install --global dotnet-coverage
Commands
Command |
---|
dotnet-coverage merge |
dotnet-coverage collect |
dotnet-coverage connect |
dotnet-coverage snapshot |
dotnet-coverage shutdown |
dotnet-coverage instrument |
dotnet-coverage merge
The merge
command is used to merge several code coverage reports into one. This command is available on all platforms. This command supports the following code coverage report formats:
coverage
cobertura
xml
Synopsis
dotnet-coverage merge
[--remove-input-files]
[-o|--output <output>] [-f|--output-format <output-format>]
[-l|--log-file <log-file>] [-ll|--log-level <log-level>] [-?|-h|--help]
<files>
Arguments
<files>
The input code coverage reports.
Options
--remove-input-files
Removes all input coverage reports that were merged.
-r, --recursive
.NET 7 SDK and earlier versions only Search for coverage reports in subdirectories.
-o|--output <output>
Sets the code coverage report output file.
-f|--output-format <output-format>
The output file format. Supported values:
coverage
,xml
, andcobertura
. Default iscoverage
(binary format that can be opened in Visual Studio).-l|--log-file <log-file>
Sets the log file path. When you provide a directory (with a path separator at the end), a new log file is generated for each process under analysis.
-ll|--log-level <log-level>
Sets the log level. Supported values:
Error
,Info
, andVerbose
.
dotnet-coverage collect
The collect
command is used to collect code coverage data for any .NET process and its subprocesses. For example, you can collect code coverage data for a console application or a Blazor application. This command supports dynamic and static instrumentation. Static instrumentation is available on all platforms. You can specify files to be statically instrumented using include-files
option. Dynamic instrumentation is available on Windows (x86, x64 and Arm64), Linux (x64), and macOS (x64). The command supports only .NET modules. Native modules are not supported.
Synopsis
The collect
command can run in two modes.
Command Mode
The collect
command will collect code coverage for the given process executed by the command
argument.
dotnet-coverage collect
[-s|--settings <settings>] [-id|--session-id <session-id>]
[-if|--include-files <include-files>] [-o|--output <output>]
[-f|--output-format <output-format>] [-l|--log-file <log-file>]
[-ll|--log-level <log-level>] [-?|-h|--help]
<command> <args>
Server Mode
The collect
command hosts a server for code coverage collection. Clients can connect to the server via connect
command.
dotnet-coverage collect
[-s|--settings <settings>] [-id|--session-id <session-id>]
[-sv|--server-mode] [-b|--background] [-t|--timeout]
[-if|--include-files <include-files>] [-o|--output <output>]
[-f|--output-format <output-format>] [-l|--log-file <log-file>]
[-ll|--log-level <log-level>] [-?|-h|--help]
Arguments
<command>
The command for which to collect code coverage data.
<args>
The command line arguments for the command.
Options
-s|--settings <settings>
Sets the path to the XML code coverage settings.
-id|--session-id <session-id>
Specifies the code coverage session ID. If not provided, the tool will generate a random GUID.
-sv|--server-mode
Starts the collector in server mode. Clients can connect to the server with the
connect
command.-b|--background
Starts code coverage collection server in a new background process. Clients can connect to the server with the
connect
command.-t|--timeout
Timeout (in milliseconds) for interprocess communication between clients and the server.
-if|--include-files <include-files>
Specifies list of files to be statically instrumented.
-o|--output <output>
Sets the code coverage report output file.
-f|--output-format <output-format>
The output file format. Supported values:
coverage
,xml
, andcobertura
. Default iscoverage
(binary format that can be opened in Visual Studio).-l|--log-file <log-file>
Sets the log file path. When you provide a directory (with a path separator at the end), a new log file is generated for each process under analysis.
-ll|--log-level <log-level>
Sets the log level. Supported values:
Error
,Info
, andVerbose
.
dotnet-coverage connect
The connect
command is used to connect with the existing server and collects code coverage data for any .NET process and its subprocesses. For example, you can collect code coverage data for a console application or a Blazor application. The command supports only .NET modules. Native modules are not supported.
Note
Command will use dynamic instrumentation for all subprocesses which is available on Windows (x86, x64 and Arm64), Linux (x64), and macOS (x64). If you need to statically instrument any .NET module use instrument
command (with corresponding session ID option) before executing connect
command.
Synopsis
dotnet-coverage connect
[-b|--background] [-t|--timeout]
[-l|--log-file <log-file>] [-ll|--log-level <log-level>] [-?|-h|--help]
<session>
<command> <args>
Arguments
<session>
The session ID of the server hosted by the
collect
command.<command>
The command for which to collect code coverage data.
<args>
The command line arguments for the command.
Options
-b|--background
Starts the client in a new background process.
-t|--timeout
Timeout (in milliseconds) for interprocess communication between the client and the server.*
-l|--log-file <log-file>
-l|--log-file <log-file>
Sets the log file path. When you provide a directory (with a path separator at the end), a new log file is generated for each process under analysis.
-ll|--log-level <log-level>
Sets the log level. Supported values:
Error
,Info
, andVerbose
.
dotnet-coverage snapshot
Creates a coverage file for existing code coverage collection.
Synopsis
dotnet-coverage snapshot
[-r|--reset]
[-o|--output <output>]
[-tn|--tag-name <tag-name>] [-tid|--tag-identifier <tag-identifier>]
[-t|--timeout]
[-l|--log-file <log-file>] [-ll|--log-level <log-level>] [-?|-h|--help]
<session>
Arguments
<session>
The session ID of the collection for which a coverage file is to be generated.
Options
-r|--reset <reset>
Clears existing coverage information after a coverage file is created.
-o|--output <output>
Sets the code coverage report output file. If not provided, it's generated automatically with a timestamp.
-tn|--tag-name <tag-name>
Creates a snapshot tag name in the coverage file with current coverage information. Tag-name and tag-identifier are mutually inclusive.
-tid|--tag-identifier <tag-identifier>
Creates a snapshot tag identifier in the coverage file with current coverage information. Tag-name and tag-identifier are mutually inclusive.
-t|--timeout
Timeout (in milliseconds) for interprocess communication between the client and the server.
-l|--log-file <log-file>
Sets the log file path. When you provide a directory (with a path separator at the end), a new log file is generated for each process under analysis.
-ll|--log-level <log-level>
Sets the log level. Supported values:
Error
,Info
, andVerbose
.
dotnet-coverage shutdown
Closes existing code coverage collection.
Synopsis
dotnet-coverage shutdown
[-t|--timeout]
[-l|--log-file <log-file>] [-ll|--log-level <log-level>] [-?|-h|--help]
<session>
Arguments
<session>
The session ID of the collection to be closed.
Options
-t|--timeout
Timeout (in milliseconds) for interprocess communication with the server.
-l|--log-file <log-file>
Sets the log file path. When you provide a directory (with a path separator at the end), a new log file is generated for each process under analysis.
-ll|--log-level <log-level>
Sets the log level. Supported values:
Error
,Info
, andVerbose
.
dotnet-coverage instrument
The instrument command is used to instrument binary on disk.
Synopsis
dotnet-coverage instrument
[-s|--settings <settings>] [-id|--session-id <session-id>]
[-o|--output <output>] [-l|--log-file <log-file>]
[-ll|--log-level <log-level>] [-?|-h|--help]
<input-file>
Arguments
<input-file>
The input binary.
Options
-s|--settings <settings>
Sets the path to the XML code coverage settings.
-id|--session-id <session-id>
Specifies the code coverage session ID. If not provided, the tool will generate a random GUID.
-o|--output <output>
Sets the path to output file binary. If not provided, instrumentation will be performed in-place.
-l|--log-file <log-file>
Sets the log file path. When you provide a directory (with a path separator at the end), a new log file is generated for each process under analysis.
-ll|--log-level <log-level>
Sets the log level. Supported values:
Error
,Info
, andVerbose
.
Sample scenarios
Collecting code coverage
Collect code coverage data for any .NET application (such as console or Blazor) by using the following command:
dotnet-coverage collect dotnet run
In case of an application that requires a signal to terminate, you can use Ctrl+C, which will still let you collect code coverage data. For the argument, you can provide any command that will eventually start a .NET app. For example, it can be a PowerShell script.
Sessions
When you're running code coverage analysis on a .NET server that just waits for messages and sends responses, you need a way to stop the server to get final code coverage results. You can use Ctrl+C locally, but not in Azure Pipelines. For these scenarios, you can use sessions. You can specify a session ID when starting collection, and then use the shutdown
command to stop collection and the server.
For example, assume you have a server in the D:\serverexample\server directory and a test project in the D:\serverexample\tests directory. Tests are communicating with the server through the network. You can start code coverage collection for the server as follows:
D:\serverexample\server> dotnet-coverage collect --session-id serverdemo "dotnet run"
Session ID was specified as serverdemo
. Then you can run tests as follows:
D:\serverexample\tests> dotnet test
A code coverage file for session serverdemo
can be generated with current coverage as follows:
dotnet-coverage snapshot --output after_first_test.coverage serverdemo
Also, a snapshot tag can be added to the coverage file using tag options as follows:
dotnet-coverage snapshot --tag-name after_first_test --tag-identifier after_first_test serverdemo
Finally, session serverdemo
and the server can be closed as follows:
dotnet-coverage shutdown serverdemo
Following is an example of full output on the server side:
D:\serverexample\server> dotnet-coverage collect --session-id serverdemo "dotnet run"
SessionId: serverdemo
Waiting for a connection... Connected!
Received: Hello!
Sent: HELLO!
Waiting for a connection... Code coverage results: output.coverage.
D:\serverexample\server>
Server and client mode
Code coverage collection can be done in server-client mode as well. In this scenario, a code coverage collection server starts, and multiple clients can connect with the server. Code coverage is collected for all the clients collectively.
Start the code coverage server using the following command:
dotnet-coverage collect --session-id serverdemo --server-mode
In this example, the session ID was specified as serverdemo
for the server. A client can connect to the server using this session ID using the following command:
dotnet-coverage connect serverdemo dotnet run
Finally, you can close the session serverdemo
and the server using the following command:
dotnet-coverage shutdown serverdemo
The server process creates a collective code coverage report for all clients and exits.
Following is an example of full output on the server side:
D:\serverexample\server> dotnet-coverage collect --session-id serverdemo --server-mode
SessionId: serverdemo
// Server will be in idle state and wait for connect and shutdown commands
Code coverage results: output.coverage.
D:\serverexample\server>
Following is an example of full output on the client side:
D:\serverexample\server> dotnet-coverage connect serverdemo ConsoleApplication.exe World
Hello World!!
D:\serverexample\server> dotnet-coverage connect serverdemo WpfApplication.exe
D:\serverexample\server> dotnet-coverage shutdown serverdemo
D:\serverexample\server>
You can also start both server and client in background mode. Another process starts in the background and returns control back to the user.
Following is an example of full output in background server client mode:
D:\serverexample\server> dotnet-coverage collect --session-id serverdemo --server-mode --background
D:\serverexample\server> dotnet-coverage connect --background serverdemo ConsoleApplication.exe World
D:\serverexample\server> dotnet-coverage connect --background serverdemo WpfApplication.exe
D:\serverexample\server> dotnet-coverage shutdown serverdemo
D:\serverexample\server>
Static code coverage for managed assemblies
The dotnet-coverage tool can be used to collect code coverage for managed assemblies using static instrumentation. There are three different methods available that you can use. To demonstrate, let's assume we have a simple C# console application:
D:\examples\ConsoleApp> dotnet run
Hello, World!
Use collect command with include files option or configuration
If you don't want to use the instrument
command, then the files to be instrumented can be specified using --include-files
option as follows:
D:\examples\ConsoleApp> dotnet-coverage collect --include-files .\bin\Debug\net7.0\*.dll dotnet run
Microsoft (R) Code Coverage Command Line Tool (x64)
Copyright (c) Microsoft Corporation. All rights reserved.
SessionId: 57862ec0-e512-49a5-8b66-2804174680fc
Hello, World!
Code coverage results: output.coverage.
You can also specify files to be instrumented using configuration as follows:
<ModulePaths>
<IncludeDirectories>
<Directory>D:\examples\ConsoleApp\bin\Debug\net7.0</Directory>
</IncludeDirectories>
</ModulePaths>
Using instrument and collect commands
In this case, first binary needs to be instrumented as follows:
D:\examples\ConsoleApp> dotnet-coverage instrument .\bin\Debug\net7.0\ConsoleApp.dll
Microsoft (R) Code Coverage Command Line Tool (x64)
Copyright (c) Microsoft Corporation. All rights reserved.
Input file successfully instrumented.
Then you can collect code coverage as follows:
D:\examples\ConsoleApp> dotnet-coverage collect .\bin\Debug\net7.0\ConsoleApp.exe
Microsoft (R) Code Coverage Command Line Tool (x64)
Copyright (c) Microsoft Corporation. All rights reserved.
SessionId: a09e6bef-ff64-4b5f-8bb8-fc495ebb50ba
Hello, World!
Code coverage results: output.coverage.
Use the instrument and collect commands in server mode
In this case, you can completely separate coverage collection from running your application. First, instrument your binary as follows:
D:\examples\ConsoleApp> dotnet-coverage instrument --session-id 73c34ce5-501c-4369-a4cb-04d31427d1a4 .\bin\Debug\net7.0\ConsoleApp.dll
Microsoft (R) Code Coverage Command Line Tool (x64)
Copyright (c) Microsoft Corporation. All rights reserved.
Input file successfully instrumented.
Note
Session ID needs to be used in this scenario to make sure that the application can connect and provide data to external collector.
In the second step, you need to start coverage collector as follows:
D:\examples\ConsoleApp> dotnet-coverage collect --session-id 73c34ce5-501c-4369-a4cb-04d31427d1a4 --server-mode
Microsoft (R) Code Coverage Command Line Tool (x64)
Copyright (c) Microsoft Corporation. All rights reserved.
SessionId: 73c34ce5-501c-4369-a4cb-04d31427d1a4
Then the application can be started as follows:
D:\examples\ConsoleApp> .\bin\Debug\net7.0\ConsoleApp.exe
Hello, World!
Finally, the collector can be closed as follows:
D:\examples\ConsoleApp> dotnet-coverage shutdown 73c34ce5-501c-4369-a4cb-04d31427d1a4
Microsoft (R) Code Coverage Command Line Tool (x64)
Copyright (c) Microsoft Corporation. All rights reserved.
Settings
You can specify a file with settings when you use the collect
command. The settings file can be used to exclude some modules or methods from code coverage analysis. The format is the same as the data collector configuration inside a runsettings file. For more information, see Customize code coverage analysis. Here's an example:
<?xml version="1.0" encoding="utf-8"?>
<Configuration>
<CodeCoverage>
<!--
Additional paths to search for .pdb (symbol) files. Symbols must be found for modules to be instrumented.
If .pdb files are in the same folder as the .dll or .exe files, they are automatically found. Otherwise, specify them here.
Note that searching for symbols increases code coverage run time. So keep this small and local.
-->
<SymbolSearchPaths>
<Path>C:\Users\User\Documents\Visual Studio 2012\Projects\ProjectX\bin\Debug</Path>
<Path>\\mybuildshare\builds\ProjectX</Path>
</SymbolSearchPaths>
<!--
About include/exclude lists:
Empty "Include" clauses imply all; empty "Exclude" clauses imply none.
Each element in the list is a regular expression (ECMAScript syntax). See /visualstudio/ide/using-regular-expressions-in-visual-studio.
An item must first match at least one entry in the include list to be included.
Included items must then not match any entries in the exclude list to remain included.
-->
<!-- Match assembly file paths: -->
<ModulePaths>
<Include>
<ModulePath>.*\.dll$</ModulePath>
<ModulePath>.*\.exe$</ModulePath>
</Include>
<Exclude>
<ModulePath>.*CPPUnitTestFramework.*</ModulePath>
</Exclude>
<!-- Additional directories from .NET assemblies should be statically instrumented: -->
<IncludeDirectories>
<Directory Recursive="true">C:\temp</Directory>
</IncludeDirectories>
</ModulePaths>
<!-- Match fully qualified names of functions: -->
<!-- (Use "\." to delimit namespaces in C# or Visual Basic, "::" in C++.) -->
<Functions>
<Exclude>
<Function>^Fabrikam\.UnitTest\..*</Function>
<Function>^std::.*</Function>
<Function>^ATL::.*</Function>
<Function>.*::__GetTestMethodInfo.*</Function>
<Function>^Microsoft::VisualStudio::CppCodeCoverageFramework::.*</Function>
<Function>^Microsoft::VisualStudio::CppUnitTestFramework::.*</Function>
</Exclude>
</Functions>
<!-- Match attributes on any code element: -->
<Attributes>
<Exclude>
<!-- Don't forget "Attribute" at the end of the name -->
<Attribute>^System\.Diagnostics\.DebuggerHiddenAttribute$</Attribute>
<Attribute>^System\.Diagnostics\.DebuggerNonUserCodeAttribute$</Attribute>
<Attribute>^System\.CodeDom\.Compiler\.GeneratedCodeAttribute$</Attribute>
<Attribute>^System\.Diagnostics\.CodeAnalysis\.ExcludeFromCodeCoverageAttribute$</Attribute>
</Exclude>
</Attributes>
<!-- Match the path of the source files in which each method is defined: -->
<Sources>
<Exclude>
<Source>.*\\atlmfc\\.*</Source>
<Source>.*\\vctools\\.*</Source>
<Source>.*\\public\\sdk\\.*</Source>
<Source>.*\\microsoft sdks\\.*</Source>
<Source>.*\\vc\\include\\.*</Source>
</Exclude>
</Sources>
<!-- Match the company name property in the assembly: -->
<CompanyNames>
<Exclude>
<CompanyName>.*microsoft.*</CompanyName>
</Exclude>
</CompanyNames>
<!-- Match the public key token of a signed assembly: -->
<PublicKeyTokens>
<!-- Exclude Visual Studio extensions: -->
<Exclude>
<PublicKeyToken>^B77A5C561934E089$</PublicKeyToken>
<PublicKeyToken>^B03F5F7F11D50A3A$</PublicKeyToken>
<PublicKeyToken>^31BF3856AD364E35$</PublicKeyToken>
<PublicKeyToken>^89845DCD8080CC91$</PublicKeyToken>
<PublicKeyToken>^71E9BCE111E9429C$</PublicKeyToken>
<PublicKeyToken>^8F50407C4E9E73B6$</PublicKeyToken>
<PublicKeyToken>^E361AF139669C375$</PublicKeyToken>
</Exclude>
</PublicKeyTokens>
<EnableStaticManagedInstrumentation>True</EnableStaticManagedInstrumentation>
<EnableDynamicManagedInstrumentation>True</EnableDynamicManagedInstrumentation>
</CodeCoverage>
</Configuration>
Merge code coverage reports
You can merge a.coverage
and b.coverage
and store the data in merged.coverage
as follows:
dotnet-coverage merge -o merged.coverage a.coverage b.coverage
For example, if you run a command like dotnet test --collect "Code Coverage"
, the coverage report is stored into a folder that is named a random GUID. Such folders are hard to find and merge. Using this tool, you can merge all code coverage reports for all your projects using globbing patterns as follows:
dotnet-coverage merge -o merged.cobertura.xml -f cobertura **\*.coverage
The preceding command merges all coverage reports from the current directory and all subdirectories and stores the result into a cobertura file. In Azure Pipelines, you can use Publish Code Coverage Results task to publish a merged cobertura report.
You can use the merge
command to convert a code coverage report to another format. For example, the following command converts a binary code coverage report into XML format.
dotnet-coverage merge -o output.xml -f xml input.coverage