Dotnet solution: Code coverage cannot exclude modules/assemblies

42 Views Asked by At

I have an integration test project with the following config in the project's .csproj file:

<PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <RunSettingsFilePath>$(MSBuildProjectDirectory)\project.runsettings</RunSettingsFilePath>
</PropertyGroup>

In the same directory as the .csproj file, I have the file project.runsettings that contains:

<?xml version="1.0" encoding="utf-8" ?>
<RunSettings>
    <DataCollectionRunSettings>
        <DataCollectors>
            <DataCollector friendlyName="XPlat code coverage">
                <Configuration>
                    <CodeCoverage>
                        <ModulePaths>
                            <Exclude>
                                <ModulePath>microsoft.azure.webjobs.*</ModulePath>
                            </Exclude>
                        </ModulePaths>
                        <UseVerifiableInstrumentation>True</UseVerifiableInstrumentation>
                        <AllowLowIntegrityProcesses>True</AllowLowIntegrityProcesses>
                        <CollectFromChildProcesses>True</CollectFromChildProcesses>
                        <CollectAspDotNet>False</CollectAspDotNet>
                    </CodeCoverage>
                </Configuration>
            </DataCollector>
        </DataCollectors>
    </DataCollectionRunSettings>
</RunSettings>

When I run this test locally, and I inspect the generated coverage report, the excluded modules are properly excluded; they don't figure in the report. But when running the same test in a Devops pipeline, I see the excluded modules included:

Code Coverage

How to exclude them in the pipeline build? I followed the docs but I'm not seeing what I would expect. Code coverage of the excluded modules is artificially lowering the total percentage of code coverage.

2

There are 2 best solutions below

0
Andrew Plank On BEST ANSWER

I got it working in the end. I was missing the coverlet.msbuild NuGet package in my project. It turns out both coverlet.collector (which I had installed) and coverlet.msbuild are required.

The reference to the project.runsettings file was correct. Its content needed to be slightly updated:

<?xml version="1.0" encoding="utf-8" ?>
<RunSettings>
    <DataCollectionRunSettings>
        <DataCollectors>
            <DataCollector friendlyName="XPlat code coverage">
                <Configuration>
                    <Format>cobertura</Format>
                    <Exclude>[microsoft.azure.webjobs.*]*</Exclude>
                </Configuration>
            </DataCollector>
        </DataCollectors>
    </DataCollectionRunSettings>
</RunSettings>

And also, I needed to adjust my Azure pipelines yaml file to contain:

# Perform .Net 6 Test
- task: DotNetCoreCLI@2
  displayName: Test
  inputs:
    command: test
    projects: 'src/$(Build.Repository.Name).sln'
    publishTestResults: true
    arguments: '--configuration $(build_configuration) /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura'
  condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))

# Publish code coverage results
- task: PublishCodeCoverageResults@1
  displayName: 'Publish code coverage results'
  inputs:
    codeCoverageTool: 'Cobertura'
    summaryFileLocation: '**/*coverage.cobertura.xml'
  condition: and(succeededOrFailed(), eq(variables['Build.Reason'], 'PullRequest'))

In your use case, it's likely your conditions will be different.

This was enough to get it working and generating a code coverage report. Hope this helps someone in the future!

0
Ziyang Liu-MSFT On

You can use runSettingsFile in VSTest@3 task to specify the path to your runsettings file.

- task: VSTest@3
  inputs:
    testSelector: 'testAssemblies'
    testAssemblyVer2: |
      **\*test*.dll
      !**\*TestAdapter.dll
      !**\obj\**
    searchFolder: '$(System.DefaultWorkingDirectory)'
    runSettingsFile: '$(Build.SourcesDirectory)/unit-testing-using-mstest/.runsettings'
    codeCoverageEnabled: true