.NET 6+Azure DevOps环境下ReportGenerator无法查看单个文件覆盖率
问题分析与解决方案
问题根源
报错File '/src/xxx.cs' does not exist是因为Docker容器内生成的Cobertura报告中,文件路径使用的是容器内部的绝对路径(/src/开头),但Azure DevOps代理主机上的源码存储在$(Build.SourcesDirectory)路径下,两者路径不匹配导致无法定位文件。
解决方案
我们不需要在Docker容器内生成合并的覆盖率报告,改为在Azure代理主机上完成报告合并与路径映射,既避免路径不匹配问题,也无需安装Azure DevOps插件(仅用dotnet tool命令行工具即可)。
步骤1:修改Dockerfile
移除容器内的ReportGenerator执行步骤,仅保留测试生成单个项目覆盖率报告的逻辑:
# Run tests for individual test projects to generate test and code coverage report RUN dotnet test "PreAdviceGeneration.Presentation.UnitTests/PreAdviceGeneration.Presentation.UnitTests.csproj" \ --logger "trx;LogFileName=PreAdviceGeneration.Presentation.UnitTests.trx" \ --results-directory /TestResults \ /p:CoverletOutput=/TestResults/presentation/ /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura RUN dotnet test "PreAdviceGeneration.Application.UnitTests/PreAdviceGeneration.Application.UnitTests.csproj" \ --logger "trx;LogFileName=PreAdviceGeneration.Application.UnitTests.trx" \ --results-directory /TestResults \ /p:CoverletOutput=/TestResults/application/ /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura RUN dotnet test "PreAdviceGeneration.Infrastructure.IntegrationTests/PreAdviceGeneration.Infrastructure.IntegrationTests.csproj" \ --results-directory /TestResults \ --logger "trx;LogFileName=PreAdviceGeneration.Infrastructure.IntegrationTests.trx" \ /p:CoverletOutput=/TestResults/infrastructure/ /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura
步骤2:修改Azure DevOps流水线
在代理主机上安装ReportGenerator工具,合并报告并完成路径映射:
- task: CmdLine@2 displayName: Copy test results to the agent inputs: script: | echo 'Default directory is::: $(System.DefaultWorkingDirectory)' echo 'Source directory is:::: $(Build.SourcesDirectory)' echo 'ArtifactStagingDirectory is:::: $(Build.ArtifactStagingDirectory)' docker build -f $(Build.SourcesDirectory)/Dockerfile --target build -t $(Build.BuildId) . docker create -ti --name testcontainer $(Build.BuildId) docker cp testcontainer:/TestResults ./TestResults docker rm -fv testcontainer - task: PublishTestResults@2 displayName: 'Publish test results' inputs: testResultsFormat: 'VSTest' testResultsFiles: '**/*.trx' searchFolder: '$(System.DefaultWorkingDirectory)/TestResults' failTaskOnFailedTests: true - task: DotNetCoreCLI@2 displayName: Install ReportGenerator tool inputs: command: 'custom' custom: 'tool' arguments: 'install dotnet-reportgenerator-globaltool --global' - task: CmdLine@2 displayName: Generate merged coverage report inputs: script: | reportgenerator \ "-reports:$(System.DefaultWorkingDirectory)/TestResults/**/coverage.cobertura.xml" \ "-targetdir:$(System.DefaultWorkingDirectory)/TestResults/coveragereport" \ "-reporttypes:Cobertura" \ "-classfilters:-Models.*;-Constants.*;-Configurtation.*;-Program.cs;-SpmContext.cs" \ "-replacePaths:/src=$(Build.SourcesDirectory)" \ "-verbosity:Verbose" - task: PublishCodeCoverageResults@1 displayName: 'Publish code coverage results' inputs: codeCoverageTool: Cobertura summaryFileLocation: '$(System.DefaultWorkingDirectory)/TestResults/coveragereport/*.xml'
关键说明
DotNetCoreCLI@2任务通过dotnet tool全局安装ReportGenerator,无需Azure DevOps插件。reportgenerator命令中的-replacePaths:/src=$(Build.SourcesDirectory)参数,将容器内的/src/路径替换为代理主机上的实际源码路径,确保Azure DevOps能正确定位到源文件。- 如果你的Docker容器内源码路径不是
/src/,请将-replacePaths中的/src替换为容器内实际的源码根路径。
内容的提问来源于stack exchange,提问作者Vinit Divekar
相关产品推荐
相关产品推荐

