WK Integration Services Ltd

Seamless Solutions, Tailored Integration

YAML Pipeline with Code Coverage Conditional

YAML Pipeline with Code Coverage Conditional

 The YAML flow builds the solution of an Azure Function, that contains 3 projects. The unit tests are run and published, and settings are contained in the coverlet.runsettings.xml:

<?xml version=“1.0” encoding=“utf-8” ?>
<RunSettings>
  <DataCollectionRunSettings>
    <DataCollectors>
      <DataCollector friendlyName=“XPlat code coverage”>
        <Configuration>
          <ExcludeByFile/>
        </Configuration>
      </DataCollector>
    </DataCollectors>
  </DataCollectionRunSettings>
</RunSettings>

Output:

Then published:

The coverage reports then need to be merged so that overall coverage rates can be extracted, I use “reportgenerator”. The merged report is also published.

Using “xmlstarlet” I extract the line coverage value from the merged report:

coverage=$(xmlstarlet sel-t-v ‘number(//coverage[1]/@line-rate)*100’ ${cobertura_file})

The value retrieved can be used on a conditional statement:

condition: and(succeeded(), ne(variables[‘Agent.JobStatus’], ‘SucceededWithIssues’), gt(variables[‘GetLineCoverage.coverage_Line’],
variables[‘coverage_Threshold’]))

In the condition above I use the populated job variables for the line coverage threshold and the line coverage from the unit tests that are run.

Here is the full demo yaml:

trigger:
    none
stages:
stage: Test_Code_Coverage
  jobs:
  – job: BuildJob

    pool:
      vmImage: ubuntu-latest

    variables:
      coverage_Threshold: 56.48 # static
      coverage_Line: 0.00 # default

    steps:
    – task: UseDotNet@2
      inputs:
        packageType: ‘sdk’
        installationPath: $(Agent.ToolsDirectory)/dotnet
        installationScript: ‘install’
        version: ‘7.x’
      displayName: ‘Setup .NET’

    – script: |
        # Restore NuGet Packages
        dotnet restore
      displayName: ‘Restore NuGet Packages’

    – script: |
        # Build the solution
        dotnet build –configuration ‘Release’ –no-restore
      displayName: ‘Build Solution’

    – task: DotNetCoreCLI@2
      displayName: ‘Run Unit Tests – Release’
      inputs:
        command: ‘test’
        arguments: ‘–no-build –configuration “Release” –logger trx –results-directory “$(Build.SourcesDirectory)/TestResults/Coverage/”  –settings coverlet.runsettings.xml’
        publishTestResults: false

    – task: PublishTestResults@2
      displayName: ‘Publish Test Results’
      inputs:
        testResultsFormat: VSTest
        testResultsFiles: ‘**/*.trx’
        searchFolder: ‘$(Build.SourcesDirectory)/TestResults/Coverage/’

    – task: DotNetCoreCLI@2
      displayName: ‘dotnet Tool Install “reportgenerator”‘
      inputs:
        command: custom
        custom: tool
        arguments: ‘install -g dotnet-reportgenerator-globaltool’

    – script: |
        reportgenerator -reports:$(Build.SourcesDirectory)/**/*cobertura.xml -targetdir:$(Build.SourcesDirectory)/MergedCodeCoverage -reporttypes:’HtmlInline_AzurePipelines;Cobertura’
      displayName: ‘Merge Code Coverage Reports’
      workingDirectory: $(Build.SourcesDirectory)
    – task: PublishCodeCoverageResults@1
      displayName: ‘Publish Merged Code Coverage Report’
      inputs:
        codeCoverageTool: ‘cobertura’
        summaryFileLocation: ‘$(Build.SourcesDirectory)/MergedCodeCoverage/Cobertura.xml’
        reportDirectory: ‘$(Build.SourcesDirectory)/CodeCoverage’

    – script: |
        sudo apt-get update
        sudo apt-get install -y xmlstarlet
      displayName: ‘Install xmlstarlet’

    – script: |
        # Find the Cobertura XML file and store its path in a variable
        cobertura_file=$(find $(Build.SourcesDirectory)/MergedCodeCoverage/ -name ‘Cobertura.xml’ | head -n 1)
        ###echo “DEBUG:Report path: ${cobertura_file}”
        echo “##vso[task.setvariable variable=coverage_Line]$coverage_Line”
        # Check if the file exists before attempting to parse
        if [ -f “${cobertura_file}” ]; then
          # Extract line coverage percentage from Cobertura XML
          coverage=$(xmlstarlet sel -t -v ‘number(//coverage[1]/@line-rate)*100’ ${cobertura_file})
          echo “##vso[task.setvariable variable=coverage_Line;isOutput=true]$coverage” #create a new line line coverage from xml
          # Print the line coverage percentage
          echo “Line coverage percentage: $coverage%”
        else
          echo “Cobertura XML file not found.”
        fi
      name: GetLineCoverage
      displayName: ‘Print Line Coverage’

    – script: |
        echo “Agent job status: $(Agent.JobStatus)”
        echo “Code coverage percentage: $(GetLineCoverage.coverage_Line)% and threshold is: $COVERAGE_THRESHOLD%”
      displayName: ‘Condition Checks’

    – script: |
        # Over code coverage pass rate?%
        echo “Code coverage is above $COVERAGE_THRESHOLD% ($(GetLineCoverage.coverage_Line)%). The build succeeded.”
      displayName: ‘Check Code Coverage Percentage’
      condition: and(succeeded(), ne(variables[‘Agent.JobStatus’], ‘SucceededWithIssues’), gt(variables[‘GetLineCoverage.coverage_Line’], variables[‘coverage_Threshold’]))  # Only run if previous tasks succeeded

Leave a Reply

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