Search code examples
dockerazure-devopsjestjscreate-react-app

How do I get a test report when my Jest unit tests fail in Docker?


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. enter image description here

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.

enter image description here enter image description here

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.

enter image description here

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".


Solution

  • 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