test_runner: extend tag filter with boolean expression DSL#63054
test_runner: extend tag filter with boolean expression DSL#63054atlowChemi wants to merge 1 commit into
Conversation
|
Review requested:
|
| 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`/`||`, |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
that is more consistent to our name filter flag
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Before I even saw Moshe's comment, I was thinking the same thing. But after a minute, I can see the use of it.
I know && and || align with javascript, but it seems a little long, and the simpler & and | look pretty straightforward to me (and aligns with others, like query params and old skool forum query syntax). What happens when you combine them though?
--experimental-test-tag-filter=foo&bar&qux|zedIs that "foo and bar and (qux or zed)" or "(foo and bar and qux) or zed"? For some reason, my eyes see the former, but syntactically, it's usually the latter. IMO the original spec for syntax made a huge mistake not requiring parentheses when combining operators. If we support combining operators, I think parentheses should be required.
--experimental-test-tag-filter=(foo&bar&qux)|zed--experimental-test-tag-filter=foo&bar&(qux|zed)There was a problem hiding this comment.
@JakobJingleheimer I feel that & vs && is not really "a little long", and I feel using & and | could be confusing with bitwise operators, while removing just a single character...
There was a problem hiding this comment.
I considered that before posting: I think nobody would be confused here because bitwise is not appropriate.
&& vs & is a thought musing.
My bigger concern would be parens for combined operators.
There was a problem hiding this comment.
thats why I think we should release a initial version that does not include this new langauge
There was a problem hiding this comment.
@MoLow @JakobJingleheimer I opened #63221 to separate these concerns.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #63054 +/- ##
==========================================
+ Coverage 90.04% 90.07% +0.02%
==========================================
Files 714 714
Lines 225245 225641 +396
Branches 42571 42668 +97
==========================================
+ Hits 202821 203242 +421
- Misses 14186 14192 +6
+ Partials 8238 8207 -31
🚀 New features to boost your workflow:
|
|
Sweet! I'll try to carve out time on Saturday to reciew |
3591324 to
31a7737
Compare
JakobJingleheimer
left a comment
There was a problem hiding this comment.
Sorry for the delay. GitHub is having a bit of a stroke. Every time I try to add a comment to the review "Something went wrong" and I have to copy it, reload, paste, and try a couple more times.
I'll try to finish tomorrow (I got through 10 of 18 files, which doesn't include tag_filter.js).
| 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`/`||`, |
There was a problem hiding this comment.
Before I even saw Moshe's comment, I was thinking the same thing. But after a minute, I can see the use of it.
I know && and || align with javascript, but it seems a little long, and the simpler & and | look pretty straightforward to me (and aligns with others, like query params and old skool forum query syntax). What happens when you combine them though?
--experimental-test-tag-filter=foo&bar&qux|zedIs that "foo and bar and (qux or zed)" or "(foo and bar and qux) or zed"? For some reason, my eyes see the former, but syntactically, it's usually the latter. IMO the original spec for syntax made a huge mistake not requiring parentheses when combining operators. If we support combining operators, I think parentheses should be required.
--experimental-test-tag-filter=(foo&bar&qux)|zed--experimental-test-tag-filter=foo&bar&(qux|zed)| * Any include expression (a tag, wildcard, `and`, or `or`) is **false** | ||
| for an untagged test, so untagged tests are excluded under any positive | ||
| filter. | ||
| * `not X` is **true** for an untagged test, so excluding tags does not | ||
| accidentally remove untagged tests. |
There was a problem hiding this comment.
This is generally difficult to follow. I think a table of examples would be more straightforward.
| fail(nesting, loc, testNumber, name, details, directive, testId) { | ||
| fail(nesting, loc, testNumber, name, details, directive, testId, tags) { |
There was a problem hiding this comment.
General comment: this is getting to be a bit of a junk-drawer of arguments 😬
There was a problem hiding this comment.
I agree, perhaps we could open a
good first issue
@JakobJingleheimer github having issues? no way 😂 |
31a7737 to
853f715
Compare
853f715 to
131d524
Compare
Upgrades the experimental tag filter introduced by stage 1 to accept a boolean expression instead of a literal tag name. Grammar: `and`/`&&`, `or`/`||`, `not`/`!`, parentheses for grouping, and `*` wildcards inside identifiers. Standard precedence (`not > and > or`); binary operators are left-associative. Word forms require whitespace separation; punctuation forms do not. Untagged tests evaluate `false` for any include expression and `true` for `not X`, so excluding tags does not accidentally remove untagged tests. The flag and `testTagFilters` option are still repeatable; multiple expressions still AND together. Malformed expressions fail fast at the parent process at startup. Tag value validation tightens to reject whitespace, operator characters (`& | ! ( ) *`), and the reserved words `and`/`or`/`not` in any casing - a breaking change relative to the stage 1 ship, acceptable at Stability 1.0 (Early development). Signed-off-by: atlowChemi <chemi@atlow.co.il>
131d524 to
3f583b5
Compare
Summary
Builds on #63221, which landed the tags option, inheritance, reporter
event payloads, and a literal-tag-name filter. This PR upgrades the
filter to a boolean expression DSL:
and/&&,or/||,not/!, parentheses for grouping,and
*wildcards inside identifiers (bare*matches any taggedtest). Standard precedence (
not > and > or); binary operators areleft-associative. Word forms (
and/or/not) require whitespaceseparation; punctuation forms do not.
--experimental-test-tag-filterand thetestTagFiltersrun()option now accept an expression rather than a literal tag name. The
flag is still repeatable; multiple expressions still AND together.
falseagainst anempty tag set;
not Xevaluatestrue. Sonot flakykeeps everyuntagged test, while
dbexcludes them.whitespace, operator characters (
& | ! ( ) *), or the reservedwords
and/or/notin any casing. This is a breaking changerelative to test_runner: add tags option and tag-name filter #63221 - acceptable since the feature is at Stability 1.0
(Early development).
test file is spawned.
Prior art
Tag filtering with boolean composition is well-trodden in the JS
testing ecosystem. The expression syntax here is closest to Vitest's:
mocha-tags- https://www.npmjs.com/package/mocha-tagsjest-runner-groups- https://www.npmjs.com/package/jest-runner-groupsjest-tags- https://github.com/gitbrik/jest-tagsVitest additionally lets a tag carry per-test config overrides such as
timeoutorretry(with priority resolution between overlappingtags). 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 established in
#63221.