Description
Running very_good dart test with coverage collection enabled (via --coverage, or implicitly via --min-coverage/--show-uncovered, or via the new 1.4.0 very_good.yaml dart.test.min_coverage config) crashes with a PathNotFoundException when run from inside a member package of a Dart pub workspace.
Pub workspaces resolve dependencies once at the workspace root, so .dart_tool/package_config.json is only generated at the root, not duplicated inside each member package's own .dart_tool/. The very_good dart test coverage step looks for that file relative to the current working directory instead of resolving it the way dart pub/dart test themselves do (walking up to the workspace root), so it fails whenever it's invoked from inside a member directory.
Steps To Reproduce
- Create a pub workspace:
# pubspec.yaml (root)
name: workspace_root
environment:
sdk: ^3.9.0
workspace:
- packages/foo
- Create a member package
packages/foo with resolution: workspace in its pubspec.yaml, and a trivial passing test.
- From the workspace root, run
dart pub get.
cd packages/foo
- Run
very_good dart test --coverage
- See error:
Running "dart test" in . ...
✓ Optimizing tests (90ms)
00:01 +60: All tests passed!
PathNotFoundException: Cannot open file, path = '.dart_tool/package_config.json' (OS Error: No such file or directory, errno = 2)
Exit code 69.
Expected Behavior
Tests run and a coverage report is produced, the same as running dart test --coverage directly (which works fine in this exact layout).
Additional Context
- Setting
dart.test.min_coverage in very_good.yaml implicitly turns on coverage collection (collectCoverage: options.collectCoverage || options.minCoverage != null || options.showUncovered), so a bare very_good dart test with no flags at all starts crashing the moment that config key is added, with no indication that pub workspaces are the cause.
very_good test (the Flutter-oriented command, which delegates to flutter test) does not hit this issue in the same workspace/directory — its coverage-collection path resolves the package config differently and more tolerantly of the workspace layout.
- Confirmed the workspace only materializes
package_config.json at the root (workspace_root/.dart_tool/package_config.json), never inside packages/foo/.dart_tool/, even after re-running dart pub get from inside the member directory.
Possible fix
lib/src/cli/test_cli_runner.dart, inside TestCLIRunner.test(), in the block that post-processes coverage for dart test:
if (testType == TestRunType.dart && collectCoverage) {
final files = _dartCoverageFilesToProcess(p.join(cwd, 'coverage'));
final packagesPath = p.join('.dart_tool', 'package_config.json');
final hitmap = await coverage.HitMap.parseFiles(
files,
packagePath: packagesPath,
checkIgnoredLines: checkIgnore,
);
final resolver = await coverage.Resolver.create(
packagesPath: packagesPath,
packagePath: packagesPath,
);
...
Every other path in this function joins against cwd (e.g. p.join(cwd, 'coverage', 'lcov.info') a few lines above). This one is a bare literal resolved relative to whatever directory the process happens to be in, which never resolves in a pub workspace since .dart_tool/package_config.json only exists at the workspace root.
Two ways to fix it, in order of correctness:
- Join against
cwd: p.join(cwd, '.dart_tool', 'package_config.json'). Fixes non-workspace recursive runs against nested directories, but still doesn't fix workspaces.
- Walk up from
cwd looking for .dart_tool/package_config.json, the same way VeryGoodConfig.load() already walks up looking for very_good.yaml in lib/src/very_good_config/very_good_config.dart. That walk-up logic could be extracted and reused here.
Environment
- very_good_cli: 1.4.0
- Dart SDK: 3.12.2 (stable)
- Flutter: 3.44.2
- OS: macOS 15 (Darwin 25.5.0), arm64
Description
Running
very_good dart testwith coverage collection enabled (via--coverage, or implicitly via--min-coverage/--show-uncovered, or via the new 1.4.0very_good.yamldart.test.min_coverageconfig) crashes with aPathNotFoundExceptionwhen run from inside a member package of a Dart pub workspace.Pub workspaces resolve dependencies once at the workspace root, so
.dart_tool/package_config.jsonis only generated at the root, not duplicated inside each member package's own.dart_tool/. Thevery_good dart testcoverage step looks for that file relative to the current working directory instead of resolving it the waydart pub/dart testthemselves do (walking up to the workspace root), so it fails whenever it's invoked from inside a member directory.Steps To Reproduce
packages/foowithresolution: workspacein itspubspec.yaml, and a trivial passing test.dart pub get.cd packages/foovery_good dart test --coverageExpected Behavior
Tests run and a coverage report is produced, the same as running
dart test --coveragedirectly (which works fine in this exact layout).Additional Context
dart.test.min_coverageinvery_good.yamlimplicitly turns on coverage collection (collectCoverage: options.collectCoverage || options.minCoverage != null || options.showUncovered), so a barevery_good dart testwith no flags at all starts crashing the moment that config key is added, with no indication that pub workspaces are the cause.very_good test(the Flutter-oriented command, which delegates toflutter test) does not hit this issue in the same workspace/directory — its coverage-collection path resolves the package config differently and more tolerantly of the workspace layout.package_config.jsonat the root (workspace_root/.dart_tool/package_config.json), never insidepackages/foo/.dart_tool/, even after re-runningdart pub getfrom inside the member directory.Possible fix
lib/src/cli/test_cli_runner.dart, insideTestCLIRunner.test(), in the block that post-processes coverage fordart test:Every other path in this function joins against
cwd(e.g.p.join(cwd, 'coverage', 'lcov.info')a few lines above). This one is a bare literal resolved relative to whatever directory the process happens to be in, which never resolves in a pub workspace since.dart_tool/package_config.jsononly exists at the workspace root.Two ways to fix it, in order of correctness:
cwd:p.join(cwd, '.dart_tool', 'package_config.json'). Fixes non-workspace recursive runs against nested directories, but still doesn't fix workspaces.cwdlooking for.dart_tool/package_config.json, the same wayVeryGoodConfig.load()already walks up looking forvery_good.yamlinlib/src/very_good_config/very_good_config.dart. That walk-up logic could be extracted and reused here.Environment