I have created a React app and setup a fully working pipeline in Azure DevOps using Docker to build, test and publish my application.
Snippet from my pipeline yaml file:
#----------------------------------------------------------------------
# Build the docker image
#----------------------------------------------------------------------
- task: Docker@2
inputs:
containerRegistry: 'XXXcontainerrepo'
repository: 'XXX'
command: 'build'
Dockerfile: '**/production.Dockerfile'
tags: |
$(Build.BuildNumber)
arguments: '--build-arg buildNumber="$(Build.BuildNumber)"'
displayName: 'Docker build'
#----------------------------------------------------------------------
# Export and publish test results
#----------------------------------------------------------------------
- script: |
export id=$(docker images --filter "label=test=$(Build.BuildNumber)" -q | head -1)
echo "Container ID: ${id}"
docker create --name testcontainer $id
docker cp testcontainer:/app/coverage ./coverage
docker cp testcontainer:/app/junit.xml ./junit.xml
docker rm testcontainer
displayName: 'Copy test results and code coverage reports'
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: 'cobertura'
summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage/cobertura-coverage.xml'
displayName: 'Publish code coverage reports'
- task: PublishTestResults@2
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '**/junit.xml'
mergeTestResults: true
failTaskOnFailedTests: true
testRunTitle: 'Jest Unit Tests'
displayName: 'Publish test results'
Snippet from the Docker file:
# run tests
LABEL test=$buildNumber
RUN npm run test -- --reporters=default --reporters=jest-junit --coverage --watchAll=false
When all the test cases pass a test report is generated which I then copy out from my Docker container and publish using a task in the Azure pipeline.
But when a test fails I get an error in the Docker container and my build fails without any report being created. Of course I can see the failing test in the pipeline build log, but I don't get the report available in Azure DevOps since it is never created and thus not available to publish.
When I run the same command locally I get a test report created in both cases, when all test pass or when one or more fail.
So my question is, is it possible to create the report even if one or more test fail using Docker? As I understand the number of failing tests is the exit code, and when the exit code != 0 the Docker container fails.
I would still like the Docker build step to fail after the report has been created, but in case that is not possible I have set a flag in the test result publish task to fail the build if one or more test fail.
failTaskOnFailedTests: true
Update
When adding the continueOnError: true
flag to the Docker build step the build continues to the next step, but the problem still exists. It seems like the test run is halted before it can create the test and coverage reports, probably due to the non zero exit code it produces that makes the Docker step exit.
In the copy test results step I then get this output:
Error: No such container:path: testcontainer:/app/coverage
Error: No such container:path: testcontainer:/app/junit.xml
Which tells me the test run didn't create a report due to the non zero exit code which stopped the Docker build step to exit.
Solution
I ended up delaying the exit code so that the container with the test label finished and thus was available to the next step to extract the report files.
RUN npm run test -- --reporters=default --reporters=jest-junit --coverage --
watchAll=false; \
echo $? > /npm.exitcode;
# if the npm command failed - fail the build here so that we can get the
test-report files regardless of exit code
RUN exit $(cat /npm.exitcode)
I also added the condition: succeededOrFailed()
to the copy test results step and the publish code coverage step so that they always run, even if the build step "fails".
You may try the workaround in the following links:
https://github.com/MicrosoftDocs/azure-devops-docs/issues/2183 https://github.com/microsoft/vstest/issues/1848
Try adding "exit 0" to the end of this line as this: RUN dotnet test MyProject.Tests.csproj -c Release --logger "trx;LogFileName=testresults.trx"; exit 0