Parallel Execution vs. --runInBand for Stateful Test Suites
0 reputation · 05 Feb 2022, 10:15 UTC
0 reputation · 05 Feb 2022, 10:15 UTC
Vitest leverages worker processes to execute test files concurrently by default, which significantly reduces total runtime for large suites. However, this parallelization can introduce non-deterministic failures when tests rely on mutable global state or shared file system resources.
The --runInBand flag provides an alternative by forcing tests to run serially in the main process. While this ensures deterministic execution order and eliminates race conditions, it removes the performance benefits of multi-core utilization, potentially increasing CI pipeline duration.
A specific uncertainty exists regarding the isolation of mocks across these different execution modes. When using parallel workers, it is unclear if mocks are strictly isolated per worker or if state can leak across tests assigned to the same process.
--runInBand provide a different level of mock isolation compared to the default parallel worker pool?maxWorkers: 1 be preferred over the --runInBand CLI flag for stateful suites?35275 reputation · 05 Feb 2022, 21:07 UTC
The --runInBand flag provides a lower level of mock and state isolation compared to the default parallel worker pool. While parallel execution isolates test files across separate worker processes or threads, --runInBand executes all tests sequentially within the main process. This removes the process boundary, meaning global state mutations, modified prototypes, or mocks that are not explicitly cleared can leak from one test file into the next.
In default parallel mode, Vitest distributes files across workers. If two files are assigned to different workers, they are strictly isolated. If they share a worker, Vitest still attempts to isolate the environment, but the process boundary remains the primary defense against leakage. In contrast, --runInBand eliminates this boundary entirely to reduce the overhead of spawning workers.
You should prefer maxWorkers: 1 over --runInBand when your suite is stateful but still requires process-level isolation. Use maxWorkers: 1 under these specific constraints:
To verify if state is leaking in your current configuration, you can run a scoped test:
test-a.spec.ts that modifies a global variable or a module-level singleton.test-b.spec.ts that asserts the initial value of that same global variable.vitest --runInBand; if test-b fails, you have state leakage.vitest --maxWorkers=1; if test-b passes, the worker boundary is successfully isolating your suites.Diagnostic Detail Needed: To provide a more precise recommendation, are you using threads or forks in your poolOptions? This changes how memory is shared and how isolation is enforced.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.