AZ-400: Designing and Implementing Microsoft DevOps Solutions

Design and Implement Pipeline Automation

Understanding Code Coverage

Ensuring that your application behaves as expected requires more than just writing code—it demands thorough testing. Code coverage quantifies how much of your codebase is exercised by automated tests, helping teams detect untested logic, reduce bugs, and maintain long-term software quality.

What Is Code Coverage?

Code coverage is a metric that shows the proportion of your source code executed during test runs. By highlighting untested regions, it helps you:

  • Identify missing tests
  • Prevent regressions
  • Increase confidence in deployments

Untested code can hide defects and increase maintenance costs. Integrating coverage analysis into your CI/CD pipeline reveals these gaps early, making your testing efforts more effective.

The image is an illustration related to "Code Coverage in Azure Pipelines," showing a person interacting with a large screen displaying code. A caption below states that it significantly enhances software reliability and maintainability.

Azure Pipelines automates coverage collection alongside build and test steps, ensuring your quality gates stay green without manual intervention.

Types of Code Coverage

Understanding different coverage metrics lets you choose the right level of testing rigor:

Coverage MetricDescription
Statement CoverageMeasures how many individual statements have been run.
Branch CoverageEnsures each decision point (e.g., if/else, switch) is covered.
Path CoverageValidates all possible execution routes through the code.

Tip

Branch and path coverage provide deeper insight into complex logic but can be more challenging to achieve.

The image describes three types of code coverage: statement coverage, branch coverage, and path coverage, each with a brief explanation. It includes a graphic of a code editor.

Integrating Coverage in Azure Pipelines

A robust CI/CD pipeline typically follows these steps:

  1. Run tests to execute your code paths
  2. Collect coverage metrics from test reports
  3. Publish results to your pipeline dashboard

Popular tools include Cobertura and JaCoCo for Java, plus Coverlet for .NET.

The image lists three tools required for code coverage: Cobertura, JaCoCo for Java, and Coverlet for .NET, each with their respective logos.

Below is a sample YAML configuration for a .NET application in Azure Pipelines:

trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

steps:
- script: echo "Setting up test environment..."
  displayName: 'Initialize'

- task: DotNetCoreCLI@2
  inputs:
    command: 'test'
    projects: '**/*Tests/*.csproj'
    arguments: '--configuration Release --collect "Code coverage"'
  displayName: 'Run Tests with Coverage'

- task: PublishCodeCoverageResults@1
  inputs:
    codeCoverageTool: 'Cobertura'
    summaryFileLocation: '$(Build.SourcesDirectory)/**/coverage.cobertura.xml'
    reportDirectory: '$(Build.SourcesDirectory)/**/coverageReport'
  displayName: 'Publish Coverage Report'

- script: echo "Pipeline tasks completed successfully."
  displayName: 'Finalize'

Azure Pipelines’ modular tasks let you extend this setup with additional analysis, security scans, or deployment stages.

Viewing and Analyzing Coverage Reports

Once the pipeline finishes:

  • Check the Summary tab for overall coverage percentages
  • Open the Code Coverage tab for detailed reports, including missed lines and risk areas
  • Download raw data for offline review or integration with other tools

The image is a flowchart titled "Analyzing Code Coverage Results," showing how coverage reports lead to three outcomes: percentage of code covered, number of missed lines, and potential areas of risk.

To create richer visualizations, use ReportGenerator, which transforms XML and other coverage data into HTML reports with charts and summaries.

The image shows a code coverage analysis with a circular chart indicating 78% coverage, alongside a logo for "ReportGenerator."

Best Practices

  • Prioritize meaningful tests over sheer coverage percentages.
  • Avoid brittle tests by focusing on stability and maintainability.
  • Use coverage thresholds strategically—don’t make 100% a hard requirement.
  • Review uncovered code during retrospectives to plan new tests.

Warning

Chasing 100% coverage can lead to overly complex or low-value tests. Focus on critical paths and high-risk modules instead.

The image outlines best practices for maximizing code coverage, emphasizing the importance of writing quality tests, maintaining balance, and avoiding the pursuit of 100% coverage at the expense of test quality.

References

Watch Video

Watch video content

Previous
Local Tests Unit Tests Integration Tests Load Tests