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__)
def test_login(page):Interactive study board
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
logger.info("Navigated to login page")Interactive study board
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"
# pytest-playwright supports this via CLI flags directly:Interactive study board
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
pip install pytest-rerunfailures