← Back

Playwright Python Test Utilities

Reusable utilities for building reliable real-world automation frameworks

1

Reusable Login Utility

Login is one of the most repeated actions in UI automation. Instead of writing login steps in every test, create a reusable utility.

utils/login.py
from playwright.sync_api import Page

def login(page: Page, username: str, password: str):
    page.goto("https://example.com/login")

    page.get_by_label("Username").fill(username)
    page.get_by_label("Password").fill(password)
    page.get_by_role("button", name="Login").click()

    page.wait_for_url("**/dashboard")
Real-time use: Use the same login utility for smoke, regression and end-to-end tests.
2

Navigation Utility

Create a common navigation helper when many tests repeatedly open the same application pages.

utils/navigation.py
def open_dashboard(page):
    page.goto("https://example.com/dashboard")
    page.wait_for_load_state("domcontentloaded")


def open_orders(page):
    page.goto("https://example.com/orders")
    page.wait_for_load_state("domcontentloaded")
3

Wait Utility

Playwright already provides automatic waiting. Prefer locator-based waits instead of unnecessary hard-coded sleeps.

utils/waits.py
def wait_for_dashboard(page):
    page.get_by_role(
        "heading",
        name="Dashboard"
    ).wait_for(state="visible")
Avoid: time.sleep(5) for normal UI synchronization. Let Playwright wait for the required condition whenever possible.
4

Screenshot Utility

Create a standard screenshot helper for debugging failed tests and capturing important business states.

utils/screenshots.py
from pathlib import Path

def take_screenshot(page, name):
    Path("screenshots").mkdir(
        parents=True,
        exist_ok=True
    )

    page.screenshot(
        path=f"screenshots/{name}.png",
        full_page=True
    )
5

File Upload Utility

File upload utilities are useful for profile images, invoices, documents and CSV imports.

utils/upload.py
def upload_file(page, file_path):
    page.get_by_label("Upload File").set_input_files(
        file_path
    )
6

File Download Utility

Use Playwright's download event when validating reports, invoices or exported files.

utils/download.py
def download_report(page):
    with page.expect_download() as download_info:
        page.get_by_role(
            "button",
            name="Download Report"
        ).click()

    download = download_info.value

    download.save_as(
        f"downloads/{download.suggested_filename}"
    )
7

API Request Utility

API utilities can create test data before the UI test starts. This is often faster than creating the same data through the UI.

utils/api.py
def create_customer(request, name, email):
    response = request.post(
        "/api/customers",
        data={
            "name": name,
            "email": email
        }
    )

    assert response.ok
    return response.json()
8

API Response Utility

Centralize API response validation so that tests use consistent status and payload checks.

utils/api_assertions.py
def assert_success(response):
    assert response.ok
    assert 200 <= response.status < 300


def assert_json_contains(response, key):
    data = response.json()
    assert key in data
9

Element Interaction Utility

Create small reusable helpers for common interactions such as selecting rows, clicking actions or opening menus.

utils/elements.py
def click_button(page, button_name):
    page.get_by_role(
        "button",
        name=button_name
    ).click()


def click_link(page, link_name):
    page.get_by_role(
        "link",
        name=link_name
    ).click()
10

Form-Filling Utility

Forms such as registration, checkout and customer creation can use a common form utility.

utils/forms.py
def fill_customer_form(page, customer):
    page.get_by_label("First Name").fill(
        customer["first_name"]
    )

    page.get_by_label("Last Name").fill(
        customer["last_name"]
    )

    page.get_by_label("Email").fill(
        customer["email"]
    )

    page.get_by_role(
        "button",
        name="Save"
    ).click()
11

Assertion Utility

Common business validations can be centralized into reusable assertion functions.

utils/assertions.py
from playwright.sync_api import expect

def assert_order_created(page, order_number):
    expect(
        page.get_by_text(order_number)
    ).to_be_visible()
12

URL and Environment Utility

Keep environment-specific URLs outside test logic.

utils/config.py
import os

BASE_URL = os.getenv(
    "BASE_URL",
    "https://test.example.com"
)

def get_base_url():
    return BASE_URL
13

Browser Context Utility

Browser contexts allow tests to simulate different users, permissions and session configurations.

utils/context.py
def create_user_context(browser, storage_state=None):
    return browser.new_context(
        storage_state=storage_state
    )
14

Date and Time Utility

Centralize date generation for reports, bookings, subscriptions and transaction-related tests.

utils/datetime_helper.py
from datetime import datetime, timedelta

def future_date(days=7):
    return (
        datetime.now() +
        timedelta(days=days)
    ).strftime("%Y-%m-%d")
15

Logging Utility

Standardized logging makes CI/CD failures much easier to diagnose.

utils/logger.py
import logging

logger = logging.getLogger(__name__)

def log_step(message):
    logger.info("TEST STEP: %s", message)
16

Retry / Polling Utility

Polling is useful when an external system processes a request asynchronously.

utils/polling.py
import time

def wait_until(condition, timeout=30, interval=2):
    end_time = time.time() + timeout

    while time.time() < end_time:
        if condition():
            return True

        time.sleep(interval)

    raise TimeoutError(
        "Condition was not satisfied"
    )
Real-time use: Useful for background jobs, payment processing, order fulfillment and asynchronous API workflows.
17

Storage State Utility

Save authenticated browser state once and reuse it across tests when appropriate.

utils/auth_state.py
def save_auth_state(context):
    context.storage_state(
        path="playwright/.auth/user.json"
    )
18

Trace and Diagnostic Utility

Playwright tracing is extremely useful for debugging failures in CI environments.

utils/tracing.py
def start_trace(context):
    context.tracing.start(
        screenshots=True,
        snapshots=True,
        sources=True
    )


def stop_trace(context, path):
    context.tracing.stop(path=path)
19

Cleanup Utility

Test data should be removed after tests when the environment requires cleanup.

utils/cleanup.py
def delete_customer(request, customer_id):
    response = request.delete(
        f"/api/customers/{customer_id}"
    )

    assert response.ok
20

Composite Business Utility

The most powerful utilities combine multiple low-level actions into one business-level workflow.

utils/orders.py
def create_order(page, product_name, quantity):

    page.get_by_placeholder(
        "Search products"
    ).fill(product_name)

    page.get_by_text(product_name).click()

    page.get_by_label(
        "Quantity"
    ).fill(str(quantity))

    page.get_by_role(
        "button",
        name="Add to Cart"
    ).click()

    page.get_by_role(
        "button",
        name="Checkout"
    ).click()

    page.get_by_role(
        "button",
        name="Place Order"
    ).click()
Business-level thinking: A test should ideally say what it is doing from a business perspective rather than repeating many low-level UI actions.
✓

Quick Reference

Utility Real-Time Purpose
Login Utility Authenticate users
Navigation Utility Open common application pages
Wait Utility Synchronize with UI conditions
Screenshot Utility Capture evidence and failures
Upload Utility Upload documents and files
Download Utility Validate generated reports/files
API Utility Create and validate backend data
Form Utility Fill common application forms
Assertion Utility Centralize business validations
Environment Utility Handle different environments
Context Utility Handle users and browser sessions
Date Utility Generate dynamic test dates
Logging Utility Improve test diagnostics
Polling Utility Wait for asynchronous processing
Storage State Reuse authenticated sessions
Tracing Utility Debug CI failures
Cleanup Utility Remove test-created data
Business Utility Represent complete workflows
★

Test Utility Best Practices

⚡

Real-World Test Example

A well-designed test can combine several utilities while keeping the test itself short and readable.

tests/test_create_order.py
def test_create_order(page):

    login(
        page,
        "testuser@example.com",
        "Password123"
    )

    open_dashboard(page)

    create_order(
        page,
        "Laptop",
        2
    )

    assert_order_created(
        page,
        "ORD-10001"
    )
Key idea: The test describes the business workflow while the utilities contain the reusable implementation details.