Azure Reporting Code Coverage for .NET Core and JavaScript

I could not find a relevant article for combined code coverage reporting of a project with both .NET Core tests and Javascript tests, so having spent far too much time working it out I have documented the steps necessary here to save you the same pain.

My projects are using XUnit to test my .NET Core code and npm with Jest to test my Javascript code.

In your package.json file you will need to include jest and jest-junit as dev dependencies setup the Jest testing to output results in Cobertura format, e.g.

"test": "jest --ci --coverage --reporters=jest-junit --reporters=default --coverageReporters=html --coverageReporters=cobertura",

In the Azure pipeline you will need to be running “test” as a custom npm command after npm has been installed, publish the Javascript tests so they are included in the test tab, create a code coverage report using the 3rd party tool “Report Generator”, and publish the code coverage results in a new tab.

Here is an example of what a simple Azure pipeline yml might look like. Items of special note are the exclusion of Views and Tests when the .NET Core testing is undertaken (I don’t want the 0% coverage of those items contaminating my overall results), and the combining of the Javasctipt cobertura-coverage.xml and .NET Core coverage.cobertura.xml files in the Report Generator step.

steps:
- task: DotNetCoreCLI@2
  displayName: Restore
  inputs:
    command: restore
    projects: '$(Parameters.RestoreBuildProjects)'

steps:
- task: Npm@1
  displayName: 'npm install'
  inputs:
    workingDir: TestProject
    verbose: false

steps:
- task: Npm@1
  displayName: 'npm test'
  inputs:
    command: custom
    workingDir: TestProject
    verbose: false
    customCommand: test

steps:
- task: PublishTestResults@2
  displayName: 'Publish JS Test Results'
  inputs:
    testResultsFiles: junit.xml
    searchFolder: TestProject
    mergeTestResults: true

steps:
- task: DotNetCoreCLI@2
  displayName: Build
  inputs:
    projects: '$(Parameters.RestoreBuildProjects)'
    arguments: '--configuration $(BuildConfiguration)'

steps:
- task: DotNetCoreCLI@2
  displayName: 'Test dotnet'
  inputs:
    command: test
    projects: '$(Parameters.TestProjects)'
    arguments: '--configuration $(BuildConfiguration) /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:Exclude=[TestProject.Views]*%2c[TestProject.Tests]*'

steps:
- script: |
   dotnet tool install -g dotnet-reportgenerator-globaltool
   reportgenerator -reports:$(Build.SourcesDirectory)/**/*[Tt]ests/**/coverage.cobertura.xml;$(Build.SourcesDirectory)/**/coverage/cobertura-coverage.xml -targetDir:$(Build.SourcesDirectory)/CodeCoverage -reporttypes:HtmlInline_AzurePipelines;Cobertura
  displayName: 'Create Code Coverage Report'

steps:
- task: PublishCodeCoverageResults@1
  displayName: 'Publish code coverage'
  inputs:
    codeCoverageTool: Cobertura
    summaryFileLocation: '$(Build.SourcesDirectory)/CodeCoverage/Cobertura.xml'
    reportDirectory: '$(Build.SourcesDirectory)/CodeCoverage'

steps:
- task: DotNetCoreCLI@2
  displayName: Publish
  inputs:
    command: publish
    publishWebProjects: True
    arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)'

steps:
- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)'

Once you have the pipeline running you will end up with a new tab in the results named “Code Coverage”, here is an example test project output:

Underneath the summary are more detailed coverage results that you can drill into to see where you can improve.

Leave a Reply

Your email address will not be published. Required fields are marked *