Interview Prep August 18, 2026 20 min read

40+ Playwright Python Interview Questions & Answers (2026)

Python is the second most popular language for Playwright — and increasingly the first choice for teams with Python backends. This guide covers 40+ real Playwright Python interview questions organized by difficulty, with pytest-playwright code examples, coding challenges, and the AI topics interviewers ask in 2026.

If you're interviewing for a QA Automation or SDET role that uses Python, expect Playwright questions tailored to the Python ecosystem: pytest fixtures, conftest.py patterns, sync vs async API, and Pythonic Page Object Models. This guide covers every topic interviewers ask — from beginner fundamentals to advanced async patterns and AI-powered testing.

Questions are organized into seven sections: Beginner (fundamentals), Intermediate (pytest patterns & framework design), Advanced (async API & architecture), Coding Challenges (hands-on problems), CI/CD & DevOps, AI & Modern Testing, and Interview Tips.


Beginner Playwright Python Questions

These questions test your understanding of Playwright's core concepts in a Python context. Expect 3–5 of these in any Playwright Python interview.

Beginner
1. What is Playwright for Python and how does it differ from Selenium?

Playwright for Python is Microsoft's open-source browser automation library with a native Python API. It communicates with browsers through the Chrome DevTools Protocol (CDP) and equivalent native protocols for Firefox and WebKit — making it significantly faster than Selenium's WebDriver protocol.

Key differences from Selenium in a Python context:

  • Auto-waiting — no need for WebDriverWait or expected_conditions
  • Built-in pytest pluginpytest-playwright provides fixtures out of the box
  • All three browser engines — Chromium, Firefox, and WebKit with one pip install
  • Network interception — built-in page.route() vs. Selenium's limited proxy-based approach
  • API testing — Playwright has a native request context, Selenium has none
Beginner
2. How do you install Playwright for Python?

Installation requires two steps: install the Python package, then download the browser binaries:

Terminal
# Install Playwright and the pytest plugin
pip install playwright pytest-playwright

# Download browser binaries (Chromium, Firefox, WebKit)
playwright install

# Or install only Chromium to save disk space
playwright install chromium
Beginner
3. What is the difference between Playwright's sync and async API in Python?

Playwright Python offers two APIs:

  • Sync API (from playwright.sync_api import sync_playwright) — blocking calls, simpler to read and write. Used with pytest-playwright and ideal for test automation.
  • Async API (from playwright.async_api import async_playwright) — non-blocking calls using async/await. Used with asyncio or pytest-asyncio. Ideal for scraping, concurrent operations, or integration into async frameworks.

For testing, the sync API is recommended because pytest-playwright fixtures use it by default, and synchronous test code is easier to debug and maintain.

Beginner
4. What does a basic Playwright Python test look like with pytest?

With pytest-playwright, you get a page fixture automatically — no setup or teardown code needed:

Python — test_example.py
import re
from playwright.sync_api import Page, expect


def test_homepage_title(page: Page):
    page.goto("https://playwright.dev/")
    expect(page).to_have_title(re.compile("Playwright"))


def test_get_started_link(page: Page):
    page.goto("https://playwright.dev/")
    page.get_by_role("link", name="Get started").click()
    expect(page.get_by_role("heading", name="Installation")).to_be_visible()
Beginner
5. What browser types does Playwright Python support and how do you select them?

Playwright supports Chromium (Chrome, Edge), Firefox, and WebKit (Safari). With pytest-playwright, you select browsers using the --browser CLI flag:

Terminal
# Run on Chromium (default)
pytest

# Run on Firefox
pytest --browser firefox

# Run on WebKit
pytest --browser webkit

# Run on ALL browsers
pytest --browser chromium --browser firefox --browser webkit
Beginner
6. How do you run Playwright Python tests in headless vs headed mode?

By default, pytest-playwright runs in headless mode (no visible browser window). To run headed:

Terminal
# Headed mode — shows the browser
pytest --headed

# Slow motion for demos/debugging
pytest --headed --slowmo 500
Beginner
7. How do you take screenshots in Playwright Python?

Use the page.screenshot() method with various options:

Python
def test_screenshot(page: Page):
    page.goto("https://example.com")

    # Full page screenshot
    page.screenshot(path="screenshot.png", full_page=True)

    # Element screenshot
    page.get_by_role("heading").screenshot(path="heading.png")

    # Screenshot as bytes (for comparison)
    img_bytes = page.screenshot()
Beginner
8. What locator strategies does Playwright Python support?

Playwright Python uses the same locator hierarchy as all Playwright bindings, but with Python naming conventions (snake_case):

  • page.get_by_role("button", name="Submit") — ARIA role + accessible name (most resilient)
  • page.get_by_label("Email") — form controls by label text
  • page.get_by_text("Welcome") — visible text content
  • page.get_by_placeholder("Search...") — input placeholders
  • page.get_by_test_id("submit-btn") — data-testid attribute
  • page.locator("css=.my-class") — CSS selector (less preferred)

Always prefer semantic locators (get_by_role, get_by_label) over CSS/XPath — they survive UI redesigns and improve test readability.

Beginner
9. How do assertions work in Playwright Python?

Playwright Python provides web-first assertions through the expect() function. These assertions auto-retry until the condition is met or the timeout expires:

Python
from playwright.sync_api import Page, expect

def test_assertions(page: Page):
    page.goto("https://example.com")

    # Element assertions
    expect(page.get_by_role("heading")).to_be_visible()
    expect(page.get_by_role("button")).to_be_enabled()
    expect(page.get_by_label("Email")).to_have_value("test@example.com")
    expect(page.get_by_text("Success")).to_have_count(1)

    # Page assertions
    expect(page).to_have_url(re.compile(r"dashboard"))
    expect(page).to_have_title("My Dashboard")

    # Negation
    expect(page.get_by_text("Error")).not_to_be_visible()
Beginner
10. How do you run Playwright Python tests?

With pytest-playwright installed, you run tests using standard pytest commands:

Terminal
# Run all tests
pytest

# Run a specific file
pytest tests/test_login.py

# Run a specific test by name
pytest -k "test_login_success"

# Run with verbose output
pytest -v

# Run with 4 parallel workers
pytest -n 4

Intermediate Playwright Python Questions

These questions test your ability to build and maintain a Playwright Python test framework. Expect these in mid-level SDET and QA Automation Engineer interviews.

Intermediate
11. What fixtures does pytest-playwright provide out of the box?

The pytest-playwright plugin provides these built-in fixtures:

  • page — a fresh Page instance in an isolated BrowserContext (most commonly used)
  • context — the BrowserContext for the current test (useful for multi-page scenarios)
  • browser — the shared Browser instance (useful for creating additional contexts)
  • browser_name — string name of the current browser ("chromium", "firefox", "webkit")
  • browser_type — the BrowserType object for launching additional browsers
  • playwright — the Playwright instance itself

Each page fixture creates a new BrowserContext, providing complete test isolation (separate cookies, localStorage, cache) without launching a new browser process.

Intermediate
12. How do you use conftest.py with Playwright Python?

conftest.py is pytest's mechanism for sharing fixtures across test files. In Playwright Python projects, you use it to configure browser options, create custom fixtures, and set up shared state:

Python — conftest.py
import pytest
from playwright.sync_api import Page


@pytest.fixture(scope="session")
def browser_context_args(browser_context_args):
    """Override default context options for all tests."""
    return {
        **browser_context_args,
        "viewport": {"width": 1920, "height": 1080},
        "ignore_https_errors": True,
    }


@pytest.fixture
def authenticated_page(page: Page):
    """Provide a logged-in page to any test that needs it."""
    page.goto("https://myapp.com/login")
    page.get_by_label("Email").fill("admin@test.com")
    page.get_by_label("Password").fill("password123")
    page.get_by_role("button", name="Sign In").click()
    page.wait_for_url("**/dashboard")
    return page
Intermediate
13. How do you implement the Page Object Model in Playwright Python?

POM in Python uses classes that accept a Page instance and expose properties (locators) and methods (actions). Unlike Java, Python POM classes are concise thanks to property decorators and type hints:

Python — pages/login_page.py
from playwright.sync_api import Page, expect


class LoginPage:
    def __init__(self, page: Page):
        self.page = page
        self.email_input = page.get_by_label("Email")
        self.password_input = page.get_by_label("Password")
        self.submit_button = page.get_by_role("button", name="Sign In")
        self.error_message = page.get_by_role("alert")

    def navigate(self):
        self.page.goto("https://myapp.com/login")

    def login(self, email: str, password: str):
        self.email_input.fill(email)
        self.password_input.fill(password)
        self.submit_button.click()

    def expect_error(self, message: str):
        expect(self.error_message).to_have_text(message)
Intermediate
14. How do you handle dropdowns and select elements in Playwright Python?

For native <select> elements, use select_option(). For custom dropdowns (div-based), click to open, then click the option:

Python
# Native <select> element
page.get_by_label("Country").select_option("US")            # by value
page.get_by_label("Country").select_option(label="United States") # by visible text
page.get_by_label("Country").select_option(index=3)             # by index

# Custom dropdown (click-based)
page.get_by_role("combobox", name="Country").click()
page.get_by_role("option", name="United States").click()
Intermediate
15. How do you handle dialogs (alert, confirm, prompt) in Playwright Python?

Register an event listener before the action that triggers the dialog. Playwright auto-dismisses unhandled dialogs, so you must set the handler first:

Python
# Accept an alert dialog
page.on("dialog", lambda dialog: dialog.accept())
page.get_by_role("button", name="Delete").click()

# Dismiss a confirm dialog
page.on("dialog", lambda dialog: dialog.dismiss())

# Enter text in a prompt dialog
page.on("dialog", lambda dialog: dialog.accept("my input"))

# One-time handler using expect_event
with page.expect_event("dialog") as dialog_info:
    page.get_by_role("button", name="Confirm").click()
dialog = dialog_info.value
assert dialog.message == "Are you sure?"
Intermediate
16. How do you intercept and mock network requests in Playwright Python?

Use page.route() to intercept requests matching a URL pattern and provide mock responses, abort requests, or modify responses:

Python
import json

def test_mock_api(page: Page):
    # Mock an API response
    def handle_products(route):
        route.fulfill(
            status=200,
            content_type="application/json",
            body=json.dumps([{"id": 1, "name": "Mock Product"}]),
        )

    page.route("**/api/products", handle_products)
    page.goto("https://myapp.com/shop")
    expect(page.get_by_text("Mock Product")).to_be_visible()

    # Abort image requests (speed up tests)
    page.route("**/*.{png,jpg}", lambda route: route.abort())
Intermediate
17. What wait strategies are available in Playwright Python?

Playwright's auto-waiting handles most cases, but explicit waits are sometimes needed:

  • page.wait_for_url("**/dashboard") — wait for navigation to a URL pattern
  • page.wait_for_load_state("networkidle") — wait for network to be idle (500ms with no requests)
  • page.wait_for_selector(".spinner", state="hidden") — wait for an element to disappear
  • page.wait_for_timeout(1000) — hard wait (avoid in tests, use for debugging only)
  • locator.wait_for(state="visible") — wait for a specific locator state
  • expect(locator).to_be_visible(timeout=10000) — assertion with custom timeout

Best practice: Rely on auto-waiting and web-first assertions. Avoid wait_for_timeout() in production tests.

Intermediate
18. How do you create multiple browser contexts in a single test?

Use the browser fixture to create additional contexts. This is useful for testing multi-user scenarios:

Python
from playwright.sync_api import Browser, expect

def test_two_users_chatting(browser: Browser):
    # Create two isolated contexts
    alice_context = browser.new_context()
    bob_context = browser.new_context()

    alice_page = alice_context.new_page()
    bob_page = bob_context.new_page()

    # Alice and Bob are completely isolated
    alice_page.goto("https://chat.example.com")
    bob_page.goto("https://chat.example.com")

    # Clean up
    alice_context.close()
    bob_context.close()
Intermediate
19. How do you parametrize Playwright Python tests?

Use pytest's @pytest.mark.parametrize decorator to run the same test with different data sets:

Python
import pytest
from playwright.sync_api import Page, expect


@pytest.mark.parametrize("username,password,expected", [
    ("admin@test.com", "correct_pass", "Dashboard"),
    ("admin@test.com", "wrong_pass", "Invalid credentials"),
    ("", "", "Email is required"),
])
def test_login_scenarios(page: Page, username, password, expected):
    page.goto("https://myapp.com/login")
    page.get_by_label("Email").fill(username)
    page.get_by_label("Password").fill(password)
    page.get_by_role("button", name="Sign In").click()
    expect(page.get_by_text(expected)).to_be_visible()
Intermediate
20. How do you manage environment variables and test configuration in Playwright Python?

Use python-dotenv for environment-specific config and pytest fixtures for base URLs:

Python — conftest.py
import os
import pytest
from dotenv import load_dotenv

load_dotenv()


@pytest.fixture(scope="session")
def base_url():
    """Return the base URL from environment or default."""
    return os.getenv("BASE_URL", "https://staging.myapp.com")


@pytest.fixture(scope="session")
def browser_context_args(browser_context_args, base_url):
    return {
        **browser_context_args,
        "base_url": base_url,
    }

Tip: With base_url configured, you can use relative URLs in tests: page.goto("/login") instead of the full URL. This makes switching between staging and production seamless.

Advanced Playwright Python Questions

These questions probe your experience with real-world architecture, async patterns, and debugging. Interviewers want depth and trade-off analysis.

Advanced
21. How do you use Playwright's async API with pytest?

Use pytest-asyncio alongside Playwright's async API for concurrent test operations. This is useful when you need to perform multiple async operations simultaneously:

Python — test_async.py
import asyncio
import pytest
from playwright.async_api import async_playwright, expect


@pytest.mark.asyncio
async def test_concurrent_pages():
    async with async_playwright() as p:
        browser = await p.chromium.launch()

        # Create two pages concurrently
        context = await browser.new_context()
        page1 = await context.new_page()
        page2 = await context.new_page()

        # Navigate both pages simultaneously
        await asyncio.gather(
            page1.goto("https://example.com/page1"),
            page2.goto("https://example.com/page2"),
        )

        await expect(page1).to_have_title("Page 1")
        await expect(page2).to_have_title("Page 2")
        await browser.close()
Advanced
22. How do you create custom pytest fixtures for Playwright?

Custom fixtures extend pytest-playwright's built-in fixtures. Use yield for setup/teardown patterns and type hints for IDE support:

Python — conftest.py
import pytest
from playwright.sync_api import Page, BrowserContext
from pages.login_page import LoginPage
from pages.dashboard_page import DashboardPage


@pytest.fixture
def login_page(page: Page) -> LoginPage:
    """Provide a LoginPage POM instance."""
    login = LoginPage(page)
    login.navigate()
    return login


@pytest.fixture
def admin_dashboard(page: Page) -> DashboardPage:
    """Provide a logged-in admin dashboard page."""
    login = LoginPage(page)
    login.navigate()
    login.login("admin@test.com", "password123")
    dashboard = DashboardPage(page)
    yield dashboard
    # Teardown: log out after test completes
    dashboard.logout()
Advanced
23. How do you run Playwright Python tests in parallel?

Use pytest-xdist for parallel execution. Each worker gets its own browser instance:

Terminal
# Install pytest-xdist
pip install pytest-xdist

# Run with 4 workers
pytest -n 4

# Auto-detect number of CPU cores
pytest -n auto

# Distribute tests by file (default) or by test
pytest -n 4 --dist loadfile

Important: When running in parallel, ensure your tests are fully isolated. Avoid shared database state, shared files, or any test that depends on another test's output. Each worker gets its own browser context, but your backend state must be isolated too.

Advanced
24. How do you use Playwright's tracing and debugging in Python?

Playwright traces capture a complete timeline of test execution — DOM snapshots, network requests, console logs, and screenshots at every step:

Python
def test_with_trace(page: Page, context: BrowserContext):
    # Start tracing before the test actions
    context.tracing.start(screenshots=True, snapshots=True, sources=True)

    page.goto("https://myapp.com")
    page.get_by_role("link", name="Dashboard").click()

    # Stop and save the trace
    context.tracing.stop(path="trace.zip")

# View the trace in the browser
# playwright show-trace trace.zip
Terminal — CLI tracing
# Enable tracing via CLI (no code changes needed)
pytest --tracing on

# Trace only on first retry (recommended for CI)
pytest --tracing retain-on-failure
Advanced
25. How do you perform API testing with Playwright Python's request context?

Playwright's APIRequestContext lets you make HTTP requests without launching a browser. Use it for API-level setup, teardown, or pure API testing:

Python
from playwright.sync_api import Playwright

def test_api_crud(playwright: Playwright):
    api = playwright.request.new_context(
        base_url="https://api.myapp.com",
        extra_http_headers={"Authorization": "Bearer token123"},
    )

    # Create a user
    response = api.post("/users", data={
        "name": "Jane Doe",
        "email": "jane@test.com",
    })
    assert response.status == 201
    user = response.json()

    # Fetch the user
    response = api.get(f"/users/{user['id']}")
    assert response.json()["name"] == "Jane Doe"

    # Clean up
    api.delete(f"/users/{user['id']}")
    api.dispose()
Advanced
26. How do you reuse authentication state across tests in Playwright Python?

Use storage_state to save and restore cookies/localStorage. Log in once, save the state to a file, and load it in subsequent tests:

Python — conftest.py
import pytest
from playwright.sync_api import Browser


@pytest.fixture(scope="session")
def auth_state(browser: Browser):
    """Log in once and save auth state for the entire session."""
    context = browser.new_context()
    page = context.new_page()
    page.goto("https://myapp.com/login")
    page.get_by_label("Email").fill("admin@test.com")
    page.get_by_label("Password").fill("password123")
    page.get_by_role("button", name="Sign In").click()
    page.wait_for_url("**/dashboard")
    context.storage_state(path="auth.json")
    context.close()
    return "auth.json"


@pytest.fixture
def authenticated_page(browser: Browser, auth_state):
    """Create a pre-authenticated page for each test."""
    context = browser.new_context(storage_state=auth_state)
    page = context.new_page()
    yield page
    context.close()
Advanced
27. What browser context options are commonly used in Playwright Python?

Key BrowserContext options you should know:

  • viewport={"width": 1280, "height": 720} — set the browser viewport size
  • storage_state="auth.json" — load saved authentication state
  • ignore_https_errors=True — bypass SSL certificate errors in staging
  • locale="fr-FR" — set the browser locale for i18n testing
  • timezone_id="America/New_York" — override timezone
  • geolocation={"latitude": 40.7, "longitude": -74.0} — mock GPS location
  • permissions=["geolocation", "notifications"] — grant permissions
  • color_scheme="dark" — test dark mode
  • record_video_dir="videos/" — record video of test execution
  • http_credentials={"username": "user", "password": "pass"} — HTTP Basic auth
Advanced
28. How do you use monkeypatch in Playwright Python tests?

Pytest's monkeypatch fixture lets you override environment variables, module attributes, or dictionary values during a test. Combined with Playwright, it's useful for injecting test config:

Python
def test_admin_feature_flag(page: Page, monkeypatch):
    # Override env var for this test only
    monkeypatch.setenv("FEATURE_ADMIN_PANEL", "true")

    page.goto("https://myapp.com/dashboard")
    # Admin panel should be visible because feature flag is on
    expect(page.get_by_role("navigation", name="Admin")).to_be_visible()
Advanced
29. How do you integrate Playwright with pytest-bdd for BDD testing?

pytest-bdd lets you write Gherkin-style feature files and map them to Playwright step definitions:

Gherkin — features/login.feature
Feature: User Login
  Scenario: Successful login with valid credentials
    Given I am on the login page
    When I enter "admin@test.com" and "password123"
    And I click the Sign In button
    Then I should see the dashboard
Python — test_login_bdd.py
from pytest_bdd import scenario, given, when, then, parsers
from playwright.sync_api import Page, expect


@scenario("features/login.feature", "Successful login with valid credentials")
def test_login():
    pass


@given("I am on the login page")
def navigate_to_login(page: Page):
    page.goto("https://myapp.com/login")


@when(parsers.parse('I enter "{email}" and "{password}"'))
def enter_credentials(page: Page, email, password):
    page.get_by_label("Email").fill(email)
    page.get_by_label("Password").fill(password)


@when("I click the Sign In button")
def click_sign_in(page: Page):
    page.get_by_role("button", name="Sign In").click()


@then("I should see the dashboard")
def verify_dashboard(page: Page):
    expect(page).to_have_url(re.compile(r"dashboard"))
Advanced
30. What are the performance considerations for Playwright Python test suites?

Key performance strategies for large Playwright Python suites:

  • Reuse auth state — log in once with storage_state instead of logging in per test
  • Use API for setup/teardown — create test data via API instead of UI clicks
  • Run in parallel — use pytest-xdist with -n auto for parallel workers
  • Block unnecessary resources — abort images, fonts, and analytics with page.route()
  • Use headless mode — headless is faster than headed (the default)
  • Minimize wait_for_timeout() — hard waits add up and are often unnecessary
  • Use session scope for browser — pytest-playwright already does this by default
  • Docker with pre-installed browsers — avoids downloading browsers in CI

Coding Challenges

These are hands-on problems you may be asked to solve during a live coding interview. Practice writing these from memory.

Coding
31. Write a complete login test with error handling in Playwright Python.

This test covers the happy path and verifies the user lands on the dashboard after login:

Python — test_login.py
import re
from playwright.sync_api import Page, expect


def test_successful_login(page: Page):
    # Navigate to login page
    page.goto("https://myapp.com/login")

    # Fill in credentials
    page.get_by_label("Email").fill("user@example.com")
    page.get_by_label("Password").fill("securePassword1!")

    # Submit the form
    page.get_by_role("button", name="Sign In").click()

    # Verify successful login
    expect(page).to_have_url(re.compile(r"/dashboard"))
    expect(page.get_by_role("heading", name="Welcome")).to_be_visible()
    expect(page.get_by_text("user@example.com")).to_be_visible()


def test_login_with_invalid_password(page: Page):
    page.goto("https://myapp.com/login")
    page.get_by_label("Email").fill("user@example.com")
    page.get_by_label("Password").fill("wrongpassword")
    page.get_by_role("button", name="Sign In").click()

    # Verify error message
    expect(page.get_by_role("alert")).to_have_text("Invalid email or password")
    # Verify we stayed on login page
    expect(page).to_have_url(re.compile(r"/login"))
Coding
32. Implement a Page Object Model class for a product listing page.

A complete POM class with locators, actions, and assertion helpers:

Python — pages/products_page.py
from playwright.sync_api import Page, Locator, expect


class ProductsPage:
    URL = "/products"

    def __init__(self, page: Page):
        self.page = page
        self.search_input = page.get_by_placeholder("Search products...")
        self.category_select = page.get_by_label("Category")
        self.product_cards = page.locator("[data-testid='product-card']")
        self.cart_badge = page.get_by_test_id("cart-count")
        self.sort_dropdown = page.get_by_label("Sort by")

    def navigate(self):
        self.page.goto(self.URL)
        expect(self.page).to_have_url(re.compile(r"/products"))

    def search(self, query: str):
        self.search_input.fill(query)
        self.search_input.press("Enter")

    def filter_by_category(self, category: str):
        self.category_select.select_option(label=category)

    def add_to_cart(self, product_name: str):
        card = self.product_cards.filter(has_text=product_name)
        card.get_by_role("button", name="Add to Cart").click()

    def expect_product_count(self, count: int):
        expect(self.product_cards).to_have_count(count)

    def expect_cart_count(self, count: int):
        expect(self.cart_badge).to_have_text(str(count))
Coding
33. Write an API test using Playwright Python's request context.

A complete CRUD API test without launching a browser:

Python — test_api.py
from playwright.sync_api import Playwright


def test_todo_api_crud(playwright: Playwright):
    api = playwright.request.new_context(
        base_url="https://jsonplaceholder.typicode.com",
    )

    # CREATE
    create_resp = api.post("/todos", data={
        "title": "Write Playwright tests",
        "completed": False,
        "userId": 1,
    })
    assert create_resp.status == 201
    todo = create_resp.json()
    assert todo["title"] == "Write Playwright tests"

    # READ
    get_resp = api.get("/todos/1")
    assert get_resp.status == 200
    assert get_resp.json()["id"] == 1

    # UPDATE
    update_resp = api.put("/todos/1", data={
        "title": "Updated title",
        "completed": True,
        "userId": 1,
    })
    assert update_resp.status == 200

    # DELETE
    delete_resp = api.delete("/todos/1")
    assert delete_resp.status == 200

    api.dispose()
Coding
34. Write a visual regression test in Playwright Python.

Playwright Python supports screenshot comparison for visual regression testing:

Python — test_visual.py
from playwright.sync_api import Page, expect


def test_homepage_visual(page: Page):
    page.goto("https://myapp.com")
    # Wait for animations to settle
    page.wait_for_load_state("networkidle")

    # Full page screenshot comparison
    expect(page).to_have_screenshot("homepage.png", max_diff_pixels=100)


def test_component_visual(page: Page):
    page.goto("https://myapp.com/pricing")

    # Compare a specific component
    pricing_card = page.get_by_test_id("pricing-pro")
    expect(pricing_card).to_have_screenshot(
        "pricing-pro-card.png",
        max_diff_pixel_ratio=0.01,  # Allow 1% pixel difference
    )
Terminal
# First run creates baseline screenshots
pytest --update-snapshots

# Subsequent runs compare against baselines
pytest
Coding
35. Write a data-driven test using an external data source.

Load test data from a JSON file and use pytest.mark.parametrize:

Python — test_data_driven.py
import json
import pytest
from pathlib import Path
from playwright.sync_api import Page, expect


# Load test data from JSON file
DATA_FILE = Path(__file__).parent / "data" / "users.json"
TEST_USERS = json.loads(DATA_FILE.read_text())


@pytest.mark.parametrize("user", TEST_USERS, ids=[u["name"] for u in TEST_USERS])
def test_user_profile_display(page: Page, user):
    """Verify each user's profile displays correctly."""
    page.goto(f"https://myapp.com/users/{user['id']}")

    expect(page.get_by_role("heading")).to_have_text(user["name"])
    expect(page.get_by_text(user["email"])).to_be_visible()
    expect(page.get_by_text(user["role"])).to_be_visible()
JSON — data/users.json
[
  {"id": 1, "name": "Alice Johnson", "email": "alice@test.com", "role": "Admin"},
  {"id": 2, "name": "Bob Smith", "email": "bob@test.com", "role": "Editor"},
  {"id": 3, "name": "Carol Williams", "email": "carol@test.com", "role": "Viewer"}
]

CI/CD & DevOps Questions

These questions test your ability to run Playwright Python tests in production pipelines.

CI/CD
36. How do you set up Playwright Python tests in GitHub Actions?

Here's a production-ready GitHub Actions workflow for Playwright Python:

YAML — .github/workflows/playwright.yml
name: Playwright Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install dependencies
        run: |
          pip install -r requirements.txt
          playwright install --with-deps chromium

      - name: Run tests
        run: pytest --browser chromium --tracing retain-on-failure

      - name: Upload traces
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-traces
          path: test-results/
CI/CD
37. How do you run Playwright Python tests in Docker?

Use Microsoft's official Playwright Docker image which includes all browser dependencies pre-installed:

Dockerfile
FROM mcr.microsoft.com/playwright/python:v1.48.0-noble

WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .
CMD ["pytest", "--browser", "chromium", "-n", "auto"]
CI/CD
38. How do you use pytest markers to organize Playwright tests?

Markers let you categorize tests and run subsets selectively:

Python — conftest.py + test file
# conftest.py — register custom markers
def pytest_configure(config):
    config.addinivalue_line("markers", "smoke: quick smoke tests")
    config.addinivalue_line("markers", "regression: full regression suite")
    config.addinivalue_line("markers", "api: API-only tests (no browser)")


# test_login.py — use markers
@pytest.mark.smoke
def test_login_success(page: Page):
    ...

@pytest.mark.regression
def test_login_with_expired_session(page: Page):
    ...

# Run only smoke tests
# pytest -m smoke

# Run everything except API tests
# pytest -m "not api"
CI/CD
39. How do you generate HTML reports for Playwright Python tests?

Use pytest-html for HTML reports or Playwright's built-in reporting:

Terminal
# Install pytest-html
pip install pytest-html

# Generate HTML report
pytest --html=report.html --self-contained-html

# Generate JUnit XML for CI integration
pytest --junitxml=results.xml

# Use Allure for richer reports
pip install allure-pytest
pytest --alluredir=allure-results
allure serve allure-results
CI/CD
40. How do you implement retry strategies for flaky Playwright Python tests?

Use pytest-rerunfailures to automatically retry failed tests:

Terminal + Python
# Install the plugin
pip install pytest-rerunfailures

# Retry failed tests up to 2 times
pytest --reruns 2

# Add a delay between retries
pytest --reruns 2 --reruns-delay 3

# Mark individual tests for retry
@pytest.mark.flaky(reruns=3, reruns_delay=2)
def test_sometimes_flaky(page: Page):
    ...

Warning: Retries are a band-aid, not a fix. If a test needs retries, investigate the root cause: timing issues, shared state, or external service dependencies. Fix the flake, then remove the retry.

AI & Modern Testing Questions

These questions are the 2026 differentiator. Mentioning AI-powered testing signals you're up to date with current tooling.

AI & MCP
41. How can Claude AI generate Playwright Python tests?

Claude AI can generate complete Playwright Python test files from natural language descriptions. Unlike Codegen (which records clicks), Claude understands intent and generates:

  • Semantic locators (get_by_role, get_by_label) instead of brittle CSS selectors
  • Proper POM structure with type hints
  • Edge case tests (empty fields, boundary values, error states)
  • Meaningful assertions beyond just "element exists"
  • conftest.py fixtures and pytest markers

You provide a prompt like "Write a Playwright Python test for the checkout flow including empty cart, single item, and coupon code scenarios" and Claude generates a complete, runnable test file with proper Python conventions.

AI & MCP
42. What is the MCP Server and how does it work with Playwright Python?

The Model Context Protocol (MCP) Server connects Claude AI to a running Playwright browser, giving the AI live access to the DOM, accessibility tree, network requests, and console logs. With MCP, Claude can:

  • Navigate to your actual application and inspect the live DOM
  • Read the accessibility tree to find the best locators
  • Generate tests based on the real page structure, not guessed selectors
  • Debug failing tests by examining the actual page state

The generated tests are standard pytest-playwright files — no MCP dependency at runtime. MCP is only used during test authoring.

AI & MCP
43. What are self-healing tests and how do they work with Playwright Python?

Self-healing tests use AI to automatically fix broken selectors when the UI changes. The workflow:

  1. A test fails because a locator no longer matches (e.g., button text changed from "Submit" to "Save")
  2. An AI agent detects the failure, navigates to the page via MCP, and inspects the current DOM
  3. The agent identifies the updated element using the accessibility tree and context
  4. The test file is automatically updated with the corrected locator
  5. The updated test runs again to verify the fix

This dramatically reduces maintenance burden for large test suites where locator breakage is the #1 cause of test failures.

AI & MCP
44. What is agentic testing in the context of Playwright Python?

Agentic testing uses AI agents that can plan, generate, execute, and heal Playwright Python tests autonomously. The emerging architecture in 2026:

  • Planner Agent — takes a user story and produces a structured test plan (pages to cover, flows to test, edge cases)
  • Generator Agent — takes the plan and generates pytest-playwright spec files using MCP for live DOM context
  • Healer Agent — monitors CI runs, detects failures, and fixes broken locators automatically

QA engineers become "test architects" who design the agentic pipeline and review AI output, rather than writing individual selectors and assertions by hand.

AI & MCP
45. How do you review and validate AI-generated Playwright Python test code?

AI-generated tests require the same review rigor as human-written code. Key review checklist:

  • Locator quality — verify semantic locators (get_by_role, get_by_label) are used instead of brittle CSS selectors
  • Assertion coverage — check that tests assert meaningful outcomes, not just element visibility
  • Test isolation — ensure each test is independent and doesn't rely on another test's state
  • Data management — verify test data is created/cleaned up properly, not hardcoded
  • Error paths — confirm the AI included negative test cases and edge cases
  • Naming conventions — function names should describe the scenario, not implementation details
  • No sleep calls — AI sometimes adds wait_for_timeout() unnecessarily; remove them

Tips for Acing the Interview

  1. Practice writing pytest-playwright code by hand — interviewers may ask you to write a test without IDE autocomplete. Practice get_by_role, get_by_label, expect(), and fixture syntax from memory. Know the Python snake_case API, not just the TypeScript camelCase.
  2. Know conftest.py deeply — the ability to explain fixture scopes (function, class, module, session), yield fixtures for teardown, and fixture composition is a strong signal of pytest mastery.
  3. Have a debugging story ready — prepare a specific example of a flaky or hard-to-debug Playwright Python test you diagnosed. Include the symptom, your investigation process, the root cause, and the fix. Mention Trace Viewer if you used it.
  4. Know trade-offs — "It depends" is acceptable if you explain the reasoning. Why sync vs async API? Why POM vs raw page objects? Why get_by_role over get_by_test_id? Why pytest-xdist vs single-threaded?
  5. Mention AI/MCP proactively — even if not asked directly, mentioning Claude AI + MCP Server for test generation signals you're current with 2026 tooling. Explain that the generated tests are standard pytest files with zero AI runtime dependency.
  6. Ask about their test suite — "How many tests do you have?", "What's your flake rate?", "Do you use parallel execution?" shows you think at the architecture level, not just the test-writing level.

Common mistake: Candidates who only know TypeScript Playwright syntax struggle with Python-specific questions about conftest.py, fixtures, markers, and pytest conventions. If the role requires Python, practice the Python API specifically.

Frequently Asked Questions

What Playwright Python topics are asked in interviews in 2026?

Interviews cover pytest-playwright fixtures, sync vs async API, Page Object Model in Python, conftest.py patterns, network interception, API testing with request context, parallel execution, tracing, CI/CD, and AI-powered testing with Claude and MCP Server.

Is Playwright Python as popular as Playwright TypeScript for interviews?

TypeScript remains the most popular Playwright language, but Python is growing rapidly — especially in teams with Python backends, data engineering, or ML. Many companies now accept either language. If the job listing mentions Python or pytest, expect Python-specific questions.

Do I need to know pytest to use Playwright Python?

Yes. The pytest-playwright plugin is the standard way to run Playwright tests in Python. You need to understand fixtures, conftest.py, markers, parametrize, and basic pytest conventions.

What coding challenges are common in Playwright Python interviews?

Common challenges: writing a login test, implementing a POM class, creating data-driven tests with pytest.mark.parametrize, writing API tests with request context, and setting up authentication state reuse with storage_state.

How do I prepare for a Playwright Python interview in 2026?

Focus on four areas: (1) pytest-playwright fundamentals, (2) Playwright Python API — locators, actions, assertions, network interception, (3) framework patterns — POM, custom fixtures, parallel execution, CI/CD, and (4) AI topics — Claude AI, MCP Server, self-healing locators, and agentic testing.


Asim Noaman - Playwright and Claude AI course instructor

Asim Noaman

Senior QA Automation Engineer & AI Testing Specialist

With years of hands-on experience building test automation frameworks for production applications, Asim specializes in combining traditional QA methodologies with cutting-edge AI tools. He has helped teams adopt Playwright and AI-driven testing workflows to ship faster with fewer bugs.

Udemy Instructor Published course author
Playwright + AI Expert Specialized in AI-powered QA
Production Experience Enterprise-grade frameworks
Connect on LinkedIn