TeamCity Cloud 2024.03 Help

dotCover

The dotCover runner uses the JetBrains dotCover to produce coverage reports for .NET processes. Generated reports are published to the Code Coverage tab of the Build Results page.

This runner can also be placed after multiple preceding .NET steps to merge their individual code coverages and publish a consolidated report.

dotCover Step Settings

This section explains how to use runner settings. Refer to the sections below for the examples on how to combine these settings depending on your current task.

DotCover Runner Settings
  • dotCover tool — select a dotCover version .

  • Executable and Command line arguments — optional settings that allow you to run a custom process with required arguments under dotCover coverage profile. The Executable field accepts paths to an object that spawns process to profile (for example, to a .NET CLI or to an .exe/.dll of the dotCover tool itself). Leave these settings empty if you use this step to merge snapshots generated by preceding dotCover, .NET, or NUnit runners.

  • Generate coverage report — specifies whether Build Result pages should display data from generated code coverage reports on its Code Coverage tabs.

    Build Code Coverage

    Leave this setting unchecked if you do not need a report published on the Build Results page. For example, if you intend to publish produced .html and .dcvr files as build artifacts and use them elsewhere.

  • Include additional dotCover snapshots to the report — paths to .dcvr snapshots that the runner should use to generate a final coverage report.

    Note that since dotCover automatically gathers snapshots from preceding dotCover and .NET steps, you do not need to define these rules as long as all required snapshots are produced in the same configuration. This setting allows you to include snapshots from stand-alone configurations imported via artifact dependencies.

Advanced Settings

  • Assembly filters — type "+:assemblyName" to include or "-:assemblyName" to exclude assemblies to/from the code coverage.

  • Attribute filters — type "-:attributeName" to exclude any code marked with this attribute from the code coverage.

  • Additional arguments — the list of additional command-line arguments for the dotCover cover command.

Examples: Generating a Consolidated Report

The dotCover runner can be used as a one-stop shop that tests the required project and generates a code coverage report. The following Kotlin DSL sample illustrates this setup.

// Launching .NET to test a project and generate a report object MyConfig : BuildType({ steps { dotCover { name = "dotCover step with .Net test" id = "dotcover" toolPath = "%teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" executable = "%DotNetCLI_Path%" commandLineArguments = """test %teamcity.build.checkoutDir%\ProjectA\proj_A.csproj""" } } }) // Launching .NET to test a project and generate a report object MyConfig : BuildType({ steps { dotCover { id = "dotcover" toolPath = "%teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" executable = "%teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%/dotCover.dll" commandLineArguments = "dotnet --targetWorkingDir=%teamcity.build.checkoutDir% -- test ./ProjectA/proj_A.csproj" } } })

However, in this simple scenario the final result is similar to running a .NET step with dotNet coverage enabled in its settings. The true strength of the dotCover runner lies in its ability to collect snapshots from different sources and produce a combined code coverage report. The samples below illustrate how to set up the dotCover runner depending on the exact sources of these snapshots.

From a Single Build Configuration

The sample configuration below includes multiple .NET steps that test different projects. Each of these steps has "JetBrains dotCover" selected under Code Coverage. The final dotCover step does not produce its own snapshots. Instead, it gathers all .NET runners' snapshots to create a final consolidated report published to the Code Coverage tab.

This setup requires only the Generate coverate report option selected, other runner settings remain empty.

import jetbrains.buildServer.configs.kotlin.* import jetbrains.buildServer.configs.kotlin.buildSteps.dotCover object ConsolidatedReport : BuildType({ id("consolidatedreport") name = "Code coverate report merged from three .NET steps" steps { dotnetTest { id = "dotnet" projects = "projectA/proj_A.csproj" sdk = "6" coverage = dotcover { toolPath = "%teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" } } dotnetTest { id = "dotnet_1" projects = "projectB/proj_B.csproj" sdk = "6" coverage = dotcover { toolPath = "%teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" } } // More .NET runners that test separate projects and generate dotCover snapshots dotCover { id = "dotcover" toolPath = "%teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" } } })

From a Build Chain

The build chain below inludes two configurations.

  • Configuration A runs .NET steps to test individual projects with code coverage. Produced .dcvr snapshots are published as artifacts.

import jetbrains.buildServer.configs.kotlin.* import jetbrains.buildServer.configs.kotlin.buildSteps.dotCover object ConfigA : BuildType({ name = "Configuration A: Test with code coverage and publish snapshots" // Publish snaphots // Note that the path to the snapshot directory may vary depending on the runner type and/or settings // For example, for NUnit runner use "%teamcity.agent.work.dir%\..\temp\agentTmp\dotNetCoverageResults\*.dcvr" instead artifactRules = """%teamcity.agent.work.dir%\..\temp\agentTmp\*.dcvr""" steps { dotnetTest { id = "dotnet" projects = "projectA/proj_A.csproj" sdk = "6" coverage = dotcover { toolPath = "%teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" } } dotnetTest { id = "dotnet_1" projects = "projectB/proj_B.csproj" sdk = "6" coverage = dotcover { toolPath = "%teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" } } // ... // More .NET runners that test separate projects and generate dotCover snapshots } })
  • The final dotCover step of Configuration B creates a joint report by combining the following snapshots:

    • snapshot generated by the .NET step of Configuration B (testing "Project C")

    • dotCover's own snapshot from testing "Project D"

    • snapshots generated by Configuration A and imported to Configuration B via artifact dependencies

import jetbrains.buildServer.configs.kotlin.* import jetbrains.buildServer.configs.kotlin.buildSteps.dotCover object ConfigB : BuildType({ name = "Configuration B: Test with code coverage, import snapshots, and publish report" steps { dotnetTest { id = "dotnet" projects = "projectC/proj_C.csproj" sdk = "6" coverage = dotcover { toolPath = "%teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" } } dotCover { id = "dotcover" toolPath = "%teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" executable = "%DotNetCLI_Path%" commandLineArguments = "test ./ProjectD" snapshotPaths = "%teamcity.build.workingDir%/*.dcvr" } } dependencies { artifacts(Build) { buildRule = lastSuccessful() cleanDestination = true artifactRules = "+:*.dcvr" } } })

From Parallel Tests

Your .NET runners can employ the Parallel Tests build feature to break down huge tests suites into individual batches that are executed on different agents. If you add a dotCover step to a configuration with parallel tests, it will not merge snapshots generated by individual builds that run separate batches. Each individual build will show its own results on the Overview tab of the Build Results page, and the Code Coverage tab with the consolidated report will be absent.

Code coverage with parallel tests

If you want a consolidated report, you can employ a solution similar to the one shown in the From a Build Chain section: create a dependent build configuration that will gather snapshots from all batches and merge them into a single report.

The difference in this use case is that you should rename snapshots before publishing them as artifacts. Otherwise, since each parallel build has identical settings, snapshots have identical names and each build that finishes after a faster parallel build will override its artifacts. Refer to the following section to learn more: Publish Artifacts Produced By Batch Builds

// Primary build configuration // Performs actual tests and generates coverage snapshots object PrimaryConfig : BuildType({ id = AbsoluteId("ConfigA") name = "Build" // use build.parallelTests parameter to generate unique artifact names artifactRules = """%teamcity.agent.work.dir%\..\temp\agentTmp\*.dcvr => Snapshot_%teamcity.build.parallelTests.currentBatch%""" steps { dotnetTest { id = "dotnet_1" projects = "ProjectA/proj_A.csproj" sdk = "6" coverage = dotcover { toolPath = "%teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" } } // .NET runners that test separate projects and generate dotCover snapshots } features { parallelTests { numberOfBatches = 2 } } }) // Dependent build configuration // Retrieves snapshots from parallel builds and produces a consolidated report object DotCoverReportConfig : BuildType({ id = AbsoluteId("ConfigB") name = "dotCover Report" steps { dotCover { id = "dotcover" toolPath = "%teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" snapshotPaths = "%teamcity.build.workingDir%/*/*.dcvr" } } dependencies { artifacts(DotCoverRunner_ParallelTestsWithOneCommonCoverageReport_Build) { buildRule = lastSuccessful() cleanDestination = true artifactRules = "+:*/*.dcvr" } } })
Last modified: 10 April 2024