Taking Screenshots & Logging
Screenshots and structured logging transform test failures from mysterious events into diagnosable evidence. Capturing a screenshot at the exact moment of failure — with the right naming convention and logging context — enables developers to understand and fix bugs without re-running the test. Professional SDET teams always have screenshot-on-failure implemented.
Screenshot & Logging Implementation
import pytest
import logging
import os
from datetime import datetime
from selenium import webdriver
# ── LOGGING CONFIGURATION ─────────────────────────────────────
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[
logging.FileHandler("test_run.log"),
logging.StreamHandler() # Also log to console
]
)
logger = logging.getLogger(__name__)
# ── SCREENSHOT ON FAILURE (pytest conftest.py) ────────────────
@pytest.fixture(scope="function")
def driver(request):
driver = webdriver.Chrome()
driver.implicitly_wait(10)
yield driver
# After test completes: check if test FAILED
if request.node.rep_call.failed:
# Create screenshots directory
os.makedirs("screenshots", exist_ok=True)
# Timestamp + test name for unique filename
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
test_name = request.node.name.replace("/", "_")
filename = f"screenshots/{test_name}_{timestamp}.png"
# Take and save screenshot
driver.save_screenshot(filename)
logger.error(f"❌ Test FAILED — screenshot saved: {filename}")
driver.quit()
# required pytest hook to capture failure info
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
item.rep_call = outcome.get_result() if call.when == "call" else None
# ── TEST WITH BUILT-IN LOGGING ────────────────────────────────
def test_login_flow(driver):
logger.info("Starting login test")
driver.get("https://staging.app.com/login")
logger.info(f"Navigated to: {driver.current_url}")
email_field = driver.find_element("id", "email")
email_field.send_keys("alice@test.com")
logger.info("Entered email address")
password_field = driver.find_element("id", "password")
password_field.send_keys("Test@1234")
driver.find_element("id", "submit").click()
logger.info("Clicked login button")
assert "/dashboard" in driver.current_url, f"Expected redirect to dashboard, got: {driver.current_url}"
logger.info("✅ Login successful — on dashboard")
# ── ELEMENT-LEVEL SCREENSHOT ──────────────────────────────────
def screenshot_element(driver, element, filename):
"""Take screenshot of a specific element only"""
element.screenshot(filename) # Selenium 4+ featureCommon Mistakes
- Taking screenshots only on specific assertions — screenshot capture should be in the finally/teardown fixture so it triggers on ANY failure in the test
- Overwriting screenshots with the same name — always include timestamp and test name in the filename for unique, traceable screenshots
- Logging only at INFO level — use DEBUG for step-level detail, INFO for milestones, WARNING for potential issues, ERROR for failures
- Not including screenshots in CI artifacts — screenshots saved locally disappear when CI containers are destroyed; upload as CI artifacts
Tip
Tip
Practice Taking Screenshots Logging in small, isolated examples before integrating into larger projects. Breaking concepts into small experiments builds genuine understanding faster than reading alone.
Testing pyramid: many unit tests, fewer integration, fewest E2E
Practice Task
Note
Practice Task — (1) Write a working example of Taking Screenshots Logging from scratch without looking at notes. (2) Modify it to handle an edge case (empty input, null value, or error state). (3) Share your solution in the Priygop community for feedback.
Quick Quiz
Common Mistake
Warning
A common mistake with Taking Screenshots Logging is skipping edge case testing — empty inputs, null values, and unexpected data types. Always validate boundary conditions to write robust, production-ready software testing code.
Key Takeaways
- Screenshots and structured logging transform test failures from mysterious events into diagnosable evidence.
- Taking screenshots only on specific assertions — screenshot capture should be in the finally/teardown fixture so it triggers on ANY failure in the test
- Overwriting screenshots with the same name — always include timestamp and test name in the filename for unique, traceable screenshots
- Logging only at INFO level — use DEBUG for step-level detail, INFO for milestones, WARNING for potential issues, ERROR for failures