How does Playwright's driving model let a legacy quote suite get isolation without a browser launch per test?
answer
- Separate launch cost from isolation cost
- One browser per worker, one context per test
- Contexts are profiles, not processes
- Closing a context drops its state
- Engine or flags still force a relaunch
basics
~20 sOne connection serves one browser process that can hold many isolated profiles at once. Isolation costs a fresh context, created in milliseconds, instead of a process launch, so the expensive part is paid once per worker rather than once per test.
solid answer
~40 sA legacy suite that relaunches a browser per test is paying process start, profile creation and connection setup - often seconds - to get something Playwright gets from a context. Because the driver holds a live connection to a running browser, it can ask that browser for a new isolated profile whenever it likes: `browser.newContext()` gives a fresh cookie jar, storage and cache in milliseconds, and closing it takes that state away again. The launch cost moves to once per worker process, and per-test cost becomes context creation plus navigation. Playwright Test already arranges this for you: the built-in fixtures keep a browser per worker and hand each test a new context and page. What you still relaunch for is a different engine or different launch flags - and, unavoidably, after a crash.
code
typescript · 12 linesimport { chromium } from '@playwright/test';
const browser = await chromium.launch(); // paid once: process, profile, connection
for (const quoteId of ['1042', '1043', '1044']) {
const context = await browser.newContext(); // paid per test: milliseconds
const page = await context.newPage();
await page.goto(`https://quotes.example.com/motor/${quoteId}`);
await context.close(); // cookies, storage and cache go with it
}
await browser.close();go deeper
Remember the two different costs: starting a browser is expensive, and asking a running browser for a fresh isolated profile is not. Tests normally need the second one, not the first.
Explain what a context isolates - cookies, storage, cache, permissions - and why creating one needs no new process, no new binary and no new connection, only a message on the one already open.
Diagnose the real split between launch time and journey time before promising a speed-up, and name what you still relaunch for: a different engine, different launch flags, or a crashed process.
Own the trade you are making: shared processes concentrate failure, per-worker resources become the new ceiling, and cheap isolation only pays off if the suite's order-dependence is fixed rather than merely outrun.
A suite that opens a browser per test is usually not buying isolation; it is buying isolation **and** paying for a process launch it did not need. Playwright's driving model separates those two costs. ## What the per-test cost is made of Break the old number down before trying to beat it: - **Process start** - launching a browser binary, often the largest single cost. - **Profile creation** - a fresh on-disk profile, its caches and its first-run work. - **Connection setup** - the driver attaching and negotiating with the new process. - **The test itself** - navigation, the journey, the assertions. This is the only part that is really about your quote flow. Relaunching per test pays the first three every time. The driving model lets you pay them once and keep the connection. ## What the model allows instead Because one connection is attached to one running browser, that browser can hold many **contexts** at once, each an isolated profile with its own cookies, storage, cache and permissions. Isolation therefore has a different price: | | Relaunch the browser | Open a new context | |---|---|---| | Typical cost | process start plus profile setup | milliseconds inside a running browser | | What is isolated | everything, including flags and engine | cookies, storage, cache, permissions | | Cleanup | process exit | `context.close()` drops the state | | Blast radius of a crash | one test | every test sharing that browser in the worker | ## Moving the suite, in order 1. **Measure first.** Record the wall-clock split between launch and journey for a representative file. If launch is 20% of the run, the ceiling on this change is 20%. 2. **Hoist the browser.** One browser per worker process, launched once and reused. In Playwright Test this is what the built-in fixtures already do - you get it by using `page` rather than launching yourself. 3. **Isolate per test with a context.** Each test gets a new context and a new page; closing the context is the cleanup step that used to be a process exit. 4. **Delete the teardown that no longer applies.** Kill-the-browser hooks, orphan-process sweepers and profile-directory cleaners are usually dead weight afterwards. 5. **Re-measure and check flake, not just duration.** A faster suite that leaks state between tests has moved the cost, not removed it. ## What still forces a relaunch - A **different engine**, because that is a different browser binary. - **Different launch flags or `channel`**, because those are fixed when the process starts. - A **crash or hang** of the browser process, which takes every context in it down together. Anything scoped to cookies, storage, permissions, locale, viewport or credentials is context-level, not process-level, and does not justify a launch. ## The judgment the change demands - **Sharing a process concentrates risk.** One crash now fails a batch of tests rather than one. That is usually a good trade for the time saved, but it must be a decision, not a surprise - and it makes reruns and per-worker artefacts more important. - **Isolation is only as good as your discipline.** Reusing a context to save more milliseconds quietly reintroduces the cross-test coupling the old suite was avoiding with a sledgehammer. The whole point is that a fresh context is already cheap enough not to bother. - **Do not read the speed-up as a quality gain.** A legacy quote suite that was flaky because it depended on ordering will be flaky faster. Fix the coupling on the way through, while you are already touching the fixtures. - **Watch the resource ceiling instead.** With launches gone, the limiting factor becomes memory and CPU per worker; that is a different capacity question, and it is the one you now tune. ## Why the model is what makes this possible None of the above is a scheduling trick. It follows from the fact that the driver holds a persistent connection to a browser it started and can address that browser's internals directly: it can ask for a new isolated profile and get a handle back, at any moment, without a new process, a new binary or a new connection. Under a model where isolation is welded to a session lifecycle, the same requirement really does mean starting again.
- What new failure mode does sharing one browser across a worker's tests introduce?A shared blast radius. If the browser process crashes or hangs, every test still to run in that worker is affected, not just the one that triggered it. You mitigate it by keeping workers small enough that a restart is cheap, making sure the runner can recover the worker, and collecting artefacts per test so the crash is diagnosable rather than merely fatal.
- The suite got faster but two tests now interfere. Where would you look first?At anything that outlived a context. Shared state usually means a context or page reused across tests, credentials or storage seeded once at the top, or a service-side fixture the tests both mutate. The browser process itself carries almost nothing between contexts, so a leak is nearly always something the suite deliberately hoisted for speed.
saying these in an interview costs you the question
- Says a new browser is the only way to get isolation
- Reuses one context across tests to save more time
- Thinks contexts share cookies with each other
- Ignores that a browser crash now fails a whole batch
- Claims the speed-up also fixes order-dependent tests