Skip to content

fix: very_good dart test --coverage fails in pub workspaces #1683

Description

@marcossevilla

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

  1. Create a pub workspace:
    # pubspec.yaml (root)
    name: workspace_root
    environment:
      sdk: ^3.9.0
    workspace:
      - packages/foo
  2. Create a member package packages/foo with resolution: workspace in its pubspec.yaml, and a trivial passing test.
  3. From the workspace root, run dart pub get.
  4. cd packages/foo
  5. Run very_good dart test --coverage
  6. 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:

  1. 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.
  2. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working as expected

    Type

    No type

    Projects

    Status
    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions