Skip to content

Test Coverage Pipeline

What you'll learn

  • Setting up per-package coverage thresholds
  • Generating and merging lcov reports across a monorepo
  • Configuring file and pattern exclusions
  • Integrating coverage checks into CI with pass/fail gates

Prerequisites

  • An existing Archipelago monorepo (see Monorepo Scaffolding)
  • The coverage command generated in your monorepo toolkit
  • lcov installed (brew install lcov on macOS)

Step 1: Generate the Coverage Command

bash
archipelago generate coverage

You will be prompted for:

  • appName — Your app name (e.g., MyApp)
  • defaultThreshold — Minimum coverage percentage (e.g., 80)

Step 2: Understand the Generated Structure

The brick adds the coverage command to your existing monorepo toolkit:

devtools/
└── lib/src/
    └── commands/
        └── coverage/
            ├── coverage_command.dart        # CLI entry point
            ├── lcov_parser.dart             # Parse lcov.info files
            ├── coverage_merger.dart          # Merge per-package reports
            └── threshold_checker.dart        # Enforce minimums

Step 3: Configure Coverage Thresholds

Create coverage_config.yaml in your monorepo root:

yaml
default_threshold: 80

package_thresholds:
  packages/core_network: 90
  packages/feature_auth: 85
  packages/core_common: 95

exclude_from_coverage:
  - "**/*.g.dart"
  - "**/*.freezed.dart"
  - "**/generated/**"
  - "**/*.config.dart"
  - "**/di/**"
  • default_threshold — Applied to packages without a specific override
  • package_thresholds — Per-package minimum coverage percentages
  • exclude_from_coverage — Glob patterns for files to exclude from reports

Step 4: Run Coverage Locally

Generate coverage reports for all packages or specific ones:

bash
# Run coverage for all packages
dart run devtools coverage

# Run coverage for a specific package
dart run devtools coverage --package packages/core_network

# Run coverage only for affected packages
dart run devtools coverage --affected --base main

Example output:

Coverage Report:
  packages/core_common      96.2%  (threshold: 95%) ✓
  packages/core_network     87.4%  (threshold: 90%) ✗ FAIL
  packages/feature_auth     88.1%  (threshold: 85%) ✓
  app                       72.3%  (threshold: 80%) ✗ FAIL

2 packages below threshold. Exit code: 1

Step 5: Merge lcov Reports

For a unified coverage report across the monorepo, merge individual lcov.info files:

bash
# Generate merged report
dart run devtools coverage --merge --output coverage/merged_lcov.info

# Generate HTML report from merged lcov
genhtml coverage/merged_lcov.info -o coverage/html

# Open the report
open coverage/html/index.html

Step 6: Integrate with CI

Add coverage checks to your PR validation workflow:

yaml
- name: Run tests with coverage
  run: dart run devtools coverage --affected --base origin/${{ github.base_ref }}

- name: Upload coverage report
  if: always()
  uses: actions/upload-artifact@v4
  with:
    name: coverage-report
    path: coverage/merged_lcov.info

- name: Comment coverage on PR
  if: github.event_name == 'pull_request'
  run: |
    report=$(dart run devtools coverage --affected --base origin/${{ github.base_ref }} --format markdown)
    gh pr comment ${{ github.event.number }} --body "$report"

Key Customization Points

CustomizationWhere to Change
Default coverage thresholdcoverage_config.yamldefault_threshold
Per-package thresholdscoverage_config.yamlpackage_thresholds
Excluded file patternscoverage_config.yamlexclude_from_coverage
Output format--format flag (text, json, markdown)
Merge reports--merge flag with --output path

Next Steps

Built by Banua Coder