StackInterview logoStackInterview icon

Explore

Interview Qn

Interview AI

Problems

Resume Builder

Quiz

Articles

DevKit

StackInterview

The complete platform to prepare for full-stack developer interviews - questions, AI mock interviews, coding practice, and guides.

Free to start

Platform

  • Interview Questions
  • Interview AI
  • Coding Problems
  • Company Tracks
  • Stack Quiz
  • JS Playground
  • Resume Builder

Guides

  • 50 Playwright Interview Questions 2026
  • Advanced Playwright Interview Questions and Answers (2026)
  • How to Format, Validate, and Convert JSON Online for Free (2026 Guide)
  • React 19 Server Components in 2026: Production Patterns for High-Performance Apps
  • Advanced Node.js Interview Questions and Answers (2026)
  • View all guides →

Company

  • About Us
  • Guides & Articles
  • FAQ
  • Contact
  • Pricing
  • Privacy Policy
  • Terms of Service

© 2026 StackInterview. Built for engineers, by engineers.

PrivacyTermsContact
All Articles
🎯Interview Prep17 min read

Advanced Playwright Interview Questions and Answers (2026)

26 advanced Playwright interview questions for senior QA and SDET roles - locator internals, test architecture at scale, CI/CD, tracing, and production triage scenarios.

Beginner Playwright prep covers locators and auto-waiting. Advanced rounds test something different: can you design a test architecture for 500+ specs, triage a suite that's flaky only in CI, and defend a migration off Selenium Grid? This guide covers locator internals, distributed execution, CI/CD architecture, and the production scenarios senior interviewers actually ask.

playwrightadvanced-playwrightinterview-questionsautomation-testingsdetqa-engineerplaywright-2026
On this page
  1. Advanced Playwright Interview Questions and Answers (2026)
  2. Tier 1 - Locator and Assertion Internals (Q1-Q6)
  3. Q1. What's the actual difference between `page.waitForSelector()` and `locator.waitFor()`?
  4. Q2. Walk through Playwright's full actionability and retry loop for a single `click()`.
  5. Q3. How do you interact with elements inside a Shadow DOM that `getByRole()` can't reach?
  6. Q4. What is `expect.poll()`, and when does a locator assertion fall short?
  7. Q5. How do you record and replay network traffic with HAR files?
  8. Q6. How do you build a custom polling helper for a condition Playwright doesn't natively wait on?
  9. Tier 2 - Test Architecture and Scale (Q7-Q13)
  10. Q7. Walk through Playwright Test Runner's architecture end to end.
  11. Q8. How do you scale Playwright execution across multiple machines, not just multiple workers?
  12. Q9. How would you get a 500+ test suite under a 10-minute CI budget?
  13. Q10. How do you design `BrowserContext` usage for hundreds of concurrent authenticated sessions?
  14. Q11. In a multi-tenant test architecture, what exactly does `Page` isolate versus `BrowserContext`?
  15. Q12. How do you build a resilient locator strategy for a data table that updates in real time?
  16. Q13. How would you architect a company-wide custom command library on top of Playwright?
  17. Tier 3 - CI/CD, Tooling, and Framework Decisions (Q14-Q20)
  18. Q14. A test fails in CI but passes every time locally. How do you debug it without reproducing it live?
  19. Q15. How has Playwright's tooling around component testing and debugging matured in recent releases, and what does that change architecturally?
  20. Q16. When is Component Testing *not* worth the investment over E2E?
  21. Q17. How do you integrate Playwright with BDD/Cucumber, and when is the overhead worth it?
  22. Q18. How do you design a CI strategy that runs Playwright across GitHub Actions and Azure DevOps without duplicating logic?
  23. Q19. How do you containerize Playwright so local runs match CI exactly?
  24. Q20. How do you integrate Playwright results with a test management tool like Jira, Zephyr, or Azure Test Plans?
  25. Tier 4 - Production Scenarios and Migration Decisions (Q21-Q26)
  26. Q21. A suite passes locally but is flaky specifically in CI. What's your triage order?
  27. Q22. How do you profile page performance beyond simple load time?
  28. Q23. How do you manage secrets across local dev, CI, and multiple cloud providers without leaking them?
  29. Q24. How do you design visual regression testing so it doesn't become noise at scale?
  30. Q25. A team wants to migrate an existing Selenium Grid suite to Playwright. How do you evaluate whether it's worth it?
  31. Q26. You're asked to design a Playwright test framework from scratch for a 50-engineer organization. What are the pillars?
  32. Frequently Asked Questions
  33. How is this different from a standard Playwright interview questions list?
  34. Do interviewers really ask migration questions like Selenium-to-Playwright?
  35. Is HAR replay a common interview topic?
  36. What's the single most important topic to prepare from this list?
Summarize with AI
ChatGPT
ChatGPT
Perplexity
Perplexity
Claude
Claude
Google AI
Google AI
Grok
Grok
Practice

Test your knowledge

Real interview questions asked at top product companies.

Practice Now
More Articles
Summarize with AI
ChatGPT
ChatGPT
Perplexity
Perplexity
Claude
Claude
Google AI
Google AI
Grok
Grok

This guide is built around that gap. It's organized into four tiers: locator and assertion internals, test architecture at scale, CI/CD and tooling decisions, and the production scenarios that separate a mid-level candidate from a senior one. Playwright now commands 45.1% adoption among QA professionals, ahead of Selenium at 22.1% (TestDino, 2026) - which is exactly why interviewers no longer stop at "what is a locator."

If the fundamentals need a refresher first, see Playwright interview questions and answers for the beginner-to-intermediate ground this guide builds on.

Dark-themed code editor showing a test suite open on a laptop screen, representing advanced Playwright test architecture
Dark-themed code editor showing a test suite open on a laptop screen, representing advanced Playwright test architecture

Tier 1 - Locator and Assertion Internals (Q1-Q6)

These questions probe whether you understand what's happening underneath Playwright's auto-waiting promise, not just that it exists. Interviewers ask them to filter candidates who've internalized the mental model from those who've memorized "Playwright auto-waits" as a slogan.

What interviewers actually ask at this level

Expect follow-ups to "why Playwright over Selenium" that dig into specific APIs: the gap between waitForSelector() and locator.waitFor(), when expect.poll() is the right tool instead of a locator assertion, and how to pierce a Shadow DOM the built-in selectors can't reach.


Q1. What's the actual difference between `page.waitForSelector()` and `locator.waitFor()`?

page.waitForSelector() is a legacy API from Playwright's early versions. It resolves a selector once and returns an ElementHandle - it doesn't retry the underlying action, and the handle can go stale if the DOM re-renders between the wait and your next action. locator.waitFor() is part of the modern Locator API: the locator re-queries the DOM on every use, so there's no handle to go stale, and it composes with the same actionability checks (attached, visible, stable, receives events) that every other locator action uses.

// Legacy - resolves once, handle can go stale after a re-render
const el = await page.waitForSelector('.status-badge');
await el.click(); // may fail if the DOM re-rendered in between

// Modern - re-queries fresh on every call, no stale handle risk
const badge = page.locator('.status-badge');
await badge.waitFor({ state: 'visible' });
await badge.click(); // re-resolves the DOM at click time

Interview tip: If you're still writing waitForSelector() in new test code, that's a signal to interviewers that your Playwright knowledge predates the Locator API. Reach for locator.waitFor() or, better, a locator assertion that already retries.


Q2. Walk through Playwright's full actionability and retry loop for a single `click()`.

Before any action executes, Playwright runs a checklist internally, re-evaluating on every animation frame until it passes or the timeout expires: the element must be attached to the DOM, visible (non-zero size, no display: none), stable (its bounding box hasn't moved in two consecutive frames), receives events (not obscured by another element at that point), and enabled (no disabled attribute). Web-first assertions (expect(locator).toBeVisible()) run the same underlying polling loop, which is why they don't need a manual wait either.

// This single call hides five checks running on a retry loop
await page.getByRole('button', { name: 'Confirm' }).click();

// Making the same checks explicit for a locator assertion
await expect(page.getByText('Order placed')).toBeVisible({ timeout: 10_000 });

Naming these five checks by name, unprompted, is what separates a candidate who's read the docs from one who's debugged a flaky click at 11 PM.


Q3. How do you interact with elements inside a Shadow DOM that `getByRole()` can't reach?

Playwright's built-in locators pierce open Shadow DOM automatically in most cases - getByRole() and getByText() already traverse shadow roots. For custom elements where that isn't enough, chain a CSS locator through the shadow boundary or fall back to a pierce/ selector, which crosses every shadow root in the chain without you needing to name each one.

// Chained locator - pierces one shadow boundary at a time
await page.locator('custom-datepicker').locator('button.next-month').click();

// pierce/ selector - crosses shadow boundaries automatically, useful for deep nesting
await page.locator('pierce/input[name="email"]').fill('qa@example.com');

Interview tip: Mention that most Shadow DOM "bugs" candidates report are actually closed shadow roots (mode: 'closed'), which Playwright genuinely cannot pierce - that's a framework limitation, not a locator mistake.


Q4. What is `expect.poll()`, and when does a locator assertion fall short?

Locator assertions retry against the DOM. expect.poll() retries against any async function you give it - a REST call, a database query, a message-queue check - polling until it returns a truthy match or the timeout expires. Use it when the thing you're actually waiting on lives outside the page, such as confirming a background job finished processing before asserting on the UI that reflects it.

// Waiting on a backend job that the UI doesn't reflect until it's done
await expect.poll(async () => {
  const res = await request.get(`/api/jobs/${jobId}`);
  return (await res.json()).status;
}, { timeout: 30_000 }).toBe('completed');

Q5. How do you record and replay network traffic with HAR files?

Playwright can capture every network request and response for a session into a HAR (HTTP Archive) file, then replay that file on later runs instead of hitting the real backend. This decouples UI tests from backend availability entirely - useful for testing against a third-party API with rate limits or an unstable staging environment.

// Record once against the real backend
const context = await browser.newContext({
  recordHar: { path: 'checkout-flow.har' },
});

// Replay on every subsequent run - no live backend needed
const context2 = await browser.newContext();
await context2.routeFromHAR('checkout-flow.har', { url: '**/api/**' });

Interview tip: HAR replay is distinct from route.fulfill() mocking - HAR captures real recorded traffic wholesale, while fulfill() requires you to hand-write each mock response. Interviewers ask this to see if you know when recorded fixtures beat hand-written mocks.


Q6. How do you build a custom polling helper for a condition Playwright doesn't natively wait on?

Sometimes the condition you need isn't a DOM state or a network response - it's an application-specific invariant, like "the WebSocket has received exactly 3 messages." Wrap it in a small retry loop that respects the same timeout-and-poll pattern Playwright uses internally, rather than reaching for waitForTimeout().

async function waitUntil(
  condition: () => Promise<boolean>,
  { timeout = 5000, interval = 100 } = {}
) {
  const deadline = Date.now() + timeout;
  while (Date.now() < deadline) {
    if (await condition()) return;
    await new Promise((r) => setTimeout(r, interval));
  }
  throw new Error(`Condition not met within ${timeout}ms`);
}

await waitUntil(async () => receivedMessages.length === 3);

Tier 2 - Test Architecture and Scale (Q7-Q13)

Once you clear locator internals, senior interviews pivot to architecture: how does a suite behave at 500 tests instead of 50? How do you isolate hundreds of concurrent authenticated sessions without launching hundreds of browsers?

What interviewers actually ask at this level

Expect whiteboard-style questions: sketch a Test Runner's moving parts, explain how you'd distribute execution across machines, and justify a BrowserContext strategy for a multi-tenant application under real concurrency.


Q7. Walk through Playwright Test Runner's architecture end to end.

The Test Runner has five cooperating pieces. The runner discovers spec files and builds the execution plan. Workers are isolated OS processes, each running a subset of tests with its own memory space - a crash in one worker doesn't take down the others. Reporters consume test results as they stream in and render them (HTML, JUnit, JSON, or custom). Hooks (beforeAll, beforeEach, fixtures) wire up and tear down state around tests. Trace Viewer sits outside the hot path, recording a full timeline artifact only when configured to, so it costs nothing when disabled.

Interview tip: The detail interviewers listen for is process isolation at the worker level - it's why one segfaulting browser doesn't fail your entire CI run, unlike a single-process test runner.


Q8. How do you scale Playwright execution across multiple machines, not just multiple workers?

Workers parallelize within one machine's CPU budget. Beyond that, distribute test files across separate CI runners or a dedicated execution grid, each running its own worker pool, then merge the resulting HTML/JSON reports into one artifact. Managed options (Microsoft Playwright Testing, BrowserStack, LambdaTest) and self-hosted grids both solve the same problem: turning "more machines" into "faster wall-clock time," not just "more parallelism per machine."

# GitHub Actions matrix - 4 machines, each running one shard
strategy:
  matrix:
    shard: [1, 2, 3, 4]
steps:
  - run: npx playwright test --shard=${{ matrix.shard }}/4

Q9. How would you get a 500+ test suite under a 10-minute CI budget?

Layer three techniques rather than reaching for one. First, shard the suite across parallel CI jobs (--shard=1/N) so wall-clock time drops roughly linearly with machine count. Second, separate API-only tests from UI tests and run them in different jobs - API tests typically run 5-10x faster and shouldn't share a queue with slower UI specs. Third, tag a smoke subset (@smoke) that runs on every push in under two minutes, and reserve the full regression suite for merges to main or a nightly run.

# Fast feedback on every push
npx playwright test --grep @smoke

# Full suite, sharded, only on merge to main
npx playwright test --shard=2/4

Q10. How do you design `BrowserContext` usage for hundreds of concurrent authenticated sessions?

Launching hundreds of full Browser instances is expensive and unnecessary. Launch a small pool of Browser processes (often just one per worker) and spin up a fresh BrowserContext per test - each context gets isolated cookies, storage, and cache at a fraction of the memory cost of a full browser. Pair that with pre-generated storageState files per test persona (admin, standard user, read-only) so login happens once during setup, not once per test.

// One browser, many isolated contexts - each test gets a clean session
const browser = await chromium.launch();

for (const persona of ['admin', 'standardUser', 'readOnly']) {
  const context = await browser.newContext({ storageState: `auth/${persona}.json` });
  const page = await context.newPage();
  // fully isolated session, reused login state, no fresh browser process
}

Q11. In a multi-tenant test architecture, what exactly does `Page` isolate versus `BrowserContext`?

DimensionPageBrowserContext
RepresentsOne tabOne isolated session (like an incognito window)
Cookies / storageShared with sibling pages in the same contextIsolated from every other context
Auth stateInherited from its contextOwns its own storageState
Cost to createCheap - reuse within a contextModerate - one per test is standard practice
Use caseMultiple tabs of the same session (e.g., testing a "open in new tab" link)Simulating a different user or tenant entirely

For multi-tenant apps specifically, one BrowserContext per tenant under test keeps tenant data from ever leaking into another tenant's session during a parallel run - a bug class that's much harder to catch with shared state.


Q12. How do you build a resilient locator strategy for a data table that updates in real time?

Static indexes (nth()) break the moment a row is inserted or removed mid-test. Anchor to content that's stable relative to the row's identity instead, then scope further locators inside that match.

// Fragile - breaks if row order shifts between action and assertion
await page.locator('tr').nth(3).getByRole('button', { name: 'Approve' }).click();

// Resilient - filters by a stable identifier, regardless of position
const row = page.getByRole('row').filter({ hasText: /Order #\d{5,}/ });
await row.getByRole('button', { name: 'Approve' }).click();

Q13. How would you architect a company-wide custom command library on top of Playwright?

Rather than every team hand-rolling login flows and common assertions, centralize them as a shared fixture package other teams extend. Structure it as composable fixtures (not static utility functions) so teardown ordering and dependency injection still work correctly, publish it as an internal npm package, and version it so breaking API changes don't silently break every consuming repo at once.

// shared-fixtures/index.ts - published internally, consumed by every team's repo
import { test as base } from '@playwright/test';

export const test = base.extend<{ loginAs: (role: string) => Promise<void> }>({
  loginAs: async ({ page }, use) => {
    await use(async (role: string) => {
      await page.goto('/login');
      await page.getByLabel('Role').selectOption(role);
      await page.getByRole('button', { name: 'Sign in' }).click();
    });
  },
});

For the broader async and dependency-injection patterns this design leans on, advanced Node.js interview questions covers the runtime internals that inform how these fixtures compose under the hood.


Tier 3 - CI/CD, Tooling, and Framework Decisions (Q14-Q20)

Staff-level interviews increasingly ask you to justify tooling and process decisions, not just demonstrate API knowledge. These questions test whether you can weigh tradeoffs under real organizational constraints - budget, existing infrastructure, team skill level.


Q14. A test fails in CI but passes every time locally. How do you debug it without reproducing it live?

Configure trace: 'on-first-retry' so a trace artifact only gets recorded when a test actually fails and retries - free of cost on the happy path, complete on the failure path. Download the trace from the CI artifact and open it with npx playwright show-trace. It reconstructs a full timeline: DOM snapshots, network requests, console logs, and screenshots at every step, so you're inspecting the exact CI-only state (different viewport, different timing, different environment variables) instead of guessing.

// playwright.config.ts
use: {
  trace: 'on-first-retry',
  screenshot: 'only-on-failure',
  video: 'retain-on-failure',
}

Interview tip: The instinct to say "just add waitForTimeout()" is exactly the answer that fails this question. Interviewers want to hear you reach for the trace before you reach for a wait.


Q15. How has Playwright's tooling around component testing and debugging matured in recent releases, and what does that change architecturally?

Recent Playwright releases have continued pushing two areas that matter for architecture decisions: component testing (@playwright/experimental-ct-*) has matured enough that some teams now use it to replace a meaningful slice of Jest/Vitest component suites with real-browser rendering, and debugging tooling (Trace Viewer, the VS Code extension) keeps closing the gap between "something failed" and "here's exactly why." The architectural implication: teams re-evaluating their testing pyramid should treat component tests as a third tier alongside unit and E2E, not a replacement for either.

Interview tip: Don't over-claim specific version numbers if you're not certain - say "recent versions" or "the current experimental component testing API" rather than guessing a release number. Interviewers care more that you track the ecosystem than that you memorize a changelog.


Q16. When is Component Testing *not* worth the investment over E2E?

Component testing mounts a single component in a real browser without a running app - fast, isolated, good for testing a component's props and events in the matrix of states it can be in. It's a poor fit when the bug class you actually care about is integration - how the component behaves wired into real routing, real API responses, and real sibling components. A design system's Button component is a great component-testing candidate. A checkout flow's payment step, where the bugs live in the handoff between components, isn't.

// Good component-testing candidate - isolated, prop-driven behavior
test('button shows spinner while loading', async ({ mount }) => {
  const button = await mount(<Button loading={true} label="Save" />);
  await expect(button.getByRole('status')).toBeVisible();
});

Q17. How do you integrate Playwright with BDD/Cucumber, and when is the overhead worth it?

playwright-bdd (or a custom Cucumber adapter) maps Gherkin Given/When/Then steps to Playwright step definitions, letting non-engineers author scenarios in plain language while engineers implement the underlying automation. The overhead - an extra abstraction layer, slower iteration, step-definition maintenance - is worth it specifically when product or QA stakeholders who don't write TypeScript need to read and approve test scenarios directly. For an all-engineering team, it's usually net overhead with no corresponding benefit.

Feature: Checkout
  Scenario: Successful payment
    Given I am on the checkout page
    When I submit valid payment details
    Then I should see an order confirmation

Q18. How do you design a CI strategy that runs Playwright across GitHub Actions and Azure DevOps without duplicating logic?

Keep the actual test invocation - Playwright config, sharding flags, reporter setup - in a shell script or npm script that both pipelines call identically. Let each CI platform's YAML handle only what's platform-specific: runner provisioning, secret injection, and artifact upload. This way, a change to how tests run doesn't require editing two divergent pipeline definitions.

// package.json - single source of truth both pipelines call
"scripts": {
  "test:ci": "playwright test --shard=$SHARD/$TOTAL_SHARDS --reporter=html,junit"
}

Q19. How do you containerize Playwright so local runs match CI exactly?

Use Microsoft's official mcr.microsoft.com/playwright image, pinned to a specific version tag - it ships with Chromium, Firefox, WebKit, and every OS-level dependency pre-installed, eliminating "works on my machine" drift caused by mismatched browser binary versions between a developer's laptop and the CI runner.

FROM mcr.microsoft.com/playwright:v1.49.0-jammy
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["npx", "playwright", "test"]

Interview tip: Pinning the version tag is the detail interviewers listen for - an unpinned :latest image silently upgrades browser versions on a rebuild and can flip a passing suite to failing with no code change.


Q20. How do you integrate Playwright results with a test management tool like Jira, Zephyr, or Azure Test Plans?

Export results in a format the tool's API accepts - typically JUnit XML or a custom JSON reporter - then push them via that tool's REST API as a post-test CI step. This closes the loop between "which automated test covers which manually written test case" and gives non-engineering stakeholders traceability without needing to read a Playwright HTML report.

// playwright.config.ts - JUnit output most test management tools can ingest
reporter: [
  ['junit', { outputFile: 'results/junit.xml' }],
  ['html', { open: 'never' }],
],
# CI step - push results to the test management tool's API after the run
curl -X POST "$TEST_MGMT_API/results" -H "Authorization: Bearer $TOKEN" \
  -F "file=@results/junit.xml"

Tier 4 - Production Scenarios and Migration Decisions (Q21-Q26)

This is where advanced interviews diverge sharply from beginner ones. Instead of "define X," interviewers describe a situation and ask how you'd respond. There's rarely one correct answer - what's being evaluated is your triage process and the tradeoffs you name out loud.


Q21. A suite passes locally but is flaky specifically in CI. What's your triage order?

PERSONAL EXPERIENCE -

In practice, CI-only flakiness almost always traces back to one of three causes: resource contention (CI runners have fewer CPU cores than a developer laptop, so timing-sensitive code that "just works" locally races under load), a headless-vs-headed rendering difference, or environment parity gaps (missing fonts, different locale, different viewport default). Checking resource contention first resolved the majority of CI-only flakiness we saw on a suite that was rock-solid on every engineer's machine.

1. Reproduce load conditions locally: npx playwright test --workers=1 to rule out contention 2. Compare playwright.config.ts use blocks for CI vs. local - viewport, locale, timezone often differ silently 3. Pull the trace from the CI artifact, not a local re-run - the local environment won't show the CI-specific state 4. Check for shared state leaking between parallel workers (a global counter, a shared test database row) 5. If genuinely non-deterministic, add retries: 2 in CI as a stopgap while root-causing, never as the fix itself


Q22. How do you profile page performance beyond simple load time?

Use page.evaluate() to pull the Navigation Timing and Resource Timing APIs directly from the browser, or attach to the Chrome DevTools Protocol for deeper metrics like layout shifts and long tasks. This surfaces regressions - a new render-blocking script, a ballooning bundle - that a simple "did the page load in under 3 seconds" assertion would miss entirely.

test('checkout page has no long tasks over 50ms', async ({ page }) => {
  await page.goto('/checkout');
  const longTasks = await page.evaluate(() =>
    performance.getEntriesByType('longtask').length
  );
  expect(longTasks).toBe(0);
});

Q23. How do you manage secrets across local dev, CI, and multiple cloud providers without leaking them?

Never commit real credentials, including in .env files used for local development - use .env.example with placeholder values instead. In CI, inject secrets through the platform's native secret store (GitHub Secrets, Azure Key Vault, AWS Secrets Manager) as environment variables at runtime, scoped to the minimum set of jobs that need them. Fail the run explicitly at startup if a required secret is missing, rather than letting a test fail confusingly downstream.

// global-setup.ts - fail fast and explicitly, not three tests later
const required = ['TEST_ADMIN_EMAIL', 'TEST_ADMIN_PASSWORD', 'API_BASE_URL'];
for (const key of required) {
  if (!process.env[key]) throw new Error(`Missing required secret: ${key}`);
}

Q24. How do you design visual regression testing so it doesn't become noise at scale?

Unscoped, full-page visual diffs generate false positives constantly - a single pixel of anti-aliasing or a dynamic timestamp fails the whole suite. Scope screenshots to stable components rather than full pages where possible, mask genuinely dynamic regions (timestamps, ads, user avatars) explicitly, and set a deliberate pixel-diff tolerance rather than demanding an exact match.

await expect(page).toHaveScreenshot('dashboard.png', {
  mask: [page.locator('.last-updated-timestamp')],
  maxDiffPixelRatio: 0.01,
});

Q25. A team wants to migrate an existing Selenium Grid suite to Playwright. How do you evaluate whether it's worth it?

The migration decision usually isn't about which tool is faster in isolation - it's about which infrastructure cost disappears. WebKit support in Playwright means Safari coverage no longer requires a separate device farm; built-in network interception means an existing mocking library (WireMock, an internal proxy) can potentially be retired. Weigh the migration against removed infrastructure, not just faster test runs, since that's usually the larger cost saving.

A pragmatic path: migrate new test suites to Playwright immediately, keep the existing Selenium Grid running for legacy coverage, and port high-value flaky suites first rather than attempting a big-bang rewrite. Full parity migrations that block on 100% coverage before cutting over tend to stall for months.


Q26. You're asked to design a Playwright test framework from scratch for a 50-engineer organization. What are the pillars?

There's no single correct architecture, but a defensible answer covers these pillars, in the order interviewers expect to hear them:

  • Isolation: one BrowserContext per test, storageState fixtures per user persona, no shared mutable test data
  • Structure: POM or a fixture-based equivalent, organized by feature domain (tests/checkout/, tests/admin/), not by test type
  • Speed: tiered execution - a @smoke subset on every push, sharded full regression on merge, nightly for the slowest end-to-end paths
  • Debuggability: trace on first retry, HTML reporter by default, CI artifacts uploaded only on failure to control storage cost
  • Governance: a shared internal fixture package so every team doesn't reinvent login and common assertions independently
  • Traceability: JUnit or equivalent output wired into whatever test management tool the org already uses

Deeper architectural reasoning - service boundaries, caching layers, how a shared fixture package should version and deploy - draws directly on 50 system design patterns, which senior interviewers expect you to apply outside of pure system design rounds too.


Frequently Asked Questions

How is this different from a standard Playwright interview questions list?

Standard guides cover fundamentals: locators, auto-waiting, POM, and basic CI setup - that ground is covered in Playwright interview questions and answers. This guide assumes that baseline and focuses on what changes at senior and staff level: distributed execution, CI architecture, and real production triage.

Do interviewers really ask migration questions like Selenium-to-Playwright?

At senior and staff levels, yes. A candidate who can only operate within an existing Playwright setup looks different from one who can justify why an org should adopt it, what it costs to migrate, and what infrastructure it lets you retire. Migration reasoning signals architectural ownership, not just tool fluency.

Is HAR replay a common interview topic?

It's less common than locators or CI, but it shows up in senior rounds focused on test reliability, since it directly answers "how do you keep UI tests fast and deterministic when a third-party API is involved." Knowing the distinction between HAR replay and route.fulfill() mocking is a strong signal of hands-on experience.

What's the single most important topic to prepare from this list?

BrowserContext architecture (Q10-Q11) and CI triage (Q21) come up most consistently, because they're the two places where "I know the API" and "I've operated this in production" diverge sharply. Pair those with the framework design synthesis question (Q26), which many senior loops end on.


Advanced Playwright interviews reward candidates who've operated a suite past the point where it "just worked" - scaled it past 500 tests, chased down CI-only flakiness, and made the call on whether a migration was worth the disruption. Work through each tier, be ready to defend a tradeoff out loud, and you'll be prepared for whichever tier a senior or staff loop opens with.

About the author: Abhijeet Kushwaha is a full-stack developer and automation engineer with hands-on experience building Playwright test suites for production applications. He writes about software testing, frontend engineering, and developer tools at Stack Interview.

Also see: Playwright interview questions and answers for the full beginner-to-advanced question set, and advanced Node.js interview questions for the runtime and architecture questions that come up alongside Playwright in senior SDET rounds.

More from Interview Prep

📁

Advanced Node.js Interview Questions and Answers (2026)

18 min read

🗄️

MySQL Interview Questions and Answers (2026)

20 min read

🌳

MongoDB Interview Questions and Answers (2026)

20 min read

Browse All Articles