dotnet-coverage 代码覆盖率实用工具

本文适用于: ✔️ .NET Core 3.1 SDK 及更高版本

摘要

dotnet-coverage [-h, --help] [--version] <command>

描述

dotnet-coverage 工具:

  • 启用跨平台收集正在运行的进程的代码覆盖率数据。
  • 提供代码覆盖率报表的跨平台合并。

选项

  • -h|--help

    显示命令行帮助。

  • --version

    显示 dotnet-coverage 实用工具的版本。

安装

若要安装最新版 dotnet-coveragedotnet-coverage,请使用 dotnet tool install 命令:

dotnet tool install --global dotnet-coverage

命令

Command
dotnet-coverage merge
dotnet-coverage collect
dotnet-coverage connect
dotnet-coverage snapshot
dotnet-coverage shutdown
dotnet-coverage 检测

dotnet-coverage merge

merge 命令用于将多个代码覆盖率报表合并为一个。 此命令在所有平台上均可用。 此命令支持以下代码覆盖率报表格式:

  • coverage
  • cobertura
  • xml

摘要

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>

自变量

  • <files>

    输入代码覆盖率报表。

选项

  • --remove-input-files

    删除所有已合并的输入覆盖率报表。

  • -r, --recursive

    仅限 .NET 7 SDK 及更早版本 在子目录中搜索覆盖率报告。

  • -o|--output <output>

    设置代码覆盖率报表输出文件。

  • -f|--output-format <output-format>

    输出文件格式。 受支持的值为:coveragexmlcobertura。 默认值为 coverage(可在 Visual Studio 中打开的二进制格式)。

  • -l|--log-file <log-file>

    设置日志文件路径。 如果提供目录(末尾有路径分隔符),则将为分析下的每个进程生成新的日志文件。

  • -ll|--log-level <log-level>

    设置日志级别。 受支持的值为:ErrorInfoVerbose

dotnet-coverage collect

collect 命令用于收集任何 .NET 进程及其子进程的代码覆盖率数据。 例如,可以收集控制台应用程序或 Blazor 应用程序的代码覆盖率数据。 此命令支持动态和静态检测。 静态检测在所有平台上可用。 可以使用 include-files 选项指定要进行静态检测的文件。 动态监测适用于 Windows(x86、x64 和 Arm64)、Linux (x64) 和 macOS (x64)。 该命令仅支持 .NET 模块。 不支持本机模块。

摘要

collect 命令可按以下两种模式运行。

命令模式

collect 命令将收集 command 参数执行的给定进程的代码覆盖率。

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>

服务器模式

collect 命令托管用于代码覆盖率收集的服务器。 客户端可以通过 connect 命令连接到服务器。

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]

自变量

  • <command>

    用于收集其代码覆盖率数据的命令。

  • <args>

    命令的命令行参数。

选项

  • -s|--settings <settings>

    设置 XML 代码覆盖率设置的路径。

  • -id|--session-id <session-id>

    指定代码覆盖率会话 ID。 如果未提供,该工具将生成随机 GUID。

  • -sv|--server-mode

    在服务器模式下启动收集器。 客户端可以使用 connect 命令连接到服务器。

  • -b|--background

    在新的后台进程中启动代码覆盖率收集服务器。 客户端可以使用 connect 命令连接到服务器。

  • -t|--timeout

    客户端与服务器之间的进程间通信的超时(以毫秒计)。

  • -if|--include-files <include-files>

    指定要进行静态检测的文件的列表。

  • -o|--output <output>

    设置代码覆盖率报表输出文件。

  • -f|--output-format <output-format>

    输出文件格式。 受支持的值为:coveragexmlcobertura。 默认值为 coverage(可在 Visual Studio 中打开的二进制格式)。

  • -l|--log-file <log-file>

    设置日志文件路径。 如果提供目录(末尾有路径分隔符),则将为分析下的每个进程生成新的日志文件。

  • -ll|--log-level <log-level>

    设置日志级别。 受支持的值为:ErrorInfoVerbose

dotnet-coverage connect

connect 命令用于连接现有服务器,并收集任何 .NET 进程及其子进程的代码覆盖率数据。 例如,可以收集控制台应用程序或 Blazor 应用程序的代码覆盖率数据。 该命令仅支持 .NET 模块。 不支持本机模块。

注意

命令将对 Windows (x86、x64 和 Arm64) 、Linux (x64) 和 macOS (x64) 上可用的所有子进程使用动态检测。 如果需要对任何 .NET 模块进行静态检测,请在执行 connect 命令之前使用 instrument 命令(具有相应会话 ID 选项)。

摘要

dotnet-coverage connect
    [-b|--background] [-t|--timeout]
    [-l|--log-file <log-file>] [-ll|--log-level <log-level>] [-?|-h|--help]
    <session>
    <command> <args>

自变量

  • <session>

    collect 命令托管的服务器的会话 ID。

  • <command>

    用于收集其代码覆盖率数据的命令。

  • <args>

    命令的命令行参数。

选项

  • -b|--background

    在新的后台进程中启动客户端。

  • -t|--timeout

    客户端与服务器之间的进程间通信的超时(以毫秒计)。* -l|--log-file <log-file>

  • -l|--log-file <log-file>

    设置日志文件路径。 如果提供目录(末尾有路径分隔符),则将为分析下的每个进程生成新的日志文件。

  • -ll|--log-level <log-level>

    设置日志级别。 受支持的值为:ErrorInfoVerbose

dotnet-coverage snapshot

为现有代码覆盖率收集创建覆盖率文件。

摘要

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>

自变量

  • <session>

    要为其生成覆盖率文件的收集的会话 ID。

选项

  • -r|--reset <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>

    设置日志级别。 受支持的值为:ErrorInfoVerbose

dotnet-coverage shutdown

关闭现有代码覆盖率集合。

摘要

dotnet-coverage shutdown
    [-t|--timeout]
    [-l|--log-file <log-file>] [-ll|--log-level <log-level>] [-?|-h|--help]
    <session>

自变量

  • <session>

    要关闭的集合的会话 ID。

选项

  • -t|--timeout

    与服务器进行进程间通信的超时(以毫秒计)。

  • -l|--log-file <log-file>

    设置日志文件路径。 如果提供目录(末尾有路径分隔符),则将为分析下的每个进程生成新的日志文件。

  • -ll|--log-level <log-level>

    设置日志级别。 受支持的值为:ErrorInfoVerbose

dotnet-coverage 检测

检测命令用于检测磁盘上的二进制文件。

摘要

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>

自变量

  • <input-file>

    二进制文件。

选项

  • -s|--settings <settings>

    设置 XML 代码覆盖率设置的路径。

  • -id|--session-id <session-id>

    指定代码覆盖率会话 ID。 如果未提供,该工具将生成随机 GUID。

  • -o|--output <output>

    设置输出文件二进制文件的路径。 如果未提供,将就地执行检测。

  • -l|--log-file <log-file>

    设置日志文件路径。 如果提供目录(末尾有路径分隔符),则将为分析下的每个进程生成新的日志文件。

  • -ll|--log-level <log-level>

    设置日志级别。 受支持的值为:ErrorInfoVerbose

示例方案

收集代码覆盖率

使用以下命令收集任何 .NET 应用程序(如控制台或 Blazor)的代码覆盖率数据:

dotnet-coverage collect dotnet run

对于需要终止信号的应用程序,可以使用 Ctrl+C,这样仍可收集代码覆盖率数据。 对于参数,可以提供最终启动 .NET 应用的任何命令。 例如,它可以是 PowerShell 脚本。

会话

在仅等待消息并发送响应的 .NET 服务器上运行代码覆盖率分析时,需要一种方法来停止该服务器,以获得最终的代码覆盖率结果。 可以在本地使用 Ctrl+C,但不能在 Azure Pipelines 中使用。 对于这些情况,可以使用会话。 可以在启动收集时指定会话 ID,然后使用 shutdown 命令停止收集和服务器。

例如,假设你在 D:\serverexample\server 目录中有一个服务器,在 D:\serverexample\tests 目录中有一个测试项目。 测试正在通过网络与服务器通信。 可以启动服务器的代码覆盖率收集,如下所示:

D:\serverexample\server> dotnet-coverage collect --session-id serverdemo "dotnet run"

会话 ID 指定为 serverdemo。 然后,可以按如下所示运行测试:

D:\serverexample\tests> dotnet test

可以使用当前覆盖率生成 serverdemo 会话的代码覆盖率文件,如下所示:

dotnet-coverage snapshot --output after_first_test.coverage serverdemo

此外,还可以使用标记选项将快照标记添加到覆盖率文件,如下所示:

dotnet-coverage snapshot --tag-name after_first_test --tag-identifier after_first_test serverdemo

最后,serverdemo 会话和服务器可以关闭,如下所示:

dotnet-coverage shutdown serverdemo

下面是服务器端的完整输出示例:

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>

服务器和客户端模式

也可以在服务器-客户端模式下完成代码覆盖率收集。 在此场景中,代码覆盖率收集服务器启动,多个客户端可以连接到服务器。 统一收集所有客户端的代码覆盖率。

使用以下命令启动代码覆盖率服务器:

dotnet-coverage collect --session-id serverdemo --server-mode

在此示例中,会话 ID 被指定为服务器的 serverdemo。 客户端可以通过以下命令使用此会话 ID 连接到服务器:

dotnet-coverage connect serverdemo dotnet run

最后,可以使用以下命令关闭会话 serverdemo 和服务器:

dotnet-coverage shutdown serverdemo

服务器进程为所有客户端创建集体代码覆盖率报表并退出。

下面是服务器端的完整输出示例:

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>

下面是客户端的完整输出示例:

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>

你还可以在后台模式下启动服务器和客户端。 另一个进程在后台启动,并将控件返回给用户。

下面是后台服务器客户端模式下完整输出的示例:

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>

托管程序集的静态代码覆盖率

dotnet-coverage 工具可用于收集使用静态检测的托管程序集的代码覆盖率。 可以使用三种不同的方法。 为了演示,假设我们具有一个简单的 C# 控制台应用程序:

D:\examples\ConsoleApp> dotnet run
Hello, World!

将 collect 命令与 include files 选项或配置配合使用

如果不想使用 instrument 命令,则可以使用 --include-files 选项指定要检测的文件,如下所示:

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.

还可以使用如下所示的配置指定要检测的文件:

<ModulePaths>
  <IncludeDirectories>
    <Directory>D:\examples\ConsoleApp\bin\Debug\net7.0</Directory>
  </IncludeDirectories>
</ModulePaths>

使用检测和收集命令

在这种情况下,需要按如下所示检测第一个二进制文件:

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.

然后,可以按如下所示收集代码覆盖率:

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.

在服务器模式下使用检测和收集命令

在这种情况下,可以将覆盖率收集与运行应用程序完全分开。 首先,按如下所示检测二进制文件:

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.

注意

此方案中需要使用会话 ID,以确保应用程序可以连接数据并将数据提供给外部收集器。

在第二步中,需要按如下方式启动覆盖率收集器:

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

然后,可按如下所示启动应用程序:

D:\examples\ConsoleApp> .\bin\Debug\net7.0\ConsoleApp.exe
Hello, World!

最后,可按如下方式关闭收集器:

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.

设置

使用 collect 命令时,可以指定具有设置的文件。 设置文件可用于从代码覆盖率分析中排除某些模块或方法。 格式与 runsettings 文件中数据收集器配置的格式相同。 有关详细信息,请参阅自定义代码覆盖率分析。 下面是一个示例:

<?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>

合并代码覆盖率报表

可以合并 a.coverageb.coverage并将数据存储在 merged.coverage 中,如下所示:

dotnet-coverage merge -o merged.coverage a.coverage b.coverage

例如,如果运行类似 dotnet test --collect "Code Coverage" 的命令,则覆盖率报表将存储到命名为随机 GUID 的文件夹中。 此类文件夹难以查找和合并。 使用此工具,可以使用 glob 模式合并所有项目的所有代码覆盖率报告,如下所示:

dotnet-coverage merge -o merged.cobertura.xml -f cobertura **\*.coverage

上述命令将合并当前目录和所有子目录中的所有覆盖率报表,并将结果存储到 cobertura 文件中。 在 Azure Pipelines 中,可以使用“发布代码覆盖率结果”任务发布合并的 cobertura 报表。

可以使用 merge 命令将代码覆盖率报表转换为其他格式。 例如,以下命令将二进制代码覆盖率报表转换为 XML 格式。

dotnet-coverage merge -o output.xml -f xml input.coverage

请参阅