skip to content

In Playwright, what does the fullyParallel config option change about test scheduling?

level: juniorimportance: must knowfreq 82%

answer

  1. What gets handed to a worker
  2. File is the default unit
  3. Order inside a file disappears
  4. Config flag plus a CLI form
  5. Describe modes override the flag

basics

~20 s

Playwright runs test files in parallel but keeps tests inside a file in order in one worker. Setting fullyParallel true schedules every individual test independently, so tests in the same file can also run at the same time.

solid answer

~40 s

By default Playwright's unit of parallelism is the file: the runner hands each spec file to a worker process, and the tests inside that file run in declaration order in that one worker. Setting `fullyParallel: true` in `playwright.config.ts`, or passing `--fully-parallel` for a single run, changes the unit to the individual test, so two tests from the same file may execute concurrently in different workers and in no guaranteed order. It is purely a scheduling switch: it changes how many tests are in flight, not what any test does. Per-group overrides still win over it, so `test.describe.configure({ mode: 'serial' })` pins a block back to one ordered worker, and `mode: 'default'` opts a whole file back out of fully parallel scheduling.

code

typescript · 8 lines
typescript
// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  testDir: './tests/payroll',
  // Schedule every test independently, not just every spec file.
  fullyParallel: true,
});

go deeper

for a junior

Remember the one-line contrast: files run together by default, tests inside a file run in order, and fullyParallel makes the individual test the unit instead.

for a middle

Explain the mechanics: dispatch unit, loss of declaration order, and how describe-level modes override the config flag per file or per block.

for a senior

Show you can roll it out safely on a real suite, predicting which shared state and which hooks change behaviour before flipping it on in CI.

for a principal

Own the policy question of whether the suite is parallel by default with marked exceptions, and what that implies for load on the system under test.

## The default schedule Playwright's runner starts a pool of worker processes and dispatches work to them. Out of the box the thing it dispatches is a whole **test file**. That gives you two guarantees that beginners rely on without noticing: - Different spec files run **at the same time**, in different worker processes. - Tests **inside** one file run **one after another, in declaration order**, in a single worker. - A failing test does **not** stop the tests declared after it in that file; they still run. So a payroll regression suite with 40 spec files already parallelises 40 ways, but a single file holding 30 tests is a 30-test-long queue on one worker. ## What `fullyParallel: true` changes Setting `fullyParallel: true` in `playwright.config.ts` moves the unit of dispatch from the file down to the **individual test**. After that: - Any test may be picked up by any free worker, including two tests declared in the same file. - **Declaration order stops being an execution order.** Test 2 in a file may start before test 1 finishes, or before it starts at all. - The wall-clock ceiling of the run drops from *longest file* to roughly *longest single test*, subject to how many workers you allow. The same switch is available for one run from the command line as `--fully-parallel`, which is handy for asking "is this suite actually parallel-safe?" without committing the config change. ## The two schedules side by side | | default | `fullyParallel: true` | |---|---|---| | Unit dispatched | one spec file | one test | | Order inside a file | declaration order | none guaranteed | | Tests of one file share a worker | yes | not necessarily | | Wall-clock floor | slowest file | slowest test | | Effect of a failure on later tests in the file | none | none | ## Precedence: config, file, group `fullyParallel` is the baseline, not the last word. `test.describe.configure({ mode })` overrides it for the scope it is called in, and the innermost call wins: 1. Call `test.describe.configure({ mode: 'parallel' })` at the top of one file to get test-level parallelism for that file only, without turning the flag on globally. 2. Call `test.describe.configure({ mode: 'default' })` at the top of a file to opt that file out again when the rest of the repository runs fully parallel. 3. Call `test.describe.configure({ mode: 'serial' })` inside a `test.describe` block to pin just that block to one worker in order. That layering is what lets a large suite adopt `fullyParallel` in one commit and quarantine the handful of order-dependent files instead of holding the whole suite back. ## Practical consequences to expect - Anything a test leaves behind, such as a queued payroll export or a mutated pay period, can now be observed by a test that used to run safely after it. The failure surfaces as a flake, not as a compile error. - Hooks change shape: a `beforeAll` in a parallel-mode block runs once **per worker** that picks up a test from it, so it may run several times in one run. - More concurrency means more browsers and more load on the system under test at once; a payroll backend that is fine with four concurrent sessions may not be fine with twenty. - The reported per-test durations do not change, only the total wall clock, so a run that looks "three times faster" is the scheduler working, not the tests getting quicker. ## How to say it in an interview Lead with the unit of parallelism. "By default the file is the unit and tests inside it are ordered on one worker; `fullyParallel` makes the test the unit, so nothing inside a file is ordered any more." Then add the escape hatch in the same breath: describe-level modes override the flag, so you turn it on globally and mark the dependent groups rather than choosing one setting for the entire repository.

  • If fullyParallel is on, how do you keep one order-dependent spec file running the old way?
    Call `test.describe.configure({ mode: 'default' })` at the top level of that file. It restores the default schedule for that file only: its tests run in declaration order in a single worker, while every other file keeps the fully parallel behaviour from the config.
  • Does fullyParallel change how many browsers are open at once?
    Indirectly. It raises how many tests are eligible to run concurrently, so the workers you allow are more likely to all be busy, each with its own browser. The concurrency ceiling itself is still the worker count, not the flag.

Default mode is one checkout lane per shopping basket; fullyParallel opens a lane for every single item.

saying these in an interview costs you the question

  • Says tests in one file always run in parallel
  • Thinks fullyParallel makes each test faster
  • Believes declaration order is honoured under fullyParallel
  • Assumes the config flag cannot be overridden per file
  • Confuses parallel scheduling with retrying failed tests