Test Frameworks
Playwright
Auto-waiting, locators, the page/context/browser model, fixtures, network interception, parallelism, and how Playwright differs from Selenium — with rapid-fire Q&A.
01What Playwright Is
Playwright is a modern end-to-end testing framework from Microsoft. It drives Chromium, Firefox, and WebKit through a single API, talks to browsers over the DevTools/CDP-style protocol rather than the WebDriver wire protocol, and ships official bindings for C#, JavaScript/TypeScript, Python, and Java.
The headline advantage over Selenium: a single process talking to the browser over a persistent connection, with auto-waiting built into every action.
- Cross-browser via one API (Chromium, Firefox, WebKit).
- Auto-waiting and web-first assertions reduce flakiness.
- Built-in network interception, tracing, video, and screenshots.
- Fast parallel execution out of the box.
02Browser / Context / Page
A single browser instance. Expensive to launch — you reuse it across tests.
An isolated session inside the browser — its own cookies, storage, and cache. Like a fresh incognito profile. Cheap to create, so each test gets its own context for isolation. This is how Playwright achieves clean state without relaunching the browser.
A single tab within a context. Most interactions happen here.
03Locators & Auto-Waiting
A Locator is a lazy, re-queried handle to an element — it re-resolves the DOM every time you act on it, which avoids stale-element problems.
Recommended, user-facing locators (in priority order):
GetByRole— by ARIA role + accessible name; most resilient.GetByLabel,GetByPlaceholder,GetByText.GetByTestId— stabledata-testidhooks.- CSS / XPath as a fallback.
Auto-waiting: before acting, Playwright waits for the element to be attached, visible, stable, enabled, and able to receive events — so explicit waits and sleep() are rarely needed.
Web-first assertions (Expect(locator).ToBeVisibleAsync()) auto-retry until the condition holds or times out — no manual polling.
await page.GetByRole(AriaRole.Button, new() { Name = "Sign in" }).ClickAsync();
await Expect(page.GetByText("Welcome")).ToBeVisibleAsync();04Network Interception & Mocking
Playwright can observe and modify network traffic, which is powerful for isolating the UI from flaky backends.
page.RouteAsync— intercept a URL pattern and fulfil, modify, or abort the request.- Stub an API to return fixed JSON so a UI test is deterministic.
- Wait for a specific response with
page.WaitForResponseAsync.
await page.RouteAsync("**/api/users", async route =>
await route.FulfillAsync(new() { Status = 200, Body = "[]" }));05Fixtures, Config & Auth Reuse
- Storage state — log in once, save cookies/localStorage to a file, and load it into new contexts so tests skip the login UI. Big speed win.
- Config — base URL, browser projects, timeouts, retries, trace/video settings centralized (in C# via fixtures/runsettings, or the JS
playwright.config). - Projects — run the same suite across multiple browsers / viewports.
storageState, and reuse it — the equivalent of seeding a logged-in session instead of clicking through login per test.06Parallelism & CI
Playwright runs tests in parallel by default using multiple worker processes; each worker gets its own browser/context, so isolation is preserved. Context-level isolation is exactly what makes safe parallelism possible.
- Workers scale to CPU cores; tune for the CI runner.
- Retries for flaky tests, configured centrally.
- Trace Viewer — record a trace on failure/first-retry; it captures DOM snapshots, network, and console for post-mortem debugging without re-running.
- Sharding splits the suite across CI machines.
07Debugging & Tooling
- Codegen — records your clicks into a test script with good locators.
- Trace Viewer — the main triage tool; step through a failed run frame by frame.
- UI Mode / headed + slowmo for live observation.
- Auto screenshots and video on failure.
08Rapid-Fire Q&A
Reveal each answer to self-check, then test yourself with the quiz.
How does Playwright avoid flakiness?
Auto-waiting on every action (attached, visible, stable, enabled) plus web-first assertions that auto-retry until the condition holds or times out.
Browser vs Context vs Page?
Browser = the instance (reused); Context = isolated session with its own cookies/storage (one per test); Page = a tab.
Why prefer GetByRole over CSS?
It matches how users and assistive tech perceive the page, so it's resilient to markup changes and encourages accessible UIs.
How do you reuse login across tests?
Authenticate once, save storageState (cookies + localStorage), load it into new contexts so tests skip the login flow.
How does Playwright handle parallelism?
Multiple worker processes, each with isolated browser context; configured by worker count and shardable across CI machines.
Playwright vs Selenium, briefly?
Single API over a persistent CDP-style connection with built-in auto-wait, network mocking, and tracing — vs Selenium's WebDriver protocol where you assemble waits and tooling yourself.
How do you mock an API in a UI test?
page.RouteAsync to intercept the request and fulfil it with controlled data, making the test deterministic.
What's the Trace Viewer?
A post-mortem tool that records DOM snapshots, network, and console per step so you debug a failed run without reproducing it.