Skip to content

feat(test): add --changed and --related flags to deno test#35199

Open
lunadogbot wants to merge 2 commits into
mainfrom
claude/cross-workspace-test-runner-research-wpxj36
Open

feat(test): add --changed and --related flags to deno test#35199
lunadogbot wants to merge 2 commits into
mainfrom
claude/cross-workspace-test-runner-research-wpxj36

Conversation

@lunadogbot

Copy link
Copy Markdown
Contributor

Closes #28182

Adds Vitest-style dependency-aware test selection to deno test as a one-shot
(non-watch)
run. The issue asked for a way to run only the tests affected by a
change once — watch mode already does dependency-aware reruns, but continuously,
which isn't the workflow the reporter wanted.

Flags

  • --changed[=<ref>] — run only test modules affected by files changed in
    git. With no value it uses the working tree (staged, unstaged and untracked);
    with a ref (--changed=main, --changed=HEAD~1) it additionally includes
    committed changes since the merge-base (<ref>...HEAD three-dot form),
    matching Vitest and Jest.
  • --related=<files> — run only test modules that depend on the given
    source files, without consulting git (Vitest's --related).
$ deno test --changed                  # tests affected by uncommitted changes
$ deno test --changed=origin/main      # tests affected since branching off main
$ deno test --related=src/util.ts      # tests that import src/util.ts

How it works

Both flags resolve a set of changed/related file paths and then filter the
collected test specifiers, reusing the module graph and the existing
has_graph_root_local_dependent_changed walk that watch mode already uses to
find dependents. Because Deno builds a single module graph spanning the whole
workspace, selection works across workspace members — a test in one member
that imports another member's changed source is selected automatically.

Design details, mostly following prior art (Vitest/Jest/Nx/Turborepo):

  • A module that is itself a changed/related file is always kept.
  • A changed .env file disables filtering (any test may read it), mirroring the
    existing watch-mode escape hatch.
  • Deleted files can't be resolved in the graph and are dropped (their former
    dependents fail typecheck anyway).
  • Both flags conflict with --watch (watch already does continuous
    dependency-aware reruns).
  • When nothing is affected the run exits 0 with a message instead of erroring,
    matching Vitest's behavior with --changed.

Changes

  • cli/args/flags.rs — flag definitions, parsing, TestFlags::{changed,related}
  • cli/tools/test/mod.rs — git change detection (changed_files_from_git),
    collect_changed_paths, filter_specifiers_by_changed, wired into run_tests
  • tests/specs/test/{related,changed} — spec tests (hermetic --related;
    git-based --changed)

Test plan

  • cargo build / cargo clippy (clean under -D clippy::all) / rustfmt
  • Unit parse tests for --changed, --related, and the --watch conflict
  • Manual end-to-end in real git repos: uncommitted --changed,
    --changed=<ref>, --related, clean-tree (no-affected message),
    cross-workspace (editing b/mod.ts ran a/a_test.ts + b/b_test.ts),
    and self-changed test file
  • --related spec output validated byte-for-byte against the built binary
  • CI green

Generated by Claude Code

claude added 2 commits June 13, 2026 15:15
Capture the actual ask, prior art (Vitest, Jest, Nx, Turborepo,
Bazel/Pants/Gradle), what already exists in the codebase (watch-mode
affected selection, has_graph_root_local_dependent_changed, workspace
graph), a recommended design, and edge cases.

Refs #28182
Add Vitest-style dependency-aware test selection to `deno test` as a
one-shot (non-watch) run:

- `--changed[=<ref>]`: run only test modules affected by files changed in
  git. With no value it uses the working tree (staged, unstaged and
  untracked); with a ref it also includes committed changes since the
  merge-base (`<ref>...HEAD`), matching Vitest/Jest.
- `--related=<files>`: run only test modules that depend on the given
  source files, without consulting git.

Both reuse the module graph and the existing
`has_graph_root_local_dependent_changed` walk that watch mode already uses
to find dependents, so selection works across workspace members (a test
in one member that imports another member's changed source is selected).
A changed `.env` file disables filtering (any test may read it), mirroring
watch mode. A module that is itself a changed/related file is always kept.

Both flags conflict with --watch (watch already does continuous
dependency-aware reruns). When nothing is affected the run exits 0 with a
message instead of erroring.

Closes #28182
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Run only tests affected by changes (git-based deno test --changed)

2 participants