-
Notifications
You must be signed in to change notification settings - Fork 30.2k
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
test_runner: add bail out #56490
base: main
Are you sure you want to change the base?
test_runner: add bail out #56490
Conversation
Review requested:
|
89f64db
to
55874e8
Compare
this.root.harness.testsProcesses.forEach((child) => { | ||
child.kill(); | ||
}); | ||
return; |
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.
replace with an abort signal?
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.
hey @atlowChemi, sure!
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.
We already have an existing signal passed to the spawned process, but that is a signal at the Test
level IIRC. perhaps we can add a new controller on root.harness
, and spawn with a AbortSignal.any
Can you explain more about what was flaky? I'm guessing you mean the tests were at different points of execution when they received the bail out signal. I think the best way to work around this is to use test fixtures that never finish. |
Hey @cjihrig, you're guessing right! Your proposed solution sounds good. I think we should add a test as follows:
WDYT? |
.add(kCancelledByParent) | ||
.add(kAborted) | ||
.add(kTestTimeoutFailure) | ||
.add(kTestBailedOut); |
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 know you just added to it here, but can we initialize the set without repeatedly calling add()
.
|
||
> Stability: 1 - Experimental | ||
|
||
The `--test-bail` flag provides a way to stop the test execution |
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.
The `--test-bail` flag provides a way to stop the test execution | |
The `--test-bail` flag provides a way to stop test execution |
By enabling this flag, the test runner will exit the test suite early | ||
when it encounters the first failing test, preventing | ||
the execution of subsequent tests. | ||
Already running tests will be canceled, and no further tests will be started. |
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'm not sure if we need to get into this small of a detail, but technically there will be a window of time where new tests may be started before being cancelled. Maybe we can say something like "The test runner will cancel all remaining tests."
when it encounters the first failing test, preventing | ||
the execution of subsequent tests. | ||
Already running tests will be canceled, and no further tests will be started. | ||
**Default:** `false`. |
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.
This default seems out of place.
@@ -1483,6 +1512,11 @@ changes: | |||
does not have a name. | |||
* `options` {Object} Configuration options for the test. The following | |||
properties are supported: | |||
* `bail` {boolean} |
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 don't think this should be an option to test()
. Should it be part of run()
instead?
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.
Yes, my bad, the bail
option it's part of run
. I'll update the doc ASAP !
}); | ||
|
||
test('top level', (t) => { | ||
t.test('forth', () => {}); |
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.
t.test('forth', () => {}); | |
t.test('fourth', () => {}); |
fixtures.path('test-runner', 'never_ending_sync.js'), | ||
fixtures.path('test-runner', 'never_ending_async.js'), | ||
] }); | ||
const stream = run({ |
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.
This file seems to have a number of stylistic changes. Was that intentional?
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.
Nope, I will remove unnecessary changes on the next commit!
it('should only allow a boolean in options.bail', async () => { | ||
[Symbol(), {}, [], () => { }, 0, 1, 0n, 1n, '', '1', Promise.resolve([])] | ||
.forEach((bail) => assert.throws(() => run({ bail }), { | ||
code: 'ERR_INVALID_ARG_TYPE' |
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.
Just out of curiosity, are we sure that these errors actually correspond to the use of bail
? For example, it's possible that ERR_INVALID_ARG_TYPE
or ERR_INVALID_ARG_VALUE
are thrown by run()
completely unrelated to the bail
option.
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've written the test following a red-green cycle.
I'll take another look and I'll add a comment here 😁
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.
Another option is to update the assertion to check the code and the message.
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 agree, we should probably do the same for the other "validation" tests as well
|
||
it('should handle the bail option', async () => { | ||
const stream = run({ | ||
files: [join(testFixtures, 'bailout/sequential.test.mjs')], |
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.
Minor nit, but if we're going to use join()
anyway:
files: [join(testFixtures, 'bailout/sequential.test.mjs')], | |
files: [join(testFixtures, 'bailout', 'sequential.test.mjs')], |
|
||
// TODO(pmarchini): Bailout is not supported in watch mode yet but it should be. | ||
// We should enable this test once it is supported. | ||
it.todo('should handle the bail option with watch mode'); |
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.
Should this be documented?
There are all sorts of annoying edge cases to account for here, and it might be worth doing a survey of how the tap, mocha, and vitest runners handle bailing out when things are running in parallel. It's much more straightforward when only one thing is running. But, for example, if the very first test in the first process fails, do we bother spawning the other child processes at all? Or, in a bail out situation, how important is it to have an accurate summary at the end of the test run with correct counts for total tests, cancelled tests, etc. |
Catching up with the last attempt (#48919), this is another try at introducing the bailout feature.
I'm opening this PR as a draft to discuss the implementation and because refactoring may be needed if this approach is well-received by the community.
Note: In some tests, I had to enforce a
concurrency=1
setting because testing the bailout feature across multiple files concurrently proved to be extremely flaky.