Skip to main content

Overview

Assertions verify that your tests produce expected results. Playwright provides two assertion styles: pytest assertions and Playwright’s web-first expect() assertions. Each has specific use cases and advantages.

Assertion Types

pytest Assertions

Traditional Python assertions using assert keyword. Best for simple checks and non-Playwright objects.

Playwright Expect

Web-first assertions with auto-waiting and retry logic. Best for UI element checks.

Basic pytest Assertions

Use standard Python assert statements for simple validations:
test_assertions.py (Lines 9-12)
# Basic assertions after login
assert page.locator('[data-test="title"]')
assert page.locator('[data-test="shopping-cart-link"]')
assert page.locator('[data-test="inventory-list"]')
# Check equality
assert page.url == "https://www.saucedemo.com/inventory.html"
assert user_id == 209
assert username == "standard_user"

# Check inequality
assert password != ""
assert status_code != 404

Playwright Web-First Assertions

Playwright’s expect() provides auto-waiting and retry logic, making tests more reliable:
test_functionalities.py (Lines 23-24)
from playwright.sync_api import expect

cart_page = CartPage(page)
cart_page.add_product("sauce-labs-backpack")
expect(cart_page.cart_badge).to_contain_text("2")
Auto-waiting: expect() automatically waits up to 5 seconds for the condition to be met, retrying until it passes or times out.

Visibility Assertions

Check if elements are visible or hidden:
test_functionalities.py (Lines 11-18)
def test_successful_login(page):
    login_page = LoginPage(page)
    login_page.navigate()
    login_page.login("standard_user", "secret_sauce")

    assert page.get_by_test_id("title").is_visible
# Element is visible
expect(page.locator("#welcome-message")).to_be_visible()

# Using pytest assert
assert page.locator("#welcome-message").is_visible()

Text Content Assertions

Verify element text content:
# Contains specific text
expect(cart_page.cart_badge).to_contain_text("2")

# Exact text match
expect(page.locator("h1")).to_have_text("Products")

# Text matches regex
expect(page.locator(".price")).to_have_text(/\$\d+\.\d{2}/)
to_contain_text() is case-sensitive. Use .lower() or regex patterns for case-insensitive matching.

CSS and Style Assertions

Validate element styling and CSS properties:
test_assertions.py (Lines 14-19)
# Check button colors before and after clicking
expect(page.locator('[data-test="add-to-cart-sauce-labs-backpack"]')).to_have_css(
    "color", "rgb(19, 35, 34)"
)
expect(page.locator('[data-test="add-to-cart-sauce-labs-backpack"]')).to_have_css(
    "background-color", "rgb(255, 255, 255)"
)

page.locator('[data-test="add-to-cart-sauce-labs-backpack"]').click()

# After clicking, button color changes
expect(page.locator('[data-test="remove-sauce-labs-backpack"]')).to_have_css(
    "color", "rgb(226, 35, 26)"
)
  • color: Text color (use RGB format)
  • background-color: Background color
  • display: Element display type (block, flex, none, etc.)
  • font-size: Text size
  • border: Border properties
  • opacity: Transparency level

URL Assertions

Verify navigation and URL changes:
test_login.py (Lines 19-20)
assert page.get_by_test_id("title").is_visible
assert page.url == login_dashboard
# Exact match
assert page.url == "https://www.saucedemo.com/inventory.html"

# Using expect
expect(page).to_have_url("https://www.saucedemo.com/inventory.html")

Element State Assertions

Check various element states:
# Element is enabled
expect(page.locator("#submit-button")).to_be_enabled()

# Element is disabled
expect(page.locator("#submit-button")).to_be_disabled()

Attribute Assertions

Validate HTML attributes:
# Has specific attribute value
expect(page.locator("a")).to_have_attribute("href", "/login")

# Attribute contains value
expect(page.locator("input")).to_have_attribute("class", /form-control/)

# Has attribute (any value)
expect(page.locator("img")).to_have_attribute("alt")

Count Assertions

Verify the number of matching elements:
# Exact count
expect(page.locator(".product-item")).to_have_count(6)

# At least/most
assert page.locator(".product-item").count() >= 1
assert page.locator(".error-message").count() == 0

Value Assertions

Check input field values:
# Input has specific value
expect(page.locator("#username")).to_have_value("standard_user")

# Empty input
expect(page.locator("#search")).to_have_value("")

# Using pytest
assert page.locator("#email").input_value() == "[email protected]"

API Response Assertions

Validate API responses in API tests:
test_API.py (Lines 33-36)
def test_create_user(api_context: APIRequestContext):
    response = api_context.post(
        "users/add",
        headers={"Content-Type": "application/json"},
        data={"firstName": "Damien", "lastName": "Smith", "age": 27}
    )
    
    user_data = response.json()
    assert user_data["id"] == 209
    assert user_data["firstName"] == "Damien"
# Success status
assert response.ok
assert response.status == 200

# Error status
assert response.status == 404
assert not response.ok

Negative Assertions

Invert any assertion using .not_:
# Element should NOT be visible
expect(page.locator(".error")).not_to_be_visible()

# Text should NOT be present
expect(page.locator("h1")).not_to_contain_text("Error")

# Element should NOT have class
expect(page.locator("button")).not_to_have_class("disabled")

# Using pytest
assert "error" not in page.url
assert not error_message.is_visible()

Custom Timeout

Adjust auto-wait timeout for specific assertions:
# Wait up to 10 seconds
expect(page.locator(".slow-loading")).to_be_visible(timeout=10000)

# Wait only 1 second
expect(page.locator(".fast-element")).to_be_visible(timeout=1000)

Assertion Best Practices

1

Use web-first assertions for UI

Prefer expect() for Playwright locators to get auto-waiting and retry logic
2

Use pytest assertions for simple checks

Use assert for URLs, API responses, and simple value comparisons
3

Be specific

Use precise assertions like to_have_text() instead of just to_be_visible()
4

Test negative cases

Verify elements are hidden or absent when expected
5

Add meaningful messages

Include custom messages for complex assertions to help debugging
When to use which?
  • Use expect() for Playwright locators and UI elements
  • Use assert for URLs, API responses, Python objects, and simple checks

Debugging Failed Assertions

When assertions fail, Playwright provides helpful error messages:
# Failed assertion output:
# AssertionError: Locator expected to be visible
# Locator: page.locator('#missing-element')
# Received: <not found>

# Add screenshots on failure (in conftest.py)
@pytest.fixture
def page(context):
    page = context.new_page()
    yield page
    if hasattr(page, '_test_failed'):
        page.screenshot(path=f"screenshots/{test_name}.png")

Next Steps

UI Testing

Learn comprehensive UI testing

API Testing

Test REST APIs effectively

Parametrization

Run tests with multiple datasets

Best Practices

Learn testing best practices

Build docs developers (and LLMs) love