Manuals / Playwright with Python / Ch 37

Part 5 · CI/CD & ReportingAdvanced35 min read

28. Logging & Error Handling

Playwright with Python · 244 pages source format

Custom logging setup import logging logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s" ) logger = logging.getLogger(__name__) def test_login(page): logger.info("Starting login test") page.goto("https://app.example.com/login") logger.info("Navigated to login page") logging.basicConfig(level=..., format=...) What it does: Configures the root logger's minimum

What you'll learn

  • Custom logging setup
  • Screenshot/video capture on failure
  • Retry logic for flaky tests

Custom logging setup

level=logging.INFO,

format="%(asctime)s - %(levelname)s - %(message)s"

)

logger = logging.getLogger(__name__)

Run / study this snippet
def test_login(page):
Interactive study board
Custom logging setupDrag stickies · tap for tips
Study mapDrag stickies · tap for tipsKeep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Assert the UIdrag · tap →Retry wiselydrag · tap →Seed datadrag · tap →Close the loopdrag · tap →Keep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Pathwise hackdrag · tap →Page under testdrag · tap →Multi-browserdrag · tap →Automation pathdrag · tap →Tooling nodedrag · tap →
Clear?

page.goto("https://app.example.com/login")

What it does: Configures the root logger's minimum severity level and output format

Types/params:

logging.ERROR) — messages below this level are suppressed

(timestamp, level, message, etc.)

Pointers: INFO level is a reasonable default for test runs — enough to trace what a test

was doing without the noise of DEBUG-level internals. Custom logging like this gives

readable output beyond raw pytest console output, especially useful when a CI failure needs a narrative of "what happened right before it broke," not just a stack trace.

  • level (constant, e.g. logging.DEBUG, logging.INFO, logging.WARNING,
  • format (string, optional) — template controlling what each log line includes
Run / study this snippet
logger.info("Navigated to login page")
Interactive study board
page.goto("https://app.example.com/login")Drag stickies · tap for tips
Study mapDrag stickies · tap for tipsKeep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Assert the UIdrag · tap →Retry wiselydrag · tap →Seed datadrag · tap →Close the loopdrag · tap →Keep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Pathwise hackdrag · tap →Page under testdrag · tap →Multi-browserdrag · tap →Automation pathdrag · tap →Tooling nodedrag · tap →
Clear?

Screenshot/video capture on failure

--screenshot / --video (pytest-playwright CLI flags)

What it does: Automatically captures a screenshot and/or video for each test, controllable by outcome.

Types/params:

Pointers: only-on-failure / retain-on-failure are the right defaults for most

suites — capturing on every single test ("on") generates large amounts of storage for passing tests you'll likely never look at, while still giving you full debugging evidence exactly when you need it (a failure).

  • --screenshot: "off", "on", "only-on-failure"
  • --video: "off", "on", "retain-on-failure"
Run / study this snippet
# pytest-playwright supports this via CLI flags directly:
Interactive study board
Screenshot/video capture on failureDrag stickies · tap for tips
Study mapDrag stickies · tap for tipsKeep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Assert the UIdrag · tap →Retry wiselydrag · tap →Seed datadrag · tap →Close the loopdrag · tap →Keep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Pathwise hackdrag · tap →Page under testdrag · tap →Multi-browserdrag · tap →Automation pathdrag · tap →Tooling nodedrag · tap →
Clear?

Retry logic for flaky tests

What it does: Automatically re-runs a failed test up to a specified number of times before marking it as a genuine failure.

Types/params:

Pointers: Retry logic should be used carefully — it's meant for genuine environmental flakiness (a network blip, a race condition in test setup), not as a way to paper over a real, reproducible bug. A test that only passes 1-in-3 tries even with retries almost always indicates a real problem worth fixing rather than retrying around indefinitely; tracking which tests need reruns over time (tying back to Chapter 30's flaky-test diagnosis) is more valuable long-term than just cranking up the rerun count.

  • --reruns <count> (integer) — max number of retry attempts
  • --reruns-delay <seconds> (number, optional) — pause between retry attempts, useful if the failure might be due to a transient backend issue that needs a moment to resolve
Run / study this snippet
pip install pytest-rerunfailures
Interactive study board
Retry logic for flaky testsDrag stickies · tap for tips
Study mapDrag stickies · tap for tipsKeep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Assert the UIdrag · tap →Retry wiselydrag · tap →Seed datadrag · tap →Close the loopdrag · tap →Keep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Pathwise hackdrag · tap →Page under testdrag · tap →Multi-browserdrag · tap →Automation pathdrag · tap →Tooling nodedrag · tap →
Clear?

Checklist