🏗️ Framework Architecture (SOLID + POM)

Framework Architecture (SOLID + POM): In Selenium, at this exact point you would answer "how does each thread get its own driver?" with DriverManager + ThreadLocal.

In Selenium, at this exact point you would answer "how does each thread get its own driver?" with DriverManager + ThreadLocal. In Playwright this question is never ASKED, because every worker already owns its own OS process and its own browser instance — isolation is a guarantee from the test runner, not something your code has to build. So why is "framework architecture" still a separate topic in Playwright — isn't everything automatic? Only isolation is automatic; every test writing `new LoginPage(page)`, the login flow being copy-pasted into 80 files, repeated setup steps like "close the cookie banner first" being rewritten in EVERY spec file — none of that is solved automatically. Second analogy: the custom fixtures you build with `test.extend` are a hotel's valet parking service — you do not carry the key (the page object) from hand to hand yourself (like ThreadLocal in Selenium); you just tell the front desk (the test function's parameter list) the name of what you need (`loginPage`), and the valet (the fixture resolver) brings the car (the object) to the door, ALREADY ready. Java comparison: this is exactly the philosophy of Spring's `@Autowired` / constructor injection — instead of manually `new`-ing an object, you tell a container "give me this", and the container resolves the dependency chain FOR you. QA context: in a Playwright project without fixtures, a 6-line setup ("log in, close the cookie banner, go to dashboard") gets repeated in EVERY one of 80 spec files; when the login flow changes, all 80 files must be scanned by hand. With a fixture, that setup lives in ONE file, and all 80 specs pick up the new behavior automatically, unchanged.

Build Your Playwright Framework Step by Step

The 4 pieces below are the BIG PICTURE of the architecture you are about to build piece by piece in this tab. They all start locked — the first time you correctly finish that step's "Try It Yourself" practice, that piece flips from locked to BUILT.

Fixture / Core Layer

🧭 Step 1 — The Big Picture: The Fixture Chain Mindmap

The same architecture is shown here from five angles: first the main flow (where the loginPage object comes from while a test runs), then the setup flow (from config to the fixture file, then to the spec), then parallel execution (why worker isolation removes the NEED for ThreadLocal), then the data-sharing scope (test/worker fixture scope + storageState), and finally a "does / does not" list for every file.

3️⃣ Parallel Execution — How Does Worker Isolation Replace ThreadLocal?

In Selenium, parallel execution runs multiple threads inside the SAME process — that is why ThreadLocal was needed, so "which thread uses which driver" never gets mixed up. In Playwright, since every worker is a SEPARATE process, that mix-up is impossible from the start: none of Worker-1's variables can leak into Worker-2's memory. This simplifies framework architecture but does NOT eliminate it — fixtures still need to be built correctly, because each worker still runs multiple tests inside itself, either sequentially or in parallel with `fullyParallel`.

4️⃣ Data-Sharing Scope — How Long Does a Fixture Live?

5️⃣ Who Does What? — File Responsibilities

test file (*.spec.ts)

playwright.config.ts

🎬 How Does the loginPage Fixture Reach a Test? (and the Worker-2 Contrast)

page fixture (built-in)