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.