Playwright · Interview preparation · SDET

Playwright Interview Preparation Guide for Automation/SDET Engineers

Progressive interview preparation grounded in official documentation, from fundamentals to production-scale test engineering.

57 questions Easy → Intermediate → Advanced Print-friendly

This guide progresses from foundational Playwright knowledge to architecture, scale, and reliability topics expected in Automation Engineer and SDET interviews. The examples and terminology use Playwright Test for Node.js/TypeScript unless stated otherwise.

How to use this guide


Easy

1. What is Playwright Test, and which browsers does it support?

Direct answer: Playwright Test is an end-to-end test framework that includes a test runner, assertions, isolation, parallel execution, and debugging tools. It supports Chromium, Firefox, and WebKit.

Explanation: It can run headless or headed on Windows, Linux, and macOS. Its browser engines provide coverage for Chrome/Edge-family behavior, Firefox, and Safari-family behavior, while device descriptors can emulate selected mobile browser characteristics.

Official sources:

Back to top ↑

2. How do you install Playwright Test in a new or existing Node.js project?

Direct answer: For a guided setup, run npm init playwright@latest. In an existing project, install @playwright/test and then install the required browser binaries with npx playwright install.

Explanation: The initializer can create a config, sample tests, and a CI workflow. On Linux CI, npx playwright install --with-deps installs browser binaries and required operating-system dependencies.

Official sources:

Back to top ↑

3. What belongs in playwright.config.ts?

Direct answer: Put test-runner settings at the top level and browser/context behavior under use.

Explanation: Top-level settings include testDir, timeout, workers, retries, projects, reporter, and webServer. Settings such as baseURL, storageState, viewport, trace, video, and screenshot belong under use. Configuration can be global, project-specific, or overridden for a test group with test.use().

Official sources:

Back to top ↑

4. What is the basic structure of a Playwright test?

Direct answer: Import test and expect, declare a named test, receive fixtures such as page, perform actions, and assert the result.

Explanation: test() registers a test with the runner. The runner supplies only the requested fixtures, and Playwright's async actions and web assertions should be awaited.

import { test, expect } from '@playwright/test';

test('shows the dashboard', async ({ page }) => {
  await page.goto('/dashboard');
  await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
});

Official sources:

Back to top ↑

5. How do you run and filter tests from the command line?

Direct answer: Use npx playwright test for the suite, append a file or line for a subset, use -g for a title match, and use --project for one configured project.

Explanation: Common development flags include --headed, --ui, --debug, --workers, --retries, and --trace. The runner is headless and runs test files in parallel by default.

Official sources:

Back to top ↑

6. What is a locator?

Direct answer: A locator is a reusable query that finds an element when an action or assertion is performed.

Explanation: Locators are central to Playwright's auto-waiting and retry behavior. They re-resolve the current DOM element before each action, so they remain useful when a framework re-renders the page.

Official sources:

Back to top ↑

7. Which locator strategy should you prefer?

Direct answer: Prefer user-facing locators such as getByRole() with an accessible name, then other user-facing attributes or an explicit test-id contract.

Explanation: Role, label, placeholder, text, alt text, and title locators model how users perceive the page. Test IDs are stable explicit contracts when user-facing values are unsuitable. Long CSS/XPath chains couple tests to DOM implementation and are usually less resilient.

Official sources:

Back to top ↑

8. What does locator strictness mean?

Direct answer: An operation that requires one target fails if its locator matches multiple elements.

Explanation: Strictness catches ambiguous tests instead of choosing an arbitrary element. Refine the locator with role, accessible name, filtering, or composition. first(), last(), and nth() opt out but can silently select the wrong element after a UI change.

Official sources:

Back to top ↑

9. What are web-first assertions?

Direct answer: Web-first assertions are async Playwright matchers that repeatedly re-check page state until the expectation passes or its timeout expires.

Explanation: Examples include toBeVisible(), toHaveText(), toHaveURL(), and toHaveCount(). They are more reliable for asynchronous UIs than immediately reading a value and applying a non-retrying assertion. They must be awaited.

Official sources:

Back to top ↑

10. What is auto-waiting?

Direct answer: Before an action, Playwright waits for the target to satisfy the action's required actionability checks.

Explanation: For a click, Playwright verifies that the locator resolves to one element and that it is visible, stable, receives events, and is enabled. If the checks do not pass within the timeout, the action fails. This is not the same as waiting for every possible application condition; assertions should still verify expected outcomes.

Official sources:

Back to top ↑

11. Why should tests avoid fixed sleeps?

Direct answer: A fixed sleep waits for elapsed time rather than the state the test needs, making tests either slow or flaky.

Explanation: Prefer locator actions, web-first assertions, or a targeted event wait such as waitForResponse(). Playwright's auto-waiting covers actionability, while explicit state-based waits cover application-specific readiness.

Official sources:

Back to top ↑

12. What are the main built-in fixtures?

Direct answer: Common fixtures are page, context, browser, browserName, and request.

Explanation: page and context are isolated for each test. browser is shared for efficiency. request is an isolated APIRequestContext for direct HTTP calls. A fixture is requested by naming it in the test or hook parameter.

Official sources:

Back to top ↑

13. What hooks does Playwright Test provide?

Direct answer: It provides beforeEach, afterEach, beforeAll, and afterAll.

Explanation: Per-test hooks run around every test; all-hooks run once for their containing scope in a worker. Hooks are useful for straightforward setup, but reusable setup/teardown is often better represented by fixtures. Tests should not rely on another test having run first.

Official sources:

Back to top ↑

14. How does Playwright isolate tests?

Direct answer: It creates a fresh browser context, similar to a new incognito profile, for each test and supplies a page in that context.

Explanation: Cookies, local storage, and session storage do not leak between contexts. Contexts are cheap to create, so Playwright can keep the browser process available while preserving test independence and preventing cascading failures.

Official sources:

Back to top ↑

15. What is a Page Object Model (POM)?

Direct answer: A POM wraps a part of the application in a higher-level API that centralizes locators and reusable user flows.

Explanation: It can reduce duplication and localize maintenance when UI details change. Keep test intent and important assertions visible; do not turn a POM into a large catch-all abstraction that hides behavior or creates shared mutable state.

Official sources:

Back to top ↑

Intermediate

16. When should you create a custom fixture instead of using hooks?

Direct answer: Use a custom fixture when setup is reusable, has paired teardown, is needed only by some tests, or composes with other dependencies.

Explanation: Fixtures encapsulate setup and cleanup around await use(value), are lazy/on-demand, and can depend on other fixtures. Hooks remain suitable for simple local actions that genuinely apply to every test in a scope.

Official sources:

Back to top ↑

17. What is the difference between test-scoped and worker-scoped fixtures?

Direct answer: A test-scoped fixture is created per test; a worker-scoped fixture is created once per worker process and reused by tests running in that worker.

Explanation: Use test scope for mutable or isolation-sensitive resources. Use worker scope for expensive resources that can be safely shared, such as a service or worker-specific account. Declare worker scope with { scope: 'worker' } and clean it up after use.

Official sources:

Back to top ↑

18. What is the difference between browser, context, and page?

Direct answer: browser is the browser process connection, context is an isolated browser profile, and page is a tab or popup inside a context.

Explanation: One browser can host many isolated contexts, and one context can host many pages. Context-level settings such as cookies, permissions, emulation, and routes apply to pages within that context.

Official sources:

Back to top ↑

19. How do you test two users interacting in one scenario?

Direct answer: Create two browser contexts from the browser fixture and a page in each context.

Explanation: Separate contexts keep each user's cookies and storage independent while allowing both users to participate in the same test—for example, an admin and customer or two chat participants. Close manually created contexts during cleanup.

Official sources:

Back to top ↑

20. How do you handle a new tab or popup without a race?

Direct answer: Start waiting for the page or popup event before triggering the action, then await the event promise.

Explanation: Use context.waitForEvent('page') for any new page in the context, or page.waitForEvent('popup') for a popup opened by a particular page. Registering the wait first prevents missing an event that occurs immediately after the click.

Official sources:

Back to top ↑

21. How do you interact with content inside an iframe?

Direct answer: Use a frame locator, such as page.frameLocator(selector).getByRole(...), or obtain a Frame with page.frame().

Explanation: Page-level locators operate in the main frame. frameLocator() keeps locator-style retry behavior and is usually the convenient choice; a Frame object is useful when selecting by frame name or URL.

Official sources:

Back to top ↑

22. How do you wait for a network response caused by an action?

Direct answer: Create the page.waitForResponse() promise before the action, perform the action, and then await the promise.

Explanation: Match with a full-URL glob, regular expression, or predicate. This event-first pattern avoids a race and is useful when a specific backend response is the readiness condition.

Official sources:

Back to top ↑

23. How do you mock an API response?

Direct answer: Register a route before navigation or the triggering action and call route.fulfill() with the desired response.

Explanation: page.route() applies to one page; context.route() applies across pages in the context. A route can fulfill without reaching the backend, abort the request, continue it with modifications, or fetch and patch the real response.

Official sources:

Back to top ↑

24. How should authenticated state be reused safely?

Direct answer: Authenticate in a setup project, save storageState, and configure dependent projects to load it.

Explanation: The state can contain sensitive cookies and headers, so store it in a gitignored directory such as playwright/.auth. A shared account is appropriate only when parallel tests do not interfere through server-side state; otherwise use separate accounts.

Official sources:

Back to top ↑

25. What are Playwright projects?

Direct answer: Projects are logical groups of tests that run with different configuration.

Explanation: They commonly represent browsers and devices, but can also represent environments, authentication states, retries, timeouts, or test subsets. Run one with --project=<name>, and use project dependencies when setup must complete first.

Official sources:

Back to top ↑

26. What does device emulation cover?

Direct answer: Device descriptors configure browser characteristics such as user agent, viewport, screen size, touch support, and mobile behavior.

Explanation: Playwright can also emulate locale, timezone, geolocation, permissions, color scheme, offline mode, and JavaScript-disabled behavior. Emulation is useful browser-level simulation, but it is not a substitute for all real-device testing.

Official sources:

Back to top ↑

27. How does parallel execution work by default?

Direct answer: Playwright runs test files in parallel worker processes, while tests in one file run in declaration order by default.

Explanation: Workers are independent OS processes with identical environments. workers limits concurrency; fullyParallel or test.describe.configure({ mode: 'parallel' }) can permit test-level parallelism. After a failure, Playwright discards the worker to preserve a clean environment.

Official sources:

Back to top ↑

28. What do retries mean, and how are results classified?

Direct answer: Retries rerun failed tests up to a configured limit; Playwright classifies results as passed, flaky, or failed.

Explanation: Passed means success on the first run, flaky means failure followed by success on retry, and failed means all attempts failed. Retries are a diagnostic/safety mechanism, not a replacement for fixing nondeterministic tests.

Official sources:

Back to top ↑

29. Which Playwright timeouts should an engineer know?

Direct answer: Know the test timeout, expect timeout, global timeout, and lower-level action, navigation, hook, and fixture timeouts.

Explanation: The default test timeout is 30 seconds and includes the test body, fixture setup, and beforeEach. Auto-retrying assertions have a separate default of 5 seconds. Configure the narrowest relevant timeout instead of globally inflating all waits.

Official sources:

Back to top ↑

30. Which tools are available for local debugging?

Direct answer: Use UI Mode, the VS Code extension, Playwright Inspector, --debug, page.pause(), headed mode, and verbose API logs.

Explanation: UI Mode provides watch-style execution and time-travel inspection. Inspector can step through actions, inspect actionability logs, and edit locators. Trace Viewer is mainly for recorded post-run diagnosis, especially CI failures.

Official sources:

Back to top ↑

31. How do screenshots, videos, and traces differ?

Direct answer: A screenshot captures one visual state, video records the viewport over time, and a trace records actions plus rich diagnostic data such as DOM snapshots, logs, network, console, and attachments.

Explanation: Configure retention under use; common choices are screenshots only on failure and traces on the first retry. Videos are written when the context closes. For CI diagnosis, the official best-practices guide recommends traces over relying only on screenshots or videos.

Official sources:

Back to top ↑

32. How does Playwright support API testing?

Direct answer: Use the built-in request fixture or create an APIRequestContext to send HTTP(S) requests directly.

Explanation: API calls can test services, establish server-side preconditions before UI actions, or verify postconditions after them. Configure baseURL, headers, credentials, and proxy centrally; assert status and response payloads.

Official sources:

Back to top ↑

33. How can accessibility checks be added to Playwright tests?

Direct answer: Use the documented @axe-core/playwright integration, run AxeBuilder.analyze(), and assert that the relevant violations collection is empty.

Explanation: Scan the page only after it reaches the intended state. Scans can target a region or selected WCAG tags. Automated checks find only some accessibility defects, so they must complement manual assessment and inclusive user testing.

Official sources:

Back to top ↑

34. What is a practical baseline for running Playwright in CI?

Direct answer: Install dependencies with npm ci, install browsers and OS dependencies with npx playwright install --with-deps, run npx playwright test, and upload the report/artifacts.

Explanation: Use a supported Linux image or the official Playwright container. The docs recommend one worker on typical CI for stability, with sharding across jobs when broader parallel scale is needed. Set forbidOnly so committed focused tests fail CI.

Official sources:

Back to top ↑

35. Which reporters should an SDET understand?

Direct answer: Understand terminal reporters (list, line, dot), human-readable HTML, machine-readable JSON/JUnit, GitHub annotations, and blob reports for merging sharded output.

Explanation: Multiple reporters can run together. A common setup uses concise console output plus HTML for investigation and JUnit for CI integration. Custom reporters implement the Playwright Reporter API.

Official sources:

Back to top ↑

Advanced

36. How does fixture lifecycle and dependency ordering work?

Direct answer: Playwright resolves only fixtures requested by a test or its dependencies, sets dependencies up first, and tears them down in reverse order after await use().

Explanation: This makes fixtures lazy and composable. Test-scoped fixtures run around a test; worker-scoped fixtures surround all applicable tests in a worker. Automatic fixtures opt in with { auto: true }, and fixture-specific timeouts can isolate slow resource setup from the test timeout.

Official sources:

Back to top ↑

37. How should authentication be designed for parallel tests that mutate server state?

Direct answer: Allocate a separate account or authenticated state per parallel worker rather than sharing one account across all workers.

Explanation: A worker-scoped fixture can use parallelIndex to acquire a unique account, authenticate once, save worker-specific state, and override storageState for tests in that worker. Account uniqueness must also account for simultaneous runs by different developers or CI jobs.

Official sources:

Back to top ↑

38. Why are project dependencies generally preferable to a basic globalSetup for test setup?

Direct answer: A setup project participates in the normal test model, so it can use fixtures, produce traces, appear in reports, and be retried; dependent projects wait for it to pass.

Explanation: globalSetup remains available as a function run before the suite, but project dependencies provide better visibility and integration with Playwright tooling. Use teardown projects when cleanup must run after dependent projects.

Official sources:

Back to top ↑

39. What are the main network-routing operations?

Direct answer: route.fulfill() supplies a response, route.continue() sends the request—optionally modified—route.abort() blocks it, and route.fetch() obtains the real response so it can be patched.

Explanation: Register routes before requests begin. Context routes cover pages and popups in that context. URL globs must match the entire URL; use regular expressions or predicates for more complex matching. If Service Workers hide events from native routing, the docs advise blocking Service Workers for that scenario.

Official sources:

Back to top ↑

40. When is HAR-based mocking useful, and what are its matching rules?

Direct answer: HAR replay is useful when a test needs a recorded set of deterministic network responses rather than many hand-written route handlers.

Explanation: Record or update a HAR, commit the intended test artifact, and replay it with routeFromHAR(). Replay matches URL and method strictly; POST requests also match payload strictly, and the best header match is selected when several entries qualify.

Official sources:

Back to top ↑

42. How does sharding differ from local parallelism?

Direct answer: Local parallelism uses worker processes on one machine; sharding partitions the suite across multiple independent machines or CI jobs.

Explanation: Invoke each shard with --shard=x/y. With fullyParallel, Playwright can balance individual tests across shards; otherwise it assigns whole files, so uneven file sizes can create uneven shards.

Official sources:

Back to top ↑

43. How do you produce one report from many shards?

Direct answer: Generate a blob report in every shard, collect all blob archives into one directory, and run npx playwright merge-reports --reporter html <directory>.

Explanation: Blob reports retain test results and attachments and are designed for later merging. Keep environments consistent, or tag/disambiguate different environments and provide merge configuration when paths differ across operating systems.

Official sources:

Back to top ↑

44. What happens to workers and hooks after a test failure?

Direct answer: Playwright discards the failed worker process and starts a clean worker; applicable afterAll and then beforeAll hooks run around that transition.

Explanation: With retries enabled, the new worker retries the failed test before continuing. This protects healthy tests from contaminated process/browser state, but it means worker and all-hook setup must tolerate being performed again.

Official sources:

Back to top ↑

45. When should serial mode be used?

Direct answer: Use serial mode only when tests are intentionally dependent and cannot reasonably be made independent.

Explanation: In a serial group, a failure skips subsequent tests, and retries rerun the whole group. Independent tests are easier to isolate, parallelize, shard, retry, and debug, so the official guidance favors independence.

Official sources:

Back to top ↑

46. How should timeout failures be diagnosed instead of simply raising every timeout?

Direct answer: Identify which budget expired and inspect its call log/trace to determine the unmet condition.

Explanation: A test timeout, expect timeout, action timeout, navigation timeout, hook timeout, fixture timeout, and global timeout have different scopes. Raising a narrow expectation or fixture timeout can be valid; globally increasing timeouts often conceals incorrect readiness conditions, resource contention, or a bad locator.

Official sources:

Back to top ↑

47. What trace policy gives useful CI evidence without excessive overhead?

Direct answer: A strong default is retries on CI with trace: 'on-first-retry'.

Explanation: It captures a rich artifact for a reproduced failure while avoiding the cost of tracing every successful test. If diagnosing first-attempt-only failures, retain-on-failure or a targeted --trace on run may be more suitable. Trace Viewer exposes the timeline, DOM snapshots, action logs, network, console, source, and attachments.

Official sources:

Back to top ↑

48. How do expect.poll() and expect(...).toPass() differ from locator assertions?

Direct answer: Locator assertions retry a specific page-facing matcher; expect.poll() repeatedly evaluates a function, while toPass() retries a block containing one or more assertions.

Explanation: Use locator assertions first for DOM state. Use polling for eventually consistent values such as an API status. Use toPass() when a multi-step assertion block must eventually succeed, and configure its timeout explicitly because its default timeout behavior differs from ordinary expect configuration.

Official sources:

Back to top ↑

49. How do you build resilient compound locators?

Direct answer: Start from a user-facing anchor, then narrow with chaining, filter({ hasText, has, hasNot }), or locator and()/or() composition.

Explanation: Scope to a stable container such as a list item or dialog and then locate the control within it. This expresses relationships users can perceive and avoids positional selectors. Ensure alternatives used with or() do not create a strictness violation when both are visible.

Official sources:

Back to top ↑

50. What is the correct pattern for any event triggered by an action?

Direct answer: Register the event wait first without awaiting it, trigger the action, then await the event promise.

Explanation: This applies to popups, downloads, responses, requests, dialogs, and similar fast events. Waiting only after the action introduces a race because the event may already have fired.

Official sources:

Back to top ↑

51. How should an advanced POM and fixture architecture divide responsibilities?

Direct answer: Let page/component objects expose domain-level UI operations and locators; let fixtures construct those objects and own environmental setup/teardown; let tests express scenarios and business assertions.

Explanation: This combines the official POM goal—centralized selectors and reusable high-level operations—with fixtures' lazy dependency lifecycle. Avoid global page objects and shared mutable state. Keep abstractions cohesive so a UI change has a localized impact and a failed test remains understandable from its steps.

Official sources:

Back to top ↑

52. How should test data be designed for parallel and repeatable execution?

Direct answer: Give tests independent data and accounts, create server state through APIs when practical, and clean up through fixture teardown or isolated backend mechanisms.

Explanation: Browser contexts isolate client state, not shared database records. Unique worker/test identifiers prevent collisions; API setup is often faster than UI setup. Tests should be runnable alone, in any order, under retries, and across shards.

Official sources:

Back to top ↑

53. What can automated accessibility testing prove?

Direct answer: It can prove only that the configured automated rules found no violations in the scanned state; it cannot prove full accessibility or WCAG conformance.

Explanation: Many issues require keyboard, screen-reader, cognitive, visual, and inclusive-user evaluation. Keep suppressions narrow, scan dynamic states after interactions, and attach full results for diagnosis. Avoid snapshotting an entire axe result object because implementation details make it fragile.

Official sources:

Back to top ↑

54. How do you choose CI workers, projects, and shards without creating flakiness?

Direct answer: Treat projects as coverage dimensions, workers as per-machine concurrency, and shards as cross-machine distribution; tune each against resource limits and test isolation.

Explanation: Start with stable resource allocation—the CI guide recommends one worker in common CI environments—then use shards for throughput. Increase workers only on sufficiently powerful agents and only after eliminating shared-state conflicts. Use blob reports and traces so distributed failures remain diagnosable.

Official sources:

Back to top ↑

55. What principles distinguish a maintainable Playwright suite?

Direct answer: Test user-visible behavior, use resilient locators and web-first assertions, isolate tests and data, centralize configuration, and introduce abstractions only where they clarify domain intent.

Explanation: Avoid testing third-party systems you do not control; mock their boundary where appropriate. Keep tests independent, use API setup for speed when it does not undermine the purpose of the test, collect traces for failures, and remove the root cause of flaky tests rather than normalizing retries.

Official sources:

Back to top ↑

56. How do you investigate a flaky Playwright test?

Direct answer: Reproduce the failure, collect evidence from both passing and failing runs, isolate the changing variable, fix the root cause, and prove the fix with repeated execution. Retries can expose flakiness, but they are not the fix.

A practical daily workflow:

  1. Confirm the pattern. Run the test repeatedly with --repeat-each, first in its normal project and then alone. Record whether it fails only in CI, under parallel load, or in one browser.
  2. Inspect evidence. Open the Trace Viewer and compare a failed run with a passing run. Check the action log, DOM snapshot, network activity, console messages, screenshots, and timing.
  3. Narrow the cause. Temporarily run with one worker and stable test data. Look for ambiguous locators, missing await, fixed sleeps, an event listener registered after its action, shared accounts, slow APIs, overlays, animations, or third-party dependencies.
  4. Fix the cause. Use resilient locators and web-first assertions, register event waits before triggering actions, isolate browser contexts and data, and mock an external boundary when the real integration is not what the test is meant to verify.
  5. Prove stability. Repeat the test locally and in CI under normal parallelism. Keep traces on the first retry for future diagnosis, and document the cause rather than simply increasing timeouts.

Example: A checkout test sometimes timed out after clicking “Place order.” The trace showed that the response completed before waitForResponse() was registered. Creating the response promise before the click removed the race; repeated parallel CI runs then confirmed the fix.

Official sources:

Back to top ↑

57. What challenges have you faced during test automation, and how did you handle them?

Direct answer: Give one or two real examples using challenge, investigation, action, and measurable outcome. Strong answers show engineering judgment instead of only naming tools.

Common daily-life challenges:

Sample interview answer: “Our parallel checkout tests reused one account, so one test occasionally consumed another test’s cart. I used traces to confirm the shared-state conflict, created a worker-scoped account fixture, seeded each cart through the API, and added cleanup. The suite became independently repeatable and the CI failure rate dropped. I kept retries as a diagnostic signal, not as the solution.” Adapt this structure to an experience you can defend with details.

Official sources:

Back to top ↑

Rapid review checklist

Before an interview, be able to explain and sketch:


Original content and license note

This interview guide is newly authored original educational content and may be shared, adapted, and reused with attribution to this guide's author or repository. It is not copied from or endorsed by Microsoft or the Playwright project. Playwright names and trademarks remain the property of their respective owners. Linked Playwright documentation, code samples, logos, and other first-party materials remain subject to their owners' copyright, trademark, and applicable license or website terms. Readers should consult the linked official sources for the current authoritative behavior.