Playwright: Auto-Waiting, Locators & Tracing
Now meet Playwright, the newer tool. The best part is what you get to stop writing: most of those manual waits just disappear.
The idea, in one line
Before every action, Playwright checks the element is actually ready and retries on its own until it is. You describe what you want; it handles the waiting.
The readiness checks, in plain words
Playwright waits for the element to be:
- visible — actually on screen
- stable — not still moving (its box is unchanged across two frames)
- enabled — not greyed out
- editable — for typing, it accepts input
- receives events — not hidden under an overlay
A click waits for all five. A fill waits for visible, enabled and editable. Whole categories of flakiness simply vanish.
Locators that read like a user
Prefer page.get_by_role("button", name="Sign in"). It matches how a person (and a screen reader) sees the page, so it survives DOM changes. Its siblings are get_by_label, get_by_placeholder, get_by_text, and get_by_test_id. When you need raw CSS or XPath, page.locator(css) is the escape hatch.
See it work
from playwright.sync_api import Page, expect
def test_login(page: Page):
page.goto("https://www.saucedemo.com/")
# Locators by role and placeholder, no manual waits
page.get_by_placeholder("Username").fill("standard_user")
page.get_by_placeholder("Password").fill("secret_sauce")
page.get_by_role("button", name="Login").click()
# A web-first assertion auto-retries until it passes
expect(page.get_by_text("Products")).to_be_visible()
# Record a trace, then open it:
# pytest --tracing on
# playwright show-trace trace.zipRead it top to bottom: go to the page, fill both fields, click Login, then check the Products text shows up. No sleeps anywhere.
Assertions here use expect(...).to_be_visible(). It keeps re-checking until it's true or it times out — you never poll by hand.
Advanced — tracing, your instant replay
When a test does fail, tracing is the payoff. Run pytest --tracing on, then playwright show-trace trace.zip. You get a frame-by-frame timeline with DOM snapshots, network activity, and the exact source line for every action.
Grounded in the official Playwright (Python) docs — Actionability, Locators, Trace Viewer
All lessons in UI Automation: Selenium + Playwright + pytest
- Selenium Locators: Finding the Element You Mean
- Waits, Actions & Frames — Killing Flakiness at the Source
- Playwright: Auto-Waiting, Locators & Tracing
- pytest Deep-Dive: Fixtures, conftest, Parametrize & Markers
- Page Object Model, Done Properly
- The Hard Stuff: Dynamic Elements, iframes, Uploads & Network Stubbing