Skip to content

Commit

Permalink
fix(jest-core): always use workers in watch mode
Browse files Browse the repository at this point in the history
The comment here already said one good reason to do this; another is
that if the test hard-crashes (e.g. an async error after it completes)
then using workers allows us to still watch for changes (perhaps to fix
that crash). So now we just always use workers in watch mode; this
probably worsens startup time slightly but for watch mode that's
hopefully not as much of a problem.

Fixes jestjs#13996.
  • Loading branch information
benjaminjkraft committed Apr 6, 2023
1 parent 470d72e commit 537d213
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- `[jest-environment-jsdom, jest-environment-node]` Fix assignment of `customExportConditions` via `testEnvironmentOptions` when custom env subclass defines a default value ([#13989](https://github.com/facebook/jest/pull/13989))
- `[jest-matcher-utils]` Fix copying value of inherited getters ([#14007](https://github.com/facebook/jest/pull/14007))
- `[jest-snapshot]` Fix a potential bug when not using prettier and improve performance ([#14036](https://github.com/facebook/jest/pull/14036))
- `[jest-core]` Always use workers in watch mode to avoid crashes (TODO).

### Chore & Maintenance

Expand Down
8 changes: 4 additions & 4 deletions packages/jest-core/src/__tests__/testSchedulerHelper.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ const getTestsMock = () => [getTestMock(), getTestMock()];

test.each`
tests | timings | detectOpenHandles | maxWorkers | watch | workerIdleMemoryLimit | expectedResult
${[getTestMock()]} | ${[500, 500]} | ${false} | ${undefined} | ${true} | ${undefined} | ${true}
${getTestsMock()} | ${[2000, 500]} | ${false} | ${1} | ${true} | ${undefined} | ${true}
${[getTestMock()]} | ${[500, 500]} | ${false} | ${undefined} | ${true} | ${undefined} | ${false}
${getTestsMock()} | ${[2000, 500]} | ${false} | ${1} | ${true} | ${undefined} | ${false}
${getTestsMock()} | ${[2000, 500]} | ${false} | ${2} | ${true} | ${undefined} | ${false}
${[getTestMock()]} | ${[2000, 500]} | ${false} | ${undefined} | ${true} | ${undefined} | ${false}
${getTestMock()} | ${[500, 500]} | ${false} | ${undefined} | ${true} | ${undefined} | ${false}
Expand All @@ -36,8 +36,8 @@ test.each`
${new Array(45)} | ${[500]} | ${false} | ${undefined} | ${false} | ${undefined} | ${false}
${getTestsMock()} | ${[2000, 500]} | ${false} | ${undefined} | ${false} | ${undefined} | ${false}
${getTestsMock()} | ${[2000, 500]} | ${true} | ${undefined} | ${false} | ${undefined} | ${true}
${[getTestMock()]} | ${[500, 500]} | ${false} | ${undefined} | ${true} | ${'500MB'} | ${true}
${getTestsMock()} | ${[2000, 500]} | ${false} | ${1} | ${true} | ${'500MB'} | ${true}
${[getTestMock()]} | ${[500, 500]} | ${false} | ${undefined} | ${true} | ${'500MB'} | ${false}
${getTestsMock()} | ${[2000, 500]} | ${false} | ${1} | ${true} | ${'500MB'} | ${false}
${getTestsMock()} | ${[2000, 500]} | ${false} | ${1} | ${false} | ${'500MB'} | ${false}
${[getTestMock()]} | ${[2000]} | ${false} | ${undefined} | ${false} | ${'500MB'} | ${false}
${getTestsMock()} | ${[500, 500]} | ${false} | ${undefined} | ${false} | ${'500MB'} | ${false}
Expand Down
22 changes: 11 additions & 11 deletions packages/jest-core/src/testSchedulerHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,25 @@ export function shouldRunInBand(
}

/*
* Run in band if we only have one test or one worker available, unless we
* are using the watch mode, in which case the TTY has to be responsive and
* we cannot schedule anything in the main thread. Same logic applies to
* watchAll.
* If we are using watch/watchAll mode, don't schedule anything in the main
* thread to keep the TTY responsive and to keep the watcher running even if
* the test crashes.
*/
const isWatchMode = watch || watchAll;
if (isWatchMode) {
return false;
}

/*
* Otherwise, run in band if we only have one test or one worker available.
* Also, if we are confident from previous runs that the tests will finish
* quickly we also run in band to reduce the overhead of spawning workers.
* Finally, the user can provide the runInBand argument in the CLI to
* force running in band.
* https://github.com/facebook/jest/blob/700e0dadb85f5dc8ff5dac6c7e98956690049734/packages/jest-config/src/getMaxWorkers.js#L14-L17
*/
const isWatchMode = watch || watchAll;
const areFastTests = timings.every(timing => timing < SLOW_TEST_TIME);
const oneWorkerOrLess = maxWorkers <= 1;
const oneTestOrLess = tests.length <= 1;

if (isWatchMode) {
return oneWorkerOrLess || (oneTestOrLess && areFastTests);
}

return (
// When specifying a memory limit, workers should be used
!workerIdleMemoryLimit &&
Expand Down

0 comments on commit 537d213

Please sign in to comment.