QA Interview Hub · Knowledge base · Quizzes
Playwright
Architecture and isolation
Playwright architecture and test isolation
Playwright drives the browser from outside through protocols: CDP for Chromium and its own patches for Firefox and WebKit. Tests run in a Node.js process and send commands to the browser, so several tabs, windows, domains and contexts are available in one test. Chromium, Firefox and WebKit are supported, as well as the languages TypeScript/JavaScript, Python, Java and .NET.
The key hierarchy: Browser → BrowserContext → Page. A BrowserContext is an isolated "incognito session" with its own cookies, storage and cache, and creating one takes milliseconds. The test runner gives every test a new context by default, so tests don't share state with each other.
This is the main difference from Cypress: isolation is cheap, and parallelism is built in and free. Tests are distributed between workers, which are separate processes, each with its own browser.
What happens under the hood of the runner
When I run npx playwright test, the main process collects the list of tests and then starts workers, which are separate Node.js processes. Each worker imports the test files itself, launches its own browser and runs the tests it was given. That is why module-level global variables are not shared between workers: each has its own copy.
An important detail that is often not known: after a test fails, the worker is destroyed, and a new one is started for the following tests. This guarantees that a "broken" state doesn't leak into other tests. The consequence: beforeAll and worker fixtures run again in the new worker. If an expensive test user is created in beforeAll, it will be created again after every failure.
Retries work the same way on new workers: a test that failed is restarted in a new process with a clean browser.
- The main process: collects tests, distributes them, gathers results for the reporters.
- A worker: its own browser (worker scope), its own fixtures.
- A test: its own BrowserContext and Page (test scope).
Hence the rule: don't rely on the order of tests or on state in module variables. If test A wrote something to a variable, test B may run in another process and won't see it.
In an interview: The runner distributes tests between workers, which are separate processes, each with its own browser. After a test fails, the worker is restarted, so beforeAll may run several times. Because of this I don't keep shared state in module variables, and I get everything I need through fixtures.
Packages, browsers and channels
There are two packages: playwright is a library for browser automation without a runner, and @playwright/test is a runner with fixtures, assertions, reporters and parallelism. For tests you take the second one, and the library is for scripts, scraping or integration with another runner.
Browsers are not taken from the system, but downloaded for a specific Playwright version: npx playwright install. On CI on Linux you add system dependencies: npx playwright install --with-deps chromium. After the package is updated, the browsers must be reinstalled, otherwise there is an error about a missing executable.
Besides the bundled Chromium, Firefox and WebKit, you can run branded browsers through channel:
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'google-chrome', use: { ...devices['Desktop Chrome'], channel: 'chrome' } },
{ name: 'edge', use: { ...devices['Desktop Edge'], channel: 'msedge' } },
],
WebKit in Playwright is not the real Safari, but the WebKit engine, close to it. It catches differences in rendering and behaviour well, but it doesn't replace a final check on a real iOS device. This is an honest answer that is valued in an interview.
In an interview: For tests I use @playwright/test, and I install browsers with npx playwright install --with-deps, because they are tied to the package version. If it is important for the business specifically to have Google Chrome or Edge, I add projects with channel. I also understand that WebKit is an approximation of Safari, not a full replacement for a real device.