Blog Post

Azure Infrastructure Blog
3 MIN READ

Enforcing Angular Unit Test Coverage in Azure DevOps Pipelines: A Step-by-Step Guide

Sakshi_Gupta22's avatar
Aug 21, 2025

In the rush to ship features, unit tests often become an afterthought. This guide helps you build a scalable Azure DevOps pipeline that enforces Angular test coverage and publishes actionable reports.

🔄 Pipeline Overview

      The Pipeline consists of the following key stages:                                

  • Install Dependencies – Ensure Angular CLI and required npm packages are set up.
  • Run Angular Unit Tests – Execute ng test in CI mode with coverage enabled.
  • Generate Reports – Store results in JUnit and Cobertura formats.
  • Publish to ADO – Push test results and coverage report into the Azure DevOps UI.
  • Verify Coverage – Fail the pipeline if coverage < 70%.    

     This workflow ensures Angular code is continuously validated, with measurable quality checks at every build.

Step-by-Step Integration Guide

1️⃣ Install Angular Dependencies

- script: |
    npm cache clean --force
    npm set "//<your-org>.jfrog.io/:_authToken=$(npm-auth-token)"
    npm config set @your-org:registry https://<your-org>.jfrog.io/artifactory/api/npm/<your-repo>/
    npm install -g npm
    npm install -g @angular/cli
    npm install -g @angular-devkit/build-angular --force
    rm -rf node_modules package-lock.json
    npm install --force
  displayName: Install npm packages
  workingDirectory: '$(System.DefaultWorkingDirectory)/unittestintegartion'

 Why it matters: Ensures a clean environment and installs all required packages for Angular testing.

2️⃣ Run Angular Unit Tests with Coverage

- script: |
    CHROME_PATH=$(which google-chrome || which chromium-browser)
    if [ -z "$CHROME_PATH" ]; then
      echo "Error: Chrome or Chromium is not installed on your system."
      exit 1
    fi
    export CHROME_BIN="$CHROME_PATH"
    echo "Running Angular tests"
    npm run test:ci -- --code-coverage
  workingDirectory: '$(System.DefaultWorkingDirectory)/unittestintegration/src/ui'
  displayName: Run Angular tests for remote
  continueOnError: true

 Why it matters: Executes tests in CI mode using ChromeHeadless and generates coverage data.

3️⃣ Create Report Directories

- script: |
    mkdir -p reports/junit
    mkdir -p reports/coverage
  displayName: Create reports directories
  workingDirectory: '$(System.DefaultWorkingDirectory)/unittestintegration/src/ui'

 Why it matters: Prepares folders for storing JUnit and Cobertura reports.

4️⃣ Publish Test Results

- task: PublishTestResults@1
  displayName: 'Publish Test Results - Generate Test Report remote'
  inputs:
    testResultsFiles: '$(System.DefaultWorkingDirectory)/unittestintegration/src/ui/reports/junit/unit-test-results.xml'

 Why it matters: Makes test results visible in Azure DevOps UI.

5️⃣ Use .NET Core SDK

- task: UseDotNet@2
  displayName: 'Use .NET Core sdk 9.0.x'
  inputs:
    version: 9.0.x

 Why it matters: Required for publishing code coverage results.

6️⃣ Publish Code Coverage

- task: PublishCodeCoverageResults@2
  inputs:
    codeCoverageTool: 'Cobertura'
    summaryFileLocation: '$(System.DefaultWorkingDirectory)/unittestintegration/src/ui/coverage/code-coverage.xml'
    reportDirectory: '$(System.DefaultWorkingDirectory)/unittestintegration/src/ui/coverage'
  displayName: 'Publish UI Code Coverage Results-remote'

 Why it matters: Displays detailed coverage reports in Azure DevOps.

7️⃣ Enforce 70% Coverage Threshold

- script: |
    angular_coverage=$(grep -oP 'line-rate="(\d+\.\d+)"' $(System.DefaultWorkingDirectory)/unittestintegration/src/ui/coverage/code-coverage.xml | head -1 | grep -oP '\d+\.\d+')
    angular_coverage=$(echo "$angular_coverage * 100" | bc)
    if (( $(echo "$angular_coverage < 70" | bc -l) )); then
      echo "Angular test coverage is below 70%: $angular_coverage%"
      exit 1
    fi
    echo "Angular test coverage is above 70%: $angular_coverage%"
  displayName: Verify Angular test coverage-remote

 Why it matters: Automatically fails the pipeline if coverage drops below 70%.

8️⃣ Configure Karma for CI

coverageReporter: {
  dir: require('path').join(__dirname, 'coverage'),
  reporters: [
    { type: 'html' },
    { type: 'lcov' },
    { type: 'cobertura', file: 'code-coverage.xml' },
    { type: 'text-summary' }
  ]
},
junitReporter: {
  outputDir: 'reports/junit',
  outputFile: 'unit-test-results.xml',
  useBrowserName: false
}

 Why it matters: Enables Cobertura and JUnit reporting for CI pipelines.

9️⃣ Update package.json

"scripts": {
  "test:ci": "ng test --watch=false --browsers=ChromeHeadless --code-coverage"
},
"devDependencies": {
  "karma-coverage": "^2.0.3",
  "karma-junit-reporter": "^2.0.1",
  "chrome-launcher": "^0.14.0"
}

 Why it matters: Adds CI-friendly test command and required packages.

Takeaway

Unit tests aren’t just about coverage numbers — they’re about confidence in every merge. By enforcing Angular unit tests in your Azure DevOps pipeline with JUnit, Cobertura, and a 70% threshold, you build a quality gate that scales with your team.

Updated Aug 21, 2025
Version 1.0
No CommentsBe the first to comment