-
-
Notifications
You must be signed in to change notification settings - Fork 34.1k
test_runner: support expecting a test-case to fail #60669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
test_runner: support expecting a test-case to fail #60669
Conversation
|
Review requested:
|
|
There is long-established precedent for
What is the commitment level and timeline for this? I ask because I've already implemented lmk, please |
|
Ah, sure. I'm not particular about the name as long as it's intuitive (which I expect this could land pretty quickly: quite a few collaborators had previously voiced support for it, and to my knowledge there have been no general concerns raised against the feature itself. Aside from the name (which is trivial to update in the PR), the remaining work is:
Creating competing PRs is never desirable and generally pisses off the person / people already working on it. Happy to collaborate on the feature; but aside from influencing the name, I think this is very straightforward and has very little implication work, especially almost none remaining. In terms of timeline to finish this, I expect to have time this week (the past ~2 weeks were very tumultuous for me). |
|
Additional features that my version has:
I think that's it, though I'll have to take a look at |
|
Alex and I considered those and pushed them to v2 to get the base implementation landed sooner (many users probably won't need the v2 extras, so no need to make them wait for things they don't want/need). If you already have an implementation for that, I'm happy to defer to you for that once this lands 🙂 |
|
Deferring to v2 makes sense, but I think you should quickly consider how it would be added to the API, just to avoid potential API thrashing or getting painted into a corner. In the implementation, you have a string value given for How would you, in v2, specify the expected failure? An |
|
Arguably a new kind of OTOH, assertions of failures maybe should be reserved for testing that the code throws the correct exception under specific conditions. |
|
That's contrary to the intention of this feature: the test should be identical to the non-failing version. This is flag to flip.
|
We were thinking in the case of In the case of For all of these, there is no API thrashing as they're all truthy / falsy, which makes them additive to the current. |
|
it all sounds good to me. I'm glad this is getting into As to reporting, I think you have three options:
In my implementation, I chose option 2. A failing xfail generates a test todo event, where the todo message is prefixed with "xfail:". A passing xfail generates a test fail event, with an error indicating that it was an xfail that unexpectedly passed. This allows my xfail aware reporter to produce a more informative report (it formats xfail results differently from both pass and todo), while degrading gracefully for legacy reporters. |
|
I (and I think Alex too?) was imagining the result of Reporters that support the extra prop do so, and those that don't just behave "normally" (even the uninformed report is still correct). |
Jacob, both spec and dot reporters rely on:
I know this as I spent a lot of time trying to reverse engineer the semantics of TestsStream, which isn't documented nearly enough for people to write custom reporters without inferring semantics by reading all of the built-in reporter code. I will open a discussion or issue on that topic when I get the chance. But as part of my reverse engineering, I ended up paying off some test_runner tech debt in precisely this part of the code: #59700. It's seems to be falling through the cracks in PR limbo. Maybe we can get that merged? It isn't strictly necessary for your PR, but since we'll have review eyes on this area of code, it would be efficient to do both at the same time? |
|
|
||
|
|
||
| it.todo('sync pass todo', () => { | ||
| it.xfail('sync expect fail (method)', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should also add a "sync pass xfail with message" like there is with todo and skip.
This opens up the question of what that should look like for TAP. In my own reporter, I append #XFAIL to the message. The discussion on TAP Directives for XPASS and XFAIL that I linked to in the main thread debates #XFAIL vs #TODO. The latter makes a lot of sense too... see my comment that conceptually an xfail is a special case of todo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean in the case of specifying it via config object? If so, the value that would subsequently be supported would be the expected failure we talked about #60669 (comment) so
it('should add', { xfail: 'Expected 2 to equal 1' }, () => { … });where the test-case must fail with an error whose message is 'Expected 2 to equal 1'
Or as a regex:
it('should add', { xfail: /expected 2 to equal 1/i }, () => { … });When it fails with a different error, xfail would then not "pass" (and would be marked "failed", reported as failed, etc).
That would then be used in the test-case reporter output like
✔ should add # Expected 2 to equal 1
✔ should add # /expected 2 to equal 1/i
✖ should add # Expected 2 to equal 1
✖ should add # /expected 2 to equal 1/i
But since that's part of v1.1, I think for now it should not handle any value other than truthy/falsy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think both a reason (like todo and skip) and expected error should be supported. Example reasons:
✔ should add #XFAIL Issue #389
✔ should add #XFAIL Can't fix until SemVer Major increment
I'm building a system where released bugs are tracked both as a a bug tracking issue and as an XFAIL test case.
I took your comment to mean (update of the current documentation to illustrate):
- skip
<boolean> | <string>If truthy, the test is skipped. If a string is provided, that string is displayed in the test results as the reason for skipping the test. Default: false.- todo
<boolean> | <string>If truthy, the test marked as TODO. If a string is provided, that string is displayed in the test results as the reason why the test is TODO. Default: false.- xfail
<boolean> | <string> | <RegExp>If truthy, the test marked as XFAIL. If a string is provided, that string is displayed in the test results as the reason why the test is expected to fail. If a RegExp is provided, only a failure that matches is permitted. Default: false.
Now I see my interpretation was wrong. In any case, that approach would allow EITHER a reason OR an expected error, NOT BOTH. I think both should be supported.
But as you say, we can punt until v1.1. 🤫🤐🙃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think both a reason (like todo and skip) and expected error should be supported.
How? I think that creates a paradox: is it merely a label or is it the expected error? There's no way to know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see two reasonable ways to do it:
- The
xfailproperty works exactly liketodoandskip: if it is a string it is the reason. Another optional property would be added to specify a specific error or error pattern, e.g.xfail_error. xfail:truestring: reasonRegExp: expected pattern in error message{reason: string, error: RegExp}
Huzzah, yes, that's it. Thanks! |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #60669 +/- ##
==========================================
- Coverage 88.54% 88.52% -0.02%
==========================================
Files 703 703
Lines 208545 208606 +61
Branches 40216 40242 +26
==========================================
+ Hits 184652 184671 +19
- Misses 15905 15947 +42
Partials 7988 7988
🚀 New features to boost your workflow:
|
|
PR is quasi-blocked by a bug in the |
241e5dd to
e93deac
Compare
Failed to start CI⚠ Commits were pushed since the last approving review: ⚠ - test_runner: support expecting a test-case to fail ⚠ - fixup!: rename `fail` → `xfail` ⚠ - fixup!: add `getXFail` to `TestStream` ⚠ - fixup!: test-case descriptions ⚠ - fixup!: add doc for `xfail` ⚠ - fixup!: tidy todo comment ⚠ - fixup!: add `# EXPECTED FAILURE` to other builtin reporter output ⚠ - fixup!: update snapshot ⚠ - fixup!: add meta to doc ⚠ - fixup!: remove unnecessary code comment ⚠ - fixup!: update snapshot ⚠ - fixup!: add `xfail` cases to all reporter tests ⚠ - fixup!: update snapshots ⚠ - fixup!: update snapshot ⚠ - fixup!: update API doc to be less "why", just "what" ✘ Refusing to run CI on potentially unsafe PRhttps://github.com/nodejs/node/actions/runs/20462588334 |
pmarchini
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
|
I did quite some digging, and it seems there is no consensus on a name. IMO none of the names are particularly good, so I think going with the most likely recognised ( |
|
@ljharb's point is that in the JS world, Ava and Jest call it And when you search both Ava and Jest's repos or Issues for "failing" or "failing test", you get more hits for regular test failures, not expected failures. It doesn't have to be |
|
if it's bikeshed time, what about |
|
|
|
I dunno about bike-shedding time 😆 I would say we don't have especially good options, what we currently have may be the best of the worst, so unless a dark-horse appears to wow everyone, let's go with what is already done. If something awesome comes up later, we can alias it and phase out the current (and provide a migration—the API won't change, just the same). |
|
I'm not sure why there's a rush to land something with a name that folks aren't broadly happy with? |
|
A time-boxed discussion on a better name sounds reasonable, and I don't mind making the change (it's a trivial find+replace since Shall we say end of day CET Saturday, 27 December? I'll be on a long train Sunday, which will give me time to make relevant changes and then babysit CI. I'll be unavailable much of January. |
|
so far we've got:
Also, there's
Any more thoughts from folks? |
|
Let's move this to a discussion (I think that will be easier, and we can eventually use its poll feature): nodejs/test-runner#1 |



This PR adds support for an
xfaildirective (similar toskipandtodo), whereby a user can flag a test-case as expected to fail.