๐Ÿ“Š Day 13: Code Coverage - Hands-On Lab Guide

Practical exercises for measuring test coverage (Windows Edition)

Duration: 4 hours | Module: Testing & Artifacts

๐Ÿ’ป Windows Environment: All commands optimized for Windows PowerShell/Command Prompt.
โš ๏ธ Prerequisites Check:
  1. Day 12 complete (projects with tests created)
  2. Java JDK 11+ and Maven installed
  3. .NET SDK 6.0+ installed
  4. Tests passing from Day 12
  5. Azure DevOps pipeline configured

Lab 1: Add JaCoCo to Maven Project โ˜•

Objective: Configure JaCoCo for Java code coverage
Time: 25 minutes

Exercise 1.1: Configure JaCoCo Plugin

1 Open Your Maven Project
# Navigate to calculator project from Day 12 cd $env:USERPROFILE\Desktop\testing-demo\calculator
2 Update pom.xml with JaCoCo
notepad pom.xml

Add JaCoCo plugin to the <build><plugins> section:

<build> <plugins> <!-- Existing surefire plugin --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0</version> </plugin> <!-- JaCoCo Coverage Plugin --> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.11</version> <executions> <execution> <id>prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>report</id> <phase>test</phase> <goals> <goal>report</goal> </goals> </execution> <execution> <id>check</id> <goals> <goal>check</goal> </goals> <configuration> <rules> <rule> <element>BUNDLE</element> <limits> <limit> <counter>LINE</counter> <value>COVEREDRATIO</value> <minimum>0.70</minimum> </limit> </limits> </rule> </rules> </configuration> </execution> </executions> </plugin> </plugins> </build>

Save and close (Ctrl+S, Alt+F4)

3 Understanding JaCoCo Configuration
Three Executions:
  • prepare-agent - Sets up coverage monitoring
  • report - Generates coverage report after tests
  • check - Enforces minimum coverage (70% in this example)
4 Run Tests with Coverage
# Run tests with coverage generation mvn clean test [INFO] --- jacoco:0.8.11:prepare-agent (prepare-agent) @ calculator --- [INFO] --- maven-surefire-plugin:3.0.0:test (default-test) @ calculator --- [INFO] Tests run: 8, Failures: 0, Errors: 0, Skipped: 0 [INFO] --- jacoco:0.8.11:report (report) @ calculator --- [INFO] Loading execution data file: target\jacoco.exec [INFO] Analyzed bundle 'calculator' with 1 classes [INFO] BUILD SUCCESS
5 View Coverage Report
# Open HTML coverage report in browser start target\site\jacoco\index.html

You'll see:

  • Overall coverage percentage
  • Coverage per package
  • Coverage per class
  • Green (covered) and red (uncovered) lines
โœ… Checkpoint: JaCoCo configured and coverage report generated

Lab 2: Add Coverlet to .NET Project ๐Ÿ”ท

Objective: Configure Coverlet for .NET code coverage
Time: 20 minutes

Exercise 2.1: Install Coverlet

1 Navigate to .NET Project
# Navigate to .NET solution from Day 12 cd $env:USERPROFILE\Desktop\testing-demo\CalculatorApp
2 Add Coverlet Package
# Add coverlet.collector to test project dotnet add Calculator.Tests package coverlet.collector info : PackageReference for package 'coverlet.collector' version '6.0.0' added info : Committing restore... # Alternative: Add coverlet.msbuild for more options dotnet add Calculator.Tests package coverlet.msbuild
3 Run Tests with Coverage
# Collect coverage using XPlat Code Coverage dotnet test --collect:"XPlat Code Coverage" Passed! - Failed: 0, Passed: 10, Skipped: 0, Total: 10, Duration: 52 ms Attachments: C:\...\TestResults\abc-123\coverage.cobertura.xml
4 Generate HTML Report (Optional)
# Install ReportGenerator global tool dotnet tool install -g dotnet-reportgenerator-globaltool # Generate HTML report from coverage data reportgenerator ` -reports:"Calculator.Tests\TestResults\**\coverage.cobertura.xml" ` -targetdir:"coveragereport" ` -reporttypes:Html # Open report start coveragereport\index.html
5 View Coverage Details

In the HTML report, you'll see:

  • Summary: Overall coverage percentage
  • Assembly: Coverage per project
  • Classes: Coverage per class
  • Line-by-line: Green (covered) vs Red (uncovered)
โœ… Checkpoint: Coverlet configured and coverage report generated

Lab 3: Improve Code Coverage ๐Ÿ“ˆ

Objective: Identify and test uncovered code
Time: 35 minutes

Exercise 3.1: Add Untested Method

1 Add New Method to Calculator (Java)
notepad src\main\java\com\example\Calculator.java

Add this method (no test yet):

public int modulo(int a, int b) { if (b == 0) { throw new IllegalArgumentException("Cannot modulo by zero"); } return a % b; }

Save and close

2 Run Coverage Without Test
mvn clean test start target\site\jacoco\index.html

Observation: Coverage will be lower because modulo() method is not tested!

3 Add Test for New Method
notepad src\test\java\com\example\CalculatorTest.java

Add these tests:

@Test @DisplayName("Test modulo operation") void testModulo() { assertEquals(1, calculator.modulo(7, 3)); assertEquals(0, calculator.modulo(6, 3)); assertEquals(2, calculator.modulo(8, 3)); } @Test @DisplayName("Test modulo by zero throws exception") void testModulo_ByZero_ThrowsException() { Exception exception = assertThrows( IllegalArgumentException.class, () -> calculator.modulo(5, 0) ); assertEquals("Cannot modulo by zero", exception.getMessage()); }

Save and close

4 Run Coverage Again
mvn clean test start target\site\jacoco\index.html

Observation: Coverage increases! modulo() method now shows green (covered)

5 Analyze Coverage Report

In the HTML report:

  • Click on package name โ†’ Click on Calculator class
  • See line-by-line coverage
  • Green background: Line was executed by tests โœ…
  • Red background: Line never executed โŒ
  • Yellow background: Partial branch coverage โš ๏ธ
โœ… Checkpoint: Understand how to improve coverage by adding tests

Lab 4: Add Coverage to Azure Pipeline (Maven) ๐Ÿ”—

Objective: Publish coverage reports to Azure DevOps
Time: 35 minutes

Exercise 4.1: Update Pipeline YAML

1 Open Pipeline File
notepad azure-pipelines.yml
2 Add Coverage Publishing

Replace content with complete pipeline:

# Maven Test + Coverage Pipeline trigger: - main pool: vmImage: 'windows-latest' steps: # Run tests with JaCoCo - task: Maven@3 displayName: 'Run Tests with Coverage' inputs: mavenPomFile: 'pom.xml' goals: 'clean test' publishJUnitResults: true testResultsFiles: '**/surefire-reports/TEST-*.xml' javaHomeOption: 'JDKVersion' jdkVersionOption: '1.11' # Publish coverage results - task: PublishCodeCoverageResults@2 displayName: 'Publish Code Coverage' inputs: summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/jacoco.xml' pathToSources: '$(System.DefaultWorkingDirectory)/src/main/java' codecoverageTool: 'JaCoCo' failIfCoverageEmpty: true

Save and close

3 Commit and Push
git add . git commit -m "Add JaCoCo coverage to pipeline" git push
4 Monitor Pipeline Execution
  • Go to Azure DevOps โ†’ Pipelines
  • Watch pipeline run
  • See "Publish Code Coverage" task execute
  • Pipeline completes successfully
5 View Coverage in Azure DevOps
  • In pipeline run, click "Code Coverage" tab
  • See coverage summary (e.g., 85.7%)
  • View coverage per file
  • Click files to see line-by-line coverage
  • Green = Covered, Red = Not covered
โœ… Checkpoint: Coverage reports visible in Azure DevOps

Lab 5: Add Coverage to .NET Pipeline ๐Ÿ”ท

Objective: Publish .NET coverage to Azure DevOps
Time: 30 minutes

Exercise 5.1: Update .NET Pipeline

1 Open Pipeline File
cd $env:USERPROFILE\Desktop\testing-demo\CalculatorApp notepad azure-pipelines.yml
2 Complete .NET Coverage Pipeline
# .NET Test + Coverage Pipeline trigger: - main pool: vmImage: 'windows-latest' steps: # Restore packages - task: DotNetCoreCLI@2 displayName: 'Restore NuGet Packages' inputs: command: 'restore' # Build - task: DotNetCoreCLI@2 displayName: 'Build Solution' inputs: command: 'build' arguments: '--configuration Release' # Run tests with coverage - task: DotNetCoreCLI@2 displayName: 'Run Tests with Coverage' inputs: command: 'test' projects: '**/*Tests.csproj' arguments: '--configuration Release --collect:"XPlat Code Coverage"' publishTestResults: true # Publish coverage results - task: PublishCodeCoverageResults@2 displayName: 'Publish Code Coverage' inputs: summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml' codecoverageTool: 'Cobertura' failIfCoverageEmpty: true

Save and close

3 Commit and Push
git add . git commit -m "Add coverage to .NET pipeline" git push
4 View .NET Coverage in Azure DevOps
  • Pipeline runs automatically
  • Click "Code Coverage" tab
  • See .NET project coverage
  • Drill down into assemblies and classes
โœ… Checkpoint: .NET coverage integrated in pipeline

Lab 6: Enforce Coverage Thresholds ๐Ÿšฆ

Objective: Fail builds when coverage drops below threshold
Time: 25 minutes

Exercise 6.1: Set Minimum Coverage (Maven)

1 Already Configured!

In Lab 1, we added the check execution with minimum 70%:

<limit> <counter>LINE</counter> <value>COVEREDRATIO</value> <minimum>0.70</minimum> </limit>
2 Test Coverage Enforcement

Option A: Delete some tests to lower coverage

notepad src\test\java\com\example\CalculatorTest.java

Comment out 2-3 tests to reduce coverage below 70%

Run Maven:

mvn clean test [ERROR] Coverage check failed: Rule violated for bundle calculator: lines covered ratio is 0.65, but expected minimum is 0.70 [INFO] BUILD FAILURE
3 Fix Coverage

Uncomment the tests or add more tests, then run again:

mvn clean test [INFO] BUILD SUCCESS

Exercise 6.2: Coverage Threshold in Pipeline (Alternative)

1 Add BuildQualityChecks Task

Add after PublishCodeCoverageResults:

# Check coverage threshold - task: BuildQualityChecks@8 displayName: 'Check Coverage Threshold' inputs: checkCoverage: true coverageFailOption: 'build' coverageType: 'lines' coverageThreshold: '80'
๐Ÿ’ก Note: BuildQualityChecks is from marketplace extension. JaCoCo's built-in check is simpler and recommended.
โœ… Checkpoint: Coverage thresholds enforce quality standards

Lab 7: Track Coverage Trends ๐Ÿ“ˆ

Objective: Monitor coverage improvements over time
Time: 20 minutes

Exercise 7.1: View Coverage History

1 Access Analytics
  • Go to Azure DevOps โ†’ Pipelines
  • Select your pipeline
  • Click "Analytics" tab
2 View Coverage Trends

You can see:

  • Coverage percentage over time (line graph)
  • Increases and decreases highlighted
  • Compare coverage across builds
  • Identify when coverage dropped
3 Compare Build Coverage
  • Click on different pipeline runs
  • Compare Code Coverage tab
  • See which files improved/degraded

Exercise 7.2: Gradual Coverage Improvement

1 Strategy for Legacy Code
Don't aim for 80% immediately!

Gradual approach:

  1. Week 1: Measure current coverage (e.g., 40%)
  2. Week 2: Set goal at 45%, write tests
  3. Week 4: Increase to 50%
  4. Week 8: Reach 60%
  5. Week 16: Target 80%
โœ… Checkpoint: Understand coverage trends and improvement strategies

๐ŸŽฏ Lab Summary

What You've Accomplished:

  • โœ… Configured JaCoCo for Java projects
  • โœ… Configured Coverlet for .NET projects
  • โœ… Generated coverage reports locally
  • โœ… Published coverage to Azure DevOps
  • โœ… Set coverage thresholds
  • โœ… Viewed coverage trends
  • โœ… Improved coverage by adding tests

Key Concepts Mastered:

  1. Code Coverage: Percentage of code tested
  2. JaCoCo: Java coverage tool with Maven integration
  3. Coverlet: .NET coverage tool
  4. Coverage Reports: HTML, XML formats
  5. Thresholds: Minimum coverage enforcement
  6. Trends: Tracking coverage over time

Next Steps:

  • ๐Ÿ“š Day 14: Advanced test reporting and artifacts
  • ๐ŸŽฏ Aim to increase coverage to 80%+
  • ๐Ÿ“Š Review coverage reports weekly
  • ๐Ÿงช Add tests for uncovered critical code
  • ๐Ÿ“ˆ Track coverage in team dashboards

๐Ÿ”ง Troubleshooting Guide

Issue Solution
No jacoco.xml generated Verify JaCoCo plugin in pom.xml
Check target/site/jacoco/ directory exists
Run: mvn clean test
Coverage shows 0% Ensure tests actually ran and passed
Check jacoco.exec file exists in target/
Verify source path is correct
Coverage not in Azure DevOps Verify PublishCodeCoverageResults task added
Check summaryFileLocation path is correct
Ensure codecoverageTool matches (JaCoCo or Cobertura)
.NET coverage file not found Check coverlet.collector package installed
Use: --collect:"XPlat Code Coverage"
Look in: TestResults/**/coverage.cobertura.xml
Build fails on coverage check Coverage below minimum threshold
Add more tests or lower threshold temporarily
Review uncovered code in report

๐Ÿ“ Quick Reference Commands

Maven / JaCoCo:

# Run tests with coverage mvn clean test # View coverage report start target\site\jacoco\index.html # Check coverage threshold mvn clean verify # Fails if below minimum

.NET / Coverlet:

# Run tests with coverage dotnet test --collect:"XPlat Code Coverage" # Generate HTML report reportgenerator ` -reports:"**/coverage.cobertura.xml" ` -targetdir:"coveragereport" ` -reporttypes:Html # View report start coveragereport\index.html

Coverage Files:

# Maven/JaCoCo target\site\jacoco\index.html # HTML report target\site\jacoco\jacoco.xml # XML for tools target\jacoco.exec # Raw execution data # .NET/Coverlet TestResults\{guid}\coverage.cobertura.xml # Coverage data coveragereport\index.html # HTML (if using reportgenerator)

๐ŸŽ‰ Day 13 Labs Complete!

You've successfully implemented code coverage tracking!

Ready for Day 14: Advanced Test Reporting & Artifacts

๐ŸŽ“ Skills Acquired:
  • JaCoCo configuration and usage
  • Coverlet configuration for .NET
  • Coverage report generation
  • Coverage publishing to Azure DevOps
  • Setting and enforcing thresholds
  • Coverage trend analysis