Testing / Playwright Interview questions
1. What is Playwright?
Playwright is an open-source end-to-end testing and browser automation framework built by Microsoft, first released in 2020. It drives Chromium, Firefox, and WebKit through one API, so the same script runs across all three engines without rewriting selectors or logic. Instead of going through the...
2. What are the supported browsers in Playwright?
Playwright ships with three browser engines, which together cover almost every major browser a user might have installed. Engine Represents Chromium Google Chrome, Microsoft Edge Firefox Mozilla Firefox WebKit Apple Safari Playwright also supports launching the actual branded builds of Google Chr...
3. What are the supported programming languages in Playwright?
Playwright officially supports four languages, each with a first-class API maintained directly by the Playwright team rather than a community wrapper. JavaScript / TypeScript - the original and most actively developed binding, paired with the @playwright/test runner. Python - available as both a ...
4. How do you install Playwright?
The fastest path is the official scaffolding command, which sets up a ready-to-run project in one step: npm init playwright@latest This installs @playwright/test , downloads the Chromium, Firefox, and WebKit browser binaries, and generates a playwright.config.ts , a sample test, and an optional G...
5. What is the purpose of the Playwright Test Runner?
Playwright Test ( @playwright/test ) is a test runner built specifically around Playwright's automation capabilities, rather than a generic runner Playwright was bolted onto afterward. It provides test isolation by giving every test a fresh browser context, parallel execution across multiple work...
6. What are locators in Playwright?
A locator represents a way to find one or more elements on the page at any given moment - it's a strategy, not a snapshot. Creating a locator doesn't query the DOM immediately; the query only runs when an action like .click() or an assertion is actually performed. const button = page.getByRole( '...
7. How do you use the page.goto() method?
page.goto(url, options) navigates the current page to a given address and returns the main resource's response object once navigation completes. await page. goto ( 'https://example.com' , { waitUntil : 'domcontentloaded' , timeout : 30000 }); The waitUntil option controls when navigation is consi...
8. Define auto-waiting in Playwright?
Auto-waiting means Playwright automatically waits for an element to be actionable before performing an interaction, instead of requiring a manual sleep() or explicit wait call in the test code. Before an action like click() or fill() runs, Playwright performs a series of actionability checks on t...
9. Describe the Playwright Inspector?
The Playwright Inspector is a graphical debugging tool that pauses a running test and lets you step through it action by action, rather than reading logs after the fact. It's launched by setting the PWDEBUG=1 environment variable, or passing --debug to the test command: PWDEBUG=1 npx playwright t...
10. List the different types of locators in Playwright?
Playwright encourages user-facing, role-based locators over brittle CSS/XPath selectors wherever possible. Locator Matches by getByRole() ARIA role and accessible name getByText() Visible text content getByLabel() Associated form label getByPlaceholder() Input placeholder text getByAltText() Imag...
11. What is a fixture in Playwright?
A fixture is a reusable, self-contained piece of setup and teardown logic that Playwright Test injects into a test function as a parameter, rather than something the test author has to instantiate manually. test( 'shows dashboard' , async ({ page }) => { await page. goto ( '/dashboard' ); }); Her...
12. How do you take a screenshot in Playwright?
The most direct way is calling screenshot() on the page or on a specific locator: await page.screenshot({ path : 'full.png' , fullPage : true }); await page.getByRole( 'heading' ).screenshot({ path : 'heading.png' }); The fullPage: true option captures the entire scrollable page rather than just ...
13. What is the Trace Viewer in Playwright?
The Trace Viewer is a post-mortem debugging tool that replays exactly what happened during a test run, using a single recorded trace.zip file. It captures a DOM snapshot, screenshot, network activity, and console logs for every action, and lets you scrub through them like a timeline rather than g...
14. How do you use codegen in Playwright?
codegen is a CLI tool that opens a real browser alongside the Inspector, records your clicks, typing, and navigation, and writes them out as working test code in real time. npx playwright codegen https://example.com As you interact with the page, Playwright picks resilient locators (preferring ro...
15. What are assertions in Playwright?
Assertions verify that the application is in an expected state, and Playwright provides two kinds. Web-first assertions, written as expect(locator)... , automatically retry until the condition becomes true or a timeout is reached, which matches how real UIs update asynchronously. await expect(pag...
16. What is the difference between Playwright and Selenium?
Both automate browsers, but they take different architectural approaches, and that shapes most of the practical differences developers run into. Playwright Selenium Talks directly to the browser over its own protocol Talks to the browser through the WebDriver protocol Built-in auto-waiting for ac...
17. How does Playwright handle multiple tabs and windows?
Each new tab or window opened from the page - via a link with target="_blank" or a window.open() call - fires a 'page' event on its parent BrowserContext . Playwright doesn't switch focus automatically like some tools; instead, you capture the new page object explicitly. const [newPage] = await P...
18. What is the difference between page.click() and locator().click()?
page.click(selector) is a shorthand that finds the element and clicks it in one step, but it doesn't retain any reference afterward - it's essentially fire-and-forget on a raw selector string. // Shorthand, no persisted reference await page.click( '#submit' ); // Locator-based, recommended const ...
19. How do you handle iframes in Playwright?
Playwright avoids the manual "switch into frame, then switch back" pattern that other tools require. Instead, page.frameLocator() scopes a locator chain to the contents of a specific iframe, and you can immediately query inside it. const frame = page.frameLocator( '#payment-iframe' ); await frame...
20. What is the difference between expect().toBeVisible() and isVisible()?
Both check visibility, but they're built for different purposes and behave very differently under the hood. expect(locator).toBeVisible() locator.isVisible() Retries until true or timeout Checks once, immediately Throws a descriptive error on failure Returns a plain boolean, never throws Meant to...
21. How does Playwright differentiate retry behavior between actions and assertions?
Actions like click() or fill() retry against a fixed set of actionability checks (attached, visible, stable, enabled, receives events) and stop as soon as all of them pass, then perform the action exactly once. Their retry loop is really a "wait until ready" loop, governed by the action's own tim...
22. What is the purpose of browser contexts in Playwright?
A BrowserContext is an isolated browser session - its own cookies, local storage, cache, and permissions - created from a single launched Browser instance without the overhead of starting a whole new browser process. const browser = await chromium.launch(); const context = await browser.newContex...
23. How do you mock API responses in Playwright?
page.route() intercepts network requests matching a URL pattern and lets you fulfill them with custom data instead of hitting the real backend. await page.route( '**/api/users' , async (route) => { await route.fulfill({ status : 200 , contentType : 'application/json' , body : JSON.stringify([{ id...
24. What is the difference between soft assertions and hard assertions in Playwright?
A regular ("hard") assertion stops the test immediately the moment it fails - any code after it never runs. Hard assertion Soft assertion expect(locator).toBeVisible() expect.soft(locator).toBeVisible() Test stops at first failure Test continues after failure One failure reported All soft failure...
25. How do you run tests in parallel in Playwright?
Playwright Test parallelizes by default, splitting test files (not individual tests within a file, unless configured) across multiple worker processes, each with its own browser instance. // playwright.config.ts export default defineConfig({ workers : 4 , fullyParallel : true , }); The workers op...
26. What is the difference between test.beforeEach and test.beforeAll?
Both are setup hooks, but they run at different scopes within a test file. test.beforeEach test.beforeAll Runs before every single test in the file/describe block Runs once before all tests in the file/describe block Receives per-test fixtures like page Runs in a worker-scoped context, not tied t...
27. How do you handle file uploads in Playwright?
Playwright interacts with the native file input directly, without needing to drive the operating system's file picker dialog. await page.getByLabel( 'Upload resume' ).setInputFiles( 'resume.pdf' ); // Multiple files await page.getByLabel( 'Attachments' ).setInputFiles([ 'a.png' , 'b.png' ]); // C...
28. How do you handle authentication state across tests in Playwright?
Rather than logging in through the UI at the start of every test - which is slow and repeated hundreds of times - Playwright supports saving authenticated browser state once and reusing it. // auth.setup.ts - runs once await page. goto ( '/login' ); await page.getByLabel( 'Email' ).fill( 'user@ex...
29. What is the difference between waitForSelector and waitForLoadState?
These wait for two different things, and confusing them is a common source of either flaky or unnecessarily slow tests. waitForSelector waitForLoadState Waits for a specific element to reach a state (attached/visible) Waits for the page as a whole to reach a load milestone Element-scoped Page-sco...
30. How do you generate an HTML report in Playwright?
The HTML reporter is built in and just needs to be enabled in the config: // playwright.config.ts export default defineConfig({ reporter : 'html' , }); After a test run, this produces a self-contained report in the playwright-report folder, showing pass/fail status per test, execution time, and -...
31. What is the difference between headless and headed mode?
These control whether the automated browser actually renders a visible window while a test runs. Headless Headed No visible browser UI Full visible browser window Generally faster, lower resource use Slightly slower, more resource use Default for CI pipelines Common for local debugging Playwright...
32. How do you debug a failing Playwright test?
Playwright provides several layered tools rather than forcing you to rely on console logs alone. npx playwright test --debug # opens the Inspector, step-by-step npx playwright test --ui # opens the interactive UI mode npx playwright show-trace trace.zip # replays a recorded run UI mode is often t...
33. What are Playwright's API testing capabilities?
Beyond browser automation, Playwright includes an APIRequestContext for making direct HTTP requests, without launching a browser at all. const response = await request.post( '/api/login' , { data : { email : 'a@b.com' , password : 'secret' }, }); expect(response.status()).toBe( 200 ); const body ...
34. How do you handle elements that load dynamically or asynchronously?
Because locators are lazy and auto-retrying, the usual recommendation is simply to act on the locator directly rather than manually polling for the element first. // No manual wait needed - the locator retries internally await page.getByText( 'Results loaded' ).waitFor(); await page.getByRole( 'r...
35. What is the difference between Playwright's expect and Jest's expect?
Playwright Test's expect is a superset built on the same familiar matcher syntax as Jest's, but extended specifically for asynchronous UI state. Playwright's expect Jest's expect Adds web-first matchers: toBeVisible, toHaveText, toHaveScreenshot General-purpose value matchers: toBe, toEqual, toCo...
36. Explain the internal working of Playwright's browser automation?
Rather than driving browsers through the WebDriver protocol like Selenium, Playwright ships small, patched builds of Chromium, Firefox, and WebKit and talks to each one over its own native automation protocol - DevTools Protocol-derived for Chromium, and dedicated protocols the Playwright team bu...
37. Explain the execution flow of a Playwright test?
A Playwright Test run moves through several distinct phases, from config resolution down to reporting, for every worker process. flowchart TD A[Load playwright.config.ts] --> B[Resolve projects and fixtures] B --> C[Spawn worker processes] C --> D[Launch browser per worker] D --> E[Create isolate...
38. Why is Playwright generally faster than Selenium?
Several architectural choices compound to make Playwright suites faster in practice, not just one single feature. First, its direct protocol connection to the browser avoids the extra network hop and JSON wire protocol overhead of WebDriver's HTTP-based command model, so each command round-trip i...
39. When should you use component testing in Playwright?
Playwright Component Testing mounts an individual UI component (React, Vue, Svelte) in isolation inside a real browser, rather than rendering the whole application through routing and full page loads. import { test, expect } from '@playwright/experimental-ct-react' ; import { Counter } from './Co...
40. How can you optimize Playwright test execution time?
Several practical levers reduce suite runtime, and they're most effective combined rather than applied one at a time. Increase parallel workers and set fullyParallel: true so both files and individual tests spread across CPU cores. Reuse authentication state via storageState instead of logging in...
41. How do you troubleshoot flaky tests in Playwright?
Start by reproducing the failure with a trace rather than guessing - enabling trace: 'on-first-retry' captures exactly what happened the moment a test first becomes unreliable, including DOM snapshots and network timing. Next, check whether the flakiness comes from a race condition the test itsel...
42. Explain the lifecycle of a browser context in Playwright?
A BrowserContext moves through a clear creation-to-disposal lifecycle, and understanding it explains why contexts are the natural unit of test isolation. flowchart LR A[browser.newContext] --> B[Context created: empty cookies/storage] B --> C[context.newPage - one or more pages] C --> D[Pages nav...
43. What happens when a Playwright locator doesn't match any element within the timeout?
Playwright doesn't fail instantly the moment zero elements match - it keeps re-querying the DOM throughout the action's timeout window (30 seconds by default for actions), since the element might simply not have rendered yet. Once the timeout elapses with still no match, Playwright throws a Timeo...
44. How does Playwright implement network interception and request mocking internally?
When a route handler is registered via page.route() , Playwright's browser-side protocol layer subscribes to the browser's own network interception hooks (built on the same low-level machinery that powers DevTools' network panel in Chromium, and equivalent hooks in the patched Firefox/WebKit buil...
45. Why doesn't Playwright rely on the WebDriver protocol?
WebDriver was designed as a standardized, cross-vendor HTTP protocol so any client library could drive any compliant browser the same way - a strength for portability, but it constrains what's exposed to exactly what the W3C spec defines, and every command is a synchronous-feeling HTTP request/re...
46. How do you implement the Page Object Model in Playwright?
The Page Object Model (POM) wraps a page's locators and interactions inside a class, so tests read like a sequence of intentions rather than raw selector calls scattered throughout. // login-page.ts export class LoginPage { constructor ( private page : Page) {} async goto () { await this .page. g...
47. What is the difference between sharding and parallel workers in Playwright?
Both spread work out for speed, but at different levels - one within a single machine, the other across multiple machines entirely. Parallel workers Sharding Multiple processes on one machine Splitting the whole suite across separate machines/CI jobs Configured via workers in config Configured vi...
48. How does Playwright handle elements inside Shadow DOM?
Unlike many older tools that require manually piercing each shadow root, Playwright's built-in locators ( getByRole , getByText , page.locator() with CSS) automatically pierce open shadow roots by default, treating shadow DOM content as if it were part of the regular document. // Works even if #m...
49. Explain the internal working of Playwright's auto-waiting and actionability checks?
Before executing an action, Playwright doesn't just check the target element once - it runs a continuous polling loop, re-evaluating every relevant actionability check on every animation frame until all of them pass simultaneously or the timeout expires. flowchart TD A[Action called, e.g. click] ...
50. How can you integrate Playwright tests into a CI/CD pipeline?
The scaffolded project already includes a working GitHub Actions workflow, which is a reasonable template for most CI providers: # .github/workflows/playwright.yml - uses: actions/setup-node@v4 - run: npm ci - run: npx playwright install --with-deps - run: npx playwright test - uses: actions/uplo...