skip to content

Run Orchestration

How a whole suite is run: the options and flags that split work across worker processes, react to failures, and hand results to CI. Asked because this is where suites break at scale.

on this pageshow

explore

questions

page 1 of 2

In Playwright, what does `npx playwright install --with-deps` do that plain `npx playwright install` does not?

level: juniorimportance: must knowfreq 70%

answer

  1. Two installs hide behind one flag
  2. Binaries alone are not enough
  3. Dynamic linking needs system libraries
  4. Needs root and a supported distro
  5. Unnecessary inside the official image

basics

~20 s

It also installs the operating-system packages the browsers link against, using the system package manager, before downloading them. Plain install only downloads the browser binaries, which then fail to launch on a bare Linux runner.

solid answer

~40 s

`npx playwright install` downloads the browser builds pinned to your installed Playwright version into its browser cache. That is only half the job on Linux: those binaries are dynamically linked and need graphics, font and audio libraries that a bare CI runner or slim base image usually lacks. `--with-deps` adds that half, shelling out to the system package manager first — so it needs root or `sudo`, and targets Debian/Ubuntu-family images. `npx playwright install-deps` is the same OS-package step on its own. Both forms take browser names, so `npx playwright install --with-deps chromium` skips two engines you never launch. Inside `mcr.microsoft.com/playwright` you need neither: the browsers and libraries are already baked into the image.

code

bash · 3 lines
bash
npm ci
npx playwright install --with-deps chromium
npx playwright test

go deeper

for a junior

Remember the split: plain install downloads browsers, and the flag adds the Linux system packages they need to start. On a bare CI runner you want the flag.

for a middle

Explain why the second half exists: the browser binaries are dynamically linked, so missing shared libraries kill them at launch even though the download succeeded.

for a senior

Show the operational angle: it needs root and distro mirrors, it runs on every job unless baked into an image, and naming a single browser cuts cold setup materially.

for a principal

Decide the policy — install per job, cache the browsers, or bake an image — and make sure whichever route you pick installs the version the lockfile just resolved.

## One command, two different installs `npx playwright install` downloads **browser builds** — the Chromium, Firefox and WebKit binaries pinned to your installed `@playwright/test` version — into Playwright's browser cache. That is a plain file download; it needs network access and disk, nothing more. Those binaries then have to *link*. On Linux a browser is a dynamically linked executable that needs graphics, font, audio and X/GTK libraries present on the host. A stock CI runner or a slim base image usually has few of them. `npx playwright install --with-deps` adds that second install: it runs the system package manager to put those shared libraries in place, then downloads the browsers. `npx playwright install-deps` is the same OS-package half on its own, for when the browsers are already present but the libraries are not. ## What the deps half needs - **Elevated privileges.** It shells out to the system package manager, so it needs root or `sudo`; an unprivileged CI user gets a permission failure, not a silent skip. - **A supported distro.** The dependency lists Playwright ships target Debian/Ubuntu-family images. On anything else you install the libraries yourself. - **Network to the distro mirrors**, not just to the browser CDN — two different egress paths, which matters on a locked-down runner. - **Time on every run** unless you bake it into an image, because packages installed into a throwaway runner die with the runner. ## Failure modes it prevents Without the OS packages, `npx playwright install` looks like it worked and the failure arrives later, at launch, as a browser process that exits immediately or a message naming a missing `.so` file. That is the confusing shape: the download step is green, the test step dies. `--with-deps` collapses both halves into one step that fails loudly at setup time. | Situation | What to run | Why | |---|---|---| | Bare Ubuntu CI runner, root available | `npx playwright install --with-deps` | Neither browsers nor libraries are present | | Inside `mcr.microsoft.com/playwright:v1.63.0-noble` | nothing | Browsers and libraries already ship in the image | | Slim custom image, browsers cached in a volume | `npx playwright install-deps` | Only the OS libraries are missing | | Local developer laptop | `npx playwright install` | The desktop OS already has the libraries | ## Narrowing what you download Both forms take browser names, so a payroll regression suite that only ever runs Chromium can do `npx playwright install --with-deps chromium` and skip two engines' worth of download and disk. That is usually the single biggest cut to a cold CI setup step. Add engines back when a project in the config actually needs them — installing less than the config launches just moves the failure to launch time. ## Where it fits in a job 1. Check out the repository and install npm dependencies as usual; this step does **not** fetch browsers for you. 2. Run `npx playwright install --with-deps` (optionally naming browsers) as an explicit step. 3. Run the suite. Inside the official image, step 2 disappears, which is most of the reason to use the image at all. Running `--with-deps` there anyway is harmless but wasteful: it re-checks packages that were baked in at build time, adding a slow apt round-trip to every job for no change in outcome. One last point worth saying out loud in an interview: the flag installs **operating-system** dependencies, not npm ones. It has nothing to do with `package.json`, lockfiles, or which browsers your config declares — it is the bridge between a downloaded binary and a Linux box that can actually execute it.

  • What breaks if you run plain install on a bare Ubuntu runner?
    The download step goes green and the failure moves to launch time: the browser process exits immediately, typically naming a missing shared library. That split is what makes it confusing — the setup step reports success while the test step dies, so people look at the tests rather than at the runner's packages.
  • Why might --with-deps fail on a CI runner that has network access?
    It runs the system package manager, so it needs elevated privileges and reachable distro mirrors — a different egress path from the browser CDN. An unprivileged user gets a permission error, and a locked-down runner can reach the browser downloads while the package repositories are blocked.

saying these in an interview costs you the question

  • Thinks it installs npm dependencies
  • Believes installing the package downloads browsers automatically
  • Runs it inside the official image out of habit
  • Expects it to work without root privileges
  • Assumes it works on any Linux distribution
open as a page

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

level: juniorimportance: must knowfreq 82%

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.

open as a page

In Playwright, how do you run one suite with several reporters at once and give each its own options?

level: juniorimportance: must knowfreq 72%

basics

~20 s

Set the reporter config option to an array of entries, each a reporter name plus an options object - for example list, junit with an outputFile, and html. The command line --reporter takes comma-separated names but carries no options.

open as a page

In Playwright, what does setting retries: 2 in playwright.config.ts do to a failing test?

level: juniorimportance: must knowfreq 70%

basics

~20 s

Playwright re-runs a failing test up to two more times, so retries: 2 allows three runs in all. Only the failing test re-runs, and one that passes on a later attempt is reported as flaky rather than failed.

open as a page

What does Playwright's --shard=1/4 flag do to the set of tests a run executes?

level: juniorimportance: must knowfreq 68%

basics

~20 s

Playwright splits the selected tests into four disjoint groups and runs only the first. Each shard is an independent run on its own machine, so all four have to be executed before the suite is covered.

open as a page

In Playwright, what does the workers option control and what is its default value?

level: juniorimportance: must knowfreq 72%

basics

~20 s

The workers option sets how many test processes Playwright runs at once, each running one test at a time. It defaults to half the machine's logical CPU cores, and --workers or -j overrides it for a run.

open as a page

Why must the mcr.microsoft.com/playwright image tag match your installed Playwright version?

level: middleimportance: must knowfreq 62%

basics

~20 s

Each Playwright release pins exact browser builds, and the image ships only those. A mismatched tag leaves the library looking for a browser revision that is not in /ms-playwright, so every test fails at launch.

open as a page

What does Playwright's forbidOnly config option protect a CI run from?

level: middleimportance: must knowfreq 66%

basics

~20 s

Playwright's forbidOnly makes a run fail when any test or group is marked with test.only. It stops a focused marker committed by accident from silently shrinking a CI suite to a single test that then reports green.

open as a page

In Playwright, when a test.describe.serial group hits a failure, what happens to the rest?

level: middleimportance: must knowfreq 66%

basics

~20 s

The tests after the failure are skipped rather than run. A retry does not resume at the failure: the whole group reruns from its first test, because serial mode treats the block as one ordered unit.

open as a page

In Playwright, does a CI run end green when three tests failed once and passed on retry?

level: middleimportance: must knowfreq 55%

basics

~20 s

Yes. Playwright records a test that failed then passed within its retries as flaky, counts it separately in the report, and still exits with code zero, so the job goes green unless the run is started with --fail-on-flaky-tests.

open as a page

How does Playwright's fullyParallel setting change the way --shard divides a suite?

level: middleimportance: must knowfreq 54%

basics

~20 s

It changes the unit being split. With fullyParallel off, Playwright shards whole spec files, so one file never spans two shards. With it on, individual tests are sharded, so shards get roughly equal test counts.

open as a page

What happens to a Playwright worker process when one of its tests fails?

level: middleimportance: must knowfreq 58%

basics

~20 s

Playwright throws the worker away. The process is shut down after the failure and a fresh worker process, with a new browser, picks up the remaining tests, so nothing the failing test left behind reaches them.

open as a page

In Playwright, what does the --max-failures flag do, and what is -x short for?

level: juniorimportance: should knowfreq 55%

basics

~10 s

In Playwright, --max-failures=N stops the whole run once N tests have failed; the remaining tests never start. The shorthand -x means --max-failures=1, so the run aborts on the first failed test.

open as a page

What does Playwright change about a run when the CI environment variable is set?

level: middleimportance: should knowfreq 44%

basics

~20 s

Only the default reporter: with CI set and no reporter configured, Playwright prints one character per test instead of the interactive line-per-test output. Everything else people attribute to it is written in the project's own config.

open as a page

What does Playwright's test.fixme() do to a test that is known to be broken?

level: middleimportance: should knowfreq 36%

basics

~20 s

In Playwright, test.fixme() stops the test from running and reports it as skipped rather than failed, so a known-broken payroll test keeps its code and its name in the suite without turning the run red.

open as a page

How does Playwright's --last-failed flag know which tests failed on the previous run?

level: middleimportance: should knowfreq 38%

basics

~20 s

Playwright writes a .last-run.json file into the test output directory recording the run status and the ids of failed tests. The --last-failed flag reads that file, so it selects nothing useful if the directory is not preserved.

open as a page

In Playwright, what does test.describe.configure({ mode: 'default' }) do in a fullyParallel project?

level: middleimportance: should knowfreq 44%

basics

~20 s

Default mode opts that scope back out of test-level parallelism. The tests run in declaration order in one worker again, but stay independent: a failure skips nothing after it, and a retry reruns only the failing test.

open as a page

In Playwright, how do `test.step` and `testInfo.attach` change what the HTML report shows for a test?

level: middleimportance: should knowfreq 48%

basics

~20 s

Steps turn a test into named, timed sections in the report, and a failure is attributed to the step it broke in. Attachments record a named file or string on the test, rendered inline for images and text.

open as a page

What do Playwright's `list`, `line` and `dot` terminal reporters each print to the console?

level: middleimportance: should knowfreq 55%

basics

~20 s

Playwright's list reporter prints one line per test with status and duration, line keeps a single updating line plus failures as they happen, and dot prints one character per test. All three print full failure detail at the end.

open as a page

In a Playwright test, what does testInfo.retry hold, and why would a hook read it?

level: middleimportance: should knowfreq 45%

basics

~20 s

testInfo.retry is the zero-based attempt number of the running Playwright test: 0 on the first run, 1 on the first retry, and so on. Hooks read it to reset state or raise logging only when a test is being re-run.

open as a page

In Playwright, how do testInfo.workerIndex and testInfo.parallelIndex differ?

level: middleimportance: should knowfreq 42%

basics

~20 s

workerIndex names a process and never repeats: every worker a run starts, including replacements after failures, gets a new one. parallelIndex names a slot between zero and workers minus one, and a replacement worker inherits it.

open as a page

Playwright's Chromium crashes pages only when the suite runs inside a container — what does `--ipc=host` change?

level: seniorimportance: should knowfreq 48%

basics

~10 s

Containers get a private, small /dev/shm, and Chromium passes large buffers through that shared memory. When it fills, renderers die and pages crash. Running with --ipc=host gives the container the host's shared memory instead.

open as a page

Your Playwright payroll suite sometimes burns the whole CI hour with no verdict — how do globalTimeout and maxFailures each bound it?

level: seniorimportance: should knowfreq 44%

basics

~20 s

In Playwright, globalTimeout caps wall-clock time for the whole run and ends it whatever the results look like; maxFailures caps how many failed tests the run tolerates. A suite that hangs without failing is stopped only by globalTimeout.

open as a page

Enabling Playwright's fullyParallel made one payroll spec fail intermittently in CI — how do you contain it?

level: seniorimportance: should knowfreq 51%

basics

~20 s

Confirm the schedule is the trigger by rerunning that spec with and without test-level parallelism, then apply the narrowest override that holds: default mode for the file, or a serial describe around only the dependent tests.

open as a page

Two Playwright runs in one CI job keep overwriting `playwright-report`; how do you give each its own folder?

level: seniorimportance: should knowfreq 42%

basics

~20 s

The html reporter clears its folder before each run, so the second run replaces the first. Point each run somewhere else with the outputFolder option, or set PLAYWRIGHT_HTML_OUTPUT_DIR per command, and archive each folder separately.

open as a page

Your Playwright suite runs with retries: 2 and trace 'on-first-retry', yet flaky tests only leave traces of passing runs — why?

level: seniorimportance: should knowfreq 40%

basics

~10 s

Because on-first-retry starts recording on the second attempt, not the first: the run that actually failed was never traced. Switching to retain-on-first-failure records the original run and keeps it only when it failed.

open as a page

Four Playwright shards each produced their own HTML report - how do you get one report for the whole run?

level: seniorimportance: should knowfreq 47%

basics

~20 s

Have every shard run the blob reporter instead of html. Each writes one archive, CI collects them into a single directory, and npx playwright merge-reports turns that directory into one HTML report covering the whole suite.

open as a page

Playwright's default worker count makes your payroll suite time out in a CPU-limited CI container - how do you diagnose and fix it?

level: seniorimportance: should knowfreq 36%

basics

~20 s

The default is half the cores the operating system reports, which is usually the host's, not the container's CPU allowance. Read the worker count from the run header, compare it with the container limit, then pin workers explicitly.

open as a page

How would you decide between the official Playwright image and `playwright install --with-deps` on a CI runner?

level: principalimportance: should knowfreq 36%

basics

~20 s

Choose the image when the environment should be pinned and the job needs nothing else; choose your own base plus an install step when it needs other tooling. Often the answer is an image built from the official one.

open as a page

Should a Playwright suite's shard split live in playwright.config.ts or in the CI command line?

level: principalimportance: should knowfreq 32%

basics

~20 s

Playwright treats both identically, so it is a question of ownership. The split belongs to the pipeline launching the jobs, so the --shard flag usually wins; the config option earns its place when a wrapper script starts the run.

open as a page

showing 1–30 of 33