Skip to content

test_runner: add experimental tag-based test filtering#63054

Open
atlowChemi wants to merge 2 commits intonodejs:mainfrom
atlowChemi:test_runner-tag-filter
Open

test_runner: add experimental tag-based test filtering#63054
atlowChemi wants to merge 2 commits intonodejs:mainfrom
atlowChemi:test_runner-tag-filter

Conversation

@atlowChemi
Copy link
Copy Markdown
Member

Summary

Adds an experimental tag-filter feature to node:test, mirroring the
boolean-expression filter shape that other test runners have established.

  • Authoring: a tags: string[] option on test() / it() / suite() /
    describe(). Tags inherit from suites to nested tests by union.
  • Filtering: --experimental-test-tag-filter='<expr>' CLI flag and
    testTagFilters: string | string[] option on run(). Repeatable;
    multiple expressions AND together. Composes by AND with
    --test-name-pattern, --test-skip-pattern, and .only.
  • Expression grammar: and/&&, or/||, not/!, parentheses,
    * wildcards. Standard precedence (not > and > or).
  • Reporter: tags: string[] field added to the six testId-keyed
    events. Built-in reporters ignore the field for v1; custom reporters
    can read it.
  • Context: t.tags accessor on TestContext exposes the test's
    flattened tag set as a frozen array.

Prior art

Tag filtering is well-trodden ground in the JS testing ecosystem. The
expression syntax here is closest to Vitest's, which itself follows the
boolean/wildcard pattern other tools converged on:

Vitest additionally lets a tag carry per-test config overrides such as
timeout or retry (with priority resolution between overlapping
tags). That's intentionally out of scope for this PR — landing it
would commit to a separate tags: [{ name, timeout, retry, priority }]
config surface that's orthogonal to filtering. It can be layered on
later without breaking the union-inheritance semantics this PR
establishes.

Add a `tags` option on `test()` / `it()` / `suite()` / `describe()` and
the `--experimental-test-tag-filter` CLI flag (plus the `testTagFilters`
option on `run()`) that accepts a Vitest-style boolean expression with
`and`/`&&`, `or`/`||`, `not`/`!`, parentheses, and `*` wildcards.

Tags inherit from suite to child tests by union. Filtering composes by
AND with name patterns, skip patterns, and `.only`. Untagged tests are
filtered out under any include expression; `not X` is true against an
untagged test. Tag matching is case-insensitive with lowercase canonical
storage.

Signed-off-by: atlowChemi <chemi@atlow.co.il>
@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/config
  • @nodejs/test_runner

@nodejs-github-bot nodejs-github-bot added lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels Apr 30, 2026
Signed-off-by: atlowChemi <chemi@atlow.co.il>
@atlowChemi atlowChemi added the test_runner Issues and PRs related to the test runner subsystem. label Apr 30, 2026
Comment thread doc/api/cli.md
declare tags via the `tags` option on `test()`, `it()`, `suite()`, or
`describe()`. Tags inherit from suites to nested tests by union.

The expression supports boolean operators (`and`/`&&`, `or`/`||`,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isnt there a better way then this tag filtering syntax?.
i.e accept in the run method a string[] or function(string) => boolean and in case you want some complex logic - use the run api without the node cli - That makes much more sense to me

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is more consistent to our name filter flag

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without the boolean syntax this feature mostly collapses into name-pattern...

The goal (I had in mind) of this feature is to introduce a easy (and common, see prior art) way to filter without the need for a programmatic API. Sure, you could already achieve complex filtering via run() API, but the goal here is to add a built-in logic for this.

Vitest, mocha-tags, and jest-runner-groups all expose such a boolean composition syntax.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 30, 2026

Codecov Report

❌ Patch coverage is 96.66161% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.67%. Comparing base (66054cc) to head (e4fca58).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
lib/internal/test_runner/runner.js 82.22% 8 Missing ⚠️
lib/internal/test_runner/tag_filter.js 98.81% 6 Missing ⚠️
lib/internal/test_runner/tests_stream.js 61.53% 5 Missing ⚠️
lib/internal/test_runner/test.js 94.54% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #63054      +/-   ##
==========================================
- Coverage   91.48%   89.67%   -1.82%     
==========================================
  Files         358      709     +351     
  Lines      151591   221054   +69463     
  Branches    23925    42419   +18494     
==========================================
+ Hits       138690   198225   +59535     
- Misses      12625    14678    +2053     
- Partials      276     8151    +7875     
Files with missing lines Coverage Δ
lib/internal/test_runner/harness.js 86.42% <100.00%> (+0.27%) ⬆️
lib/internal/test_runner/utils.js 65.19% <100.00%> (+1.60%) ⬆️
src/node_options.cc 76.63% <100.00%> (ø)
src/node_options.h 97.98% <ø> (ø)
lib/internal/test_runner/test.js 96.82% <94.54%> (-0.03%) ⬇️
lib/internal/test_runner/tests_stream.js 86.08% <61.53%> (-2.16%) ⬇️
lib/internal/test_runner/tag_filter.js 98.81% <98.81%> (ø)
lib/internal/test_runner/runner.js 93.19% <82.22%> (-0.19%) ⬇️

... and 469 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JakobJingleheimer
Copy link
Copy Markdown
Member

Sweet! I'll try to carve out time on Saturday to reciew

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

Labels

lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem.

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants