I have a .Net 6 application which has 3 Test Projects. I have Azure DevOps CI/CD pipeline which shows the code coverage report.
In a Dockerfile, I run tests for individual project and generate a code coverage report using ReportGenerator tool. Here is my DockerFile
# Install Report Generator Tool
RUN dotnet tool install dotnet-reportgenerator-globaltool --tool-path /tools
# 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
# Convert multiple cobertura reports into one and publish the result to the target directory.
RUN /tools/reportgenerator "-reports:/TestResults/**/coverage.cobertura.xml" \
"-targetdir:/TestResults/coveragereport" \
"-reporttypes:Cobertura" \
"-classfilters:-Models.*;-Constants.*;-Configurtation.*;-Program.cs;-SpmContext.cs" \
"-verbosity:Verbose"
In the azure pipeline, I first copy test report and the code coverage report stored in the container into the pipeline's host agent.
Then run the PublishCodeCoverageResults@1
task. Here is the azure pipeline.
- 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: PublishCodeCoverageResults@1
displayName: 'Publish code coverage results'
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: '$(System.DefaultWorkingDirectory)/TestResults/coveragereport/*.xml'
The issue I am facing is that, although it generates the following code coverage report,
if I dive into individual file, I see error as File '/src/PreAdviceGeneration.Application/MappingProfiles/DomainItemTopicMessageProfile.cs' does not exist (any more).
See the screenshot below
PS: Worth mentioning that I cannot install the ReportGenerator plugin in AzureDevops.
The build stage of my docker file had WORKDIR as /app
. As tests are run in app directory, the ReportGenerator sets source location starting with /app/....
. When the report is copied in Azure Host, and published, it tries to find the source code with the path /app/...
.
The source code in the Azure host agent lies at the location, $(System.DefaultWorkingDirectory)
which is /home/vsts/work/1/s
. Hence the published report cannot find the source file.
Hence to have the consistent path across docker image and Azure Host, I updated the WORKDIR of the build stage of Dockerfile to /home/vsts/work/1/s
and now I am able to see the report for individual files.
My Docker file now looks like:
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /home/vsts/work/1/s
COPY . .
.........