Playwright Python - Expectations

Assertions and Expectations for Reliable End-to-End Tests

Real-Time Examples using Python + Playwright

What are Expectations in Playwright?

Expectations are assertions used to verify that the application behaves as expected during a test.

In Playwright Python, the most common expectation API is expect().

Basic idea:

Action → Application changes → Expectation verifies the result

Basic Expectation
from playwright.sync_api import expect

expect(page).to_have_title("My Application")

expect(page.locator("#username")).to_be_visible()
1 Basic expect()

Use expect() to verify the current state of a page or element.

Basic Example
from playwright.sync_api import expect

def test_home_page(page):

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

    expect(page).to_have_title("Example Domain")
Real-time scenario:

After opening an e-commerce website, verify that the correct page title is displayed.

2 Verify Page Title

to_have_title() verifies the browser page title.

Page Title Validation
expect(page).to_have_title("Amazon.in: Online Shopping")
Real-time example:

A smoke test opens the shopping website and confirms that the expected title is loaded.

3 Verify URL

Use to_have_url() to verify that navigation reached the expected URL.

URL Expectation
page.get_by_role("link", name="Login").click()

expect(page).to_have_url(
    "https://example.com/login"
)
Real-time scenario:

Click the Login link and verify that the application actually navigated to the login page.

4 Element Should Be Visible

to_be_visible() checks whether an element is visible to the user.

Visibility Check
expect(
    page.get_by_role("button", name="Login")
).to_be_visible()
Real-time scenario:

Before clicking Login, verify that the Login button is actually visible.

5 Element Should Be Hidden

Use to_be_hidden() when an element should not be visible.

Hidden Element
expect(
    page.locator(".loading-spinner")
).to_be_hidden()
Real-time scenario:

After an API request finishes, verify that the loading spinner disappears.

6 Verify Text

Use to_have_text() to verify the complete text of an element.

Text Expectation
expect(
    page.locator("h1")
).to_have_text("Dashboard")
Real-time scenario:

After successful login, verify that the dashboard heading says "Dashboard".

7 Verify Partial Text

Use to_contain_text() when the element contains additional dynamic text.

Partial Text
expect(
    page.locator(".message")
).to_contain_text("Order placed")
Example:

The application may display: "Order placed successfully. Order ID: 12345"

Instead of matching the entire dynamic message, verify only "Order placed".

8 Verify Input Value

Use to_have_value() to verify the value entered into an input field.

Input Value
page.get_by_label("Username").fill("john")

expect(
    page.get_by_label("Username")
).to_have_value("john")
Real-time scenario:

Verify that the username field contains the value entered by the test.

9 Verify Placeholder

Use to_have_attribute() to verify HTML attributes.

Placeholder Validation
expect(
    page.get_by_label("Email")
).to_have_attribute(
    "placeholder",
    "Enter your email"
)
10 Verify Checkbox

Use to_be_checked() to verify checkbox or radio-button state.

Checkbox Example
page.get_by_label("Accept Terms").check()

expect(
    page.get_by_label("Accept Terms")
).to_be_checked()
Real-time scenario:

On a registration page, verify that the Terms and Conditions checkbox has been selected.

11 Verify Enabled / Disabled

Use to_be_enabled() or to_be_disabled() to validate controls.

Button State
expect(
    page.get_by_role("button", name="Submit")
).to_be_disabled()

# After entering mandatory information

page.get_by_label("Name").fill("John")

expect(
    page.get_by_role("button", name="Submit")
).to_be_enabled()
Real-time scenario:

The Submit button should remain disabled until all required fields are completed.

12 Verify Element Count

Use to_have_count() when the number of matching elements matters.

Count Validation
products = page.locator(".product-card")

expect(products).to_have_count(10)
Real-time scenario:

Verify that a product search returns exactly 10 products on the first page.

13 Verify List Items

Playwright can verify text and state of individual items in a list.

List Validation
items = page.locator(".product-name")

expect(items).to_have_count(3)

expect(items.nth(0)).to_have_text("Laptop")

expect(items.nth(1)).to_have_text("Mouse")

expect(items.nth(2)).to_have_text("Keyboard")
14 Verify Table Data

Expectations are very useful for validating tables.

Table Validation
row = page.locator("tr").filter(
    has_text="John"
)

expect(row).to_contain_text("Completed")
expect(row).to_contain_text("₹5000")
Real-time scenario:

In an order-management system, find John's order and verify that the status is "Completed".

15 Verify Attribute

Use to_have_attribute() to validate attributes such as href, class, aria-label and data-*.

Attribute Expectation
login_link = page.get_by_role(
    "link",
    name="Login"
)

expect(login_link).to_have_attribute(
    "href",
    "/login"
)
16 Verify CSS Class

You can verify that an element contains an expected CSS class.

CSS Class Validation
expect(
    page.locator(".alert")
).to_have_class(
    "alert alert-success"
)
Real-time scenario:

After saving a record, verify that the application displays a success message instead of an error.

17 Verify API Response

Expectations can also be used with API responses.

API Response
response = page.request.get(
    "https://api.example.com/users/100"
)

expect(response).to_be_ok()

data = response.json()

assert data["id"] == 100
Real-time scenario:

Verify that an API returns HTTP 200 before validating the returned business data.

18 Verify After Login

A common real-world pattern is to combine actions with multiple expectations.

Login Test
def test_login(page):

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

    page.get_by_label("Username").fill("john")

    page.get_by_label("Password").fill("secret")

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

    expect(page).to_have_url(
        "https://example.com/dashboard"
    )

    expect(
        page.get_by_role("heading", name="Dashboard")
    ).to_be_visible()
Why this is useful:

The test verifies both navigation and the visible dashboard after authentication.

19 Soft Assertions

Soft assertions allow a test to continue after an expectation fails so that additional problems can be reported.

Soft Assertion
from playwright.sync_api import expect

expect(
    page.get_by_text("Profile")
).to_be_visible()

expect(
    page.get_by_text("Orders")
).to_be_visible()

expect(
    page.get_by_text("Settings")
).to_be_visible()
Important:

Playwright's normal expect() is a hard assertion: if it fails, the test normally stops at that assertion.

For true soft assertions in modern Playwright, use the supported soft-assertion API available in your installed version.

20 Combine Multiple Expectations

Real-world tests often validate several conditions after one business action.

Order Creation Example
def test_create_order(page):

    page.goto("https://shop.example.com")

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

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

    expect(
        page.get_by_text("Order placed successfully")
    ).to_be_visible()

    expect(
        page.get_by_test_id("order-status")
    ).to_have_text("Confirmed")

    expect(page).to_have_url(
        "https://shop.example.com/order-confirmation"
    )
Real-time business validation:

One test validates the success message, order status, and final URL after placing an order.

Quick Reference - Playwright Expectations
Expectation Purpose Example
to_be_visible() Element is visible Login button
to_be_hidden() Element is hidden Loading spinner
to_have_text() Exact text Dashboard heading
to_contain_text() Partial text Success message
to_have_value() Input value Username field
to_be_checked() Checkbox state Accept Terms
to_be_enabled() Control is enabled Submit button
to_be_disabled() Control is disabled Submit button
to_have_count() Element count Product list
to_have_attribute() HTML attribute href / placeholder
to_have_class() CSS class Success alert
to_have_url() Current URL Dashboard URL
to_have_title() Page title Application title
Best Practices for Expectations
1. Prefer user-facing assertions

Prefer role, label, text and other meaningful locators instead of fragile CSS selectors.

2. Avoid unnecessary sleeps

Do not use time.sleep() simply to wait for an element. Playwright expectations automatically wait for expected conditions.

3. Assert business outcomes

Do not only verify that a button was clicked. Verify what changed because of the click.

4. Use specific expectations

Instead of checking generic page text, verify the exact business condition that matters.

5. Do not over-assert

Too many unrelated assertions can make tests difficult to maintain. Focus on important behavior.

Real-Time End-to-End Example

A typical e-commerce checkout test can use expectations at every important business step.

Complete Example
from playwright.sync_api import expect


def test_checkout(page):

    # Open application
    page.goto("https://shop.example.com")

    # Verify home page
    expect(page).to_have_title(
        "Online Shopping"
    )

    # Search product
    page.get_by_placeholder(
        "Search products"
    ).fill("Laptop")

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

    # Verify search results
    expect(
        page.get_by_text("Laptop")
    ).to_be_visible()

    # Select product
    page.get_by_text(
        "Laptop Pro"
    ).click()

    # Verify product page
    expect(
        page.get_by_role(
            "heading",
            name="Laptop Pro"
        )
    ).to_be_visible()

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

    # Verify cart
    expect(
        page.get_by_text("Added to cart")
    ).to_be_visible()

    # Checkout
    page.get_by_role(
        "link",
        name="Checkout"
    ).click()

    # Verify checkout page
    expect(page).to_have_url(
        "https://shop.example.com/checkout"
    )

    # Place order
    page.get_by_role(
        "button",
        name="Place Order"
    ).click()

    # Final business validation
    expect(
        page.get_by_text(
            "Order placed successfully"
        )
    ).to_be_visible()

    expect(
        page.get_by_test_id("order-status")
    ).to_have_text("Confirmed")
Key idea:

A good Playwright test does not merely perform actions. It performs an action and then verifies the expected business outcome.

Action → Expectation → Action → Expectation