$npx -y skills add flutter/agent-plugins --skill dart-collect-coverageCollect coverage using the coverage packge and create an LCOV report
| 1 | # Implementing Dart and Flutter Test Coverage |
| 2 | |
| 3 | ## Contents |
| 4 | - [Testing Fundamentals](#testing-fundamentals) |
| 5 | - [Coverage Directives](#coverage-directives) |
| 6 | - [Workflow: Configuring and Generating Coverage Reports](#workflow-configuring-and-generating-coverage-reports) |
| 7 | - [Workflow: Advanced Manual Coverage Collection](#workflow-advanced-manual-coverage-collection) |
| 8 | - [Examples](#examples) |
| 9 | |
| 10 | ## Testing Fundamentals |
| 11 | |
| 12 | Structure your test suites using the standard Dart testing paradigms. Use `package:test` for Dart projects and `flutter_test` for Flutter projects. |
| 13 | |
| 14 | - **Unit Tests:** Verify individual functions, methods, or classes. |
| 15 | - **Component/Widget Tests:** Verify component behavior, layout, and interaction using mock objects (`package:mockito`). |
| 16 | - **Integration Tests:** Verify entire app flows on simulated or real devices. |
| 17 | |
| 18 | ## Coverage Directives |
| 19 | |
| 20 | Exclude specific lines, blocks, or entire files from coverage metrics using inline comments. Pass the `--check-ignore` flag during formatting to enforce these directives. |
| 21 | |
| 22 | - Ignore a single line: `// coverage:ignore-line` |
| 23 | - Ignore a block of code: `// coverage:ignore-start` and `// coverage:ignore-end` |
| 24 | - Ignore an entire file: `// coverage:ignore-file` |
| 25 | |
| 26 | ## Workflow: Configuring and Generating Coverage Reports |
| 27 | |
| 28 | Follow this sequential workflow to add the coverage package, execute tests, and generate an LCOV report. |
| 29 | |
| 30 | **Task Progress Checklist:** |
| 31 | - [ ] 1. Add `coverage` as a `dev_dependency`. |
| 32 | - [ ] 2. Execute the automated coverage script. |
| 33 | - [ ] 3. Validate the LCOV output. |
| 34 | |
| 35 | ### 1. Add Dependencies |
| 36 | Add the `coverage` package as a `dev_dependency` to your project. Do not add it to standard dependencies. |
| 37 | |
| 38 | If working in a standard Dart project: |
| 39 | ```bash |
| 40 | dart pub add dev:coverage |
| 41 | ``` |
| 42 | |
| 43 | If working in a Flutter project: |
| 44 | ```bash |
| 45 | flutter pub add dev:coverage |
| 46 | ``` |
| 47 | |
| 48 | ### 2. Collect Coverage and Generate LCOV |
| 49 | Use the bundled `test_with_coverage` script. This script automatically runs all tests, collects the JSON coverage data from the Dart VM, and formats it into an LCOV report. |
| 50 | |
| 51 | ```bash |
| 52 | dart run coverage:test_with_coverage |
| 53 | ``` |
| 54 | *Note: If working within a Dart workspace (monorepo), specify the test directories explicitly (e.g., `dart run coverage:test_with_coverage -- pkgs/foo/test pkgs/bar/test`).* |
| 55 | |
| 56 | ### 3. Feedback Loop: Validate Output |
| 57 | **Run validator -> review errors -> fix:** |
| 58 | 1. Verify that the `coverage/` directory was created in the project root. |
| 59 | 2. Ensure `coverage/coverage.json` (raw data) and `coverage/lcov.info` (formatted report) exist. |
| 60 | 3. If coverage is missing for specific files, ensure they are imported and executed by your test files, or add `// coverage:ignore-file` if they are intentionally excluded. |
| 61 | |
| 62 | ## Workflow: Advanced Manual Coverage Collection |
| 63 | |
| 64 | If you require granular control over the VM service, isolate pausing, or need branch/function-level coverage, use the manual collection workflow. |
| 65 | |
| 66 | **Task Progress Checklist:** |
| 67 | - [ ] 1. Run tests with VM service enabled. |
| 68 | - [ ] 2. Collect raw JSON coverage. |
| 69 | - [ ] 3. Format JSON to LCOV. |
| 70 | |
| 71 | ### 1. Run Tests with VM Service |
| 72 | Execute tests while pausing isolates on exit and exposing the VM service on a specific port (e.g., 8181). |
| 73 | |
| 74 | ```bash |
| 75 | dart run --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=8181 test & |
| 76 | ``` |
| 77 | |
| 78 | ### 2. Collect Raw Coverage |
| 79 | Extract the coverage data from the running VM service and output it to a JSON file. |
| 80 | |
| 81 | ```bash |
| 82 | dart run coverage:collect_coverage --wait-paused --uri=http://127.0.0.1:8181/ -o coverage/coverage.json --resume-isolates |
| 83 | ``` |
| 84 | *Optional: Append `--function-coverage` and `--branch-coverage` to gather deeper metrics (requires Dart VM 2.17.0+).* |
| 85 | |
| 86 | ### 3. Format to LCOV |
| 87 | Convert the raw JSON data into the standard LCOV format. |
| 88 | |
| 89 | ```bash |
| 90 | dart run coverage:format_coverage --packages=.dart_tool/package_config.json --lcov -i coverage/coverage.json -o coverage/lcov.info --check-ignore |
| 91 | ``` |
| 92 | |
| 93 | ## Examples |
| 94 | |
| 95 | ### Example: `pubspec.yaml` Configuration |
| 96 | Ensure your `pubspec.yaml` reflects the `coverage` package strictly under `dev_dependencies`. |
| 97 | |
| 98 | ```yaml |
| 99 | name: my_dart_app |
| 100 | environment: |
| 101 | sdk: ^3.0.0 |
| 102 | |
| 103 | dependencies: |
| 104 | path: ^1.8.0 |
| 105 | |
| 106 | dev_dependencies: |
| 107 | test: ^1.24.0 |
| 108 | coverage: ^1.15.0 |
| 109 | ``` |
| 110 | |
| 111 | ### Example: Applying Ignore Directives |
| 112 | Use ignore directives to prevent generated code or untestable edge cases from lowering coverage scores. |
| 113 | |
| 114 | ```dart |
| 115 | // coverage:ignore-file |
| 116 | import 'package:meta/meta.dart'; |
| 117 | |
| 118 | class SystemConfig { |
| 119 | final String env; |
| 120 | |
| 121 | SystemConfig(this.env); |
| 122 | |
| 123 | // coverage:ignore-start |
| 124 | void legacyInit() { |
| 125 | print('Deprecated initialization'); |
| 126 | } |
| 127 | // coverage:ignore-end |
| 128 | |
| 129 | bool isProduction() { |
| 130 | if (env == 'prod') return true; |
| 131 | return false; // coverage:ignore-line |
| 132 | } |
| 133 | } |
| 134 | ``` |