make audit # 0.2s, no browserscripts/audit_locators.py checks every locator literal in pages/ and tests/ against the
rendered app, and flags any get_by_label that would trip strict mode. If a test broke right
after someone touched the templates, this tells you which locator died before you launch anything.
- Read the error. Playwright's messages are unusually good — they tell you what the locator resolved to and what it waited for.
--headed --slowmo 500— watch it.PWDEBUG=1— Playwright Inspector: step through, live-edit locators.- Open the trace — especially for CI failures you cannot reproduce.
pytest tests/02_pom/test_login.py --headed --slowmo 800
make headedPWDEBUG=1 pytest tests/02_pom/test_login.py -k valid --headed -s
make debugThe Inspector pauses before each action, shows the resolved locator, and has a Pick locator button that generates a locator by clicking the page. Use it to check whether your locator is ambiguous before strict mode tells you it is.
page.pause() in code does the same thing at an exact point.
A trace records the whole run: a DOM snapshot before and after every action, network, console, screenshots, and timings. It is how you debug a CI failure without reproducing it.
We capture retain-on-failure (see pytest.ini), so passing runs cost nothing.
playwright show-trace reports/test-results/<test>/trace.zip
make trace # opens the newest oneFrom CI: download the report-* artifact for the failing shard, unzip, and point
show-trace at the trace.zip inside.
What to do in the viewer:
- Scrub the timeline to the red step
- Toggle Before / Action / After snapshots — the DOM is live and inspectable
- Check Network for a 500 or a request that never fired
- Check Console for a JS error that broke rendering
- Compare the "expected" locator against the actual DOM at that instant
playwright codegen http://127.0.0.1:5000Records your clicks into Python. Treat the output as a draft: it often picks positional or text locators you would not choose, and it never produces page objects. Rewrite it.
pytest -x # stop at the first failure
pytest --lf # rerun last failures only
pytest --sw # stepwise: stop, fix, continue from there
pytest -vv --tb=long # full tracebacks
pytest -s # let print() through
pytest --collect-only # what would run, without running it
pytest --setup-plan # the fixture graph for those testsVideo (--video on) and screenshots (--screenshot on) are useful for a demo or a bug report,
but a trace beats both for actual debugging.
- Did it fail on all browsers or one? One browser usually means a real engine difference.
- Did it fail on all shards or one? One shard hints at test-order or data collision.
- Download the trace. Look at the DOM snapshot at failure.
- Reproduce the CI conditions locally:
HEADLESS=true pytest -n 2 --browser webkit. - Still passing locally? Suspect timing (CI runners are slower), timezone/locale, or shared state.