Skip to content

ChandeDeVargas/ui-testing-playwright

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

7 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

UI Testing with Playwright - Selector-Focused Automation

Playwright Python Pytest

"Good automation doesn't break. It uses stable selectors and validates real bugs."


🎯 Project Purpose

This project demostrates practical UI automation for the [SAUCEDEMO] (https://www.saucedemo.com) e-commerce site.

This is NOT about:

  • 50+ test cases
  • Showing off unnecessary framework knowledge
  • Over-engineering with complex custom wrappers

This IS about:

  • Stable selectors that don't break (data-test > id class)
  • Independet tests that can run in any order
  • Smart waits (no time.sleep() , only expect())
  • Bug-focused assertions (each assert detects a specific bug)

πŸ—‚οΈ Project Structure

ui-testing-playwright/
β”œβ”€β”€ pages/
β”‚   β”œβ”€β”€ cart_page.py           # Cart locators & actions
β”‚   β”œβ”€β”€ inventory_page.py      # Inventory locators & actions
β”‚   └── login_page.py          # Login locators & actions
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ conftest.py            # Shared fixtures (POM initialization)
β”‚   β”œβ”€β”€ test_login.py          # Authentication tests (3 tests)
β”‚   β”œβ”€β”€ test_products.py       # Product catalog tests (3 tests)
β”‚   └── test_cart.py           # Shopping cart tests (4 tests)
β”œβ”€β”€ utils/
β”‚   └── test_data.py           # Test credentials (users)
β”œβ”€β”€ .gitignore
β”œβ”€β”€ pytest.ini
β”œβ”€β”€ requirements.txt
└── README.md

Total: 10 focused tests covering critical user flows


πŸ”‘ Key Principles

1. Selector Stability (Most Important)

Priority order:

# βœ… BEST: data-test attributes (semantic, stable)
page.locator('[data-test="login-button"]').click()

# βœ… GOOD: ID (unique, stable)
page.locator('#react-burger-menu-btn').click()

# ⚠️ OK: Short CSS class (acceptable if stable)
page.locator('.shopping_cart_badge').text()

# ❌ BAD: Long CSS chains (fragile)
page.locator('div.login-container > form > button').click()

# ❌ WORSE: Text selectors (changes with i18n)
page.locator('text=Login').click()

Real example from this project:

# ❌ Fragile selector (breaks if CSS changes)
page.locator('.inventory_item .btn_inventory').click()

# βœ… Stable selector (semantic, won't break)
page.locator('[data-test="add-to-cart-sauce-labs-backpack"]').click()

2. No Artificial Waits

Never do this:

# ❌ BAD: Arbitrary waits (slow, unreliable)
page.click('#login-button')
time.sleep(3)  # Hope page loads in 3 seconds?
assert page.locator('.title').is_visible()

Always do this:

# βœ… GOOD: Smart waits (fast, reliable)
page.click('[data-test="login-button"]')
expect(page.locator('[data-test="title"]')).to_be_visible()

Playwright automatically waits for elements. Trust it.


3. Test Independence

Every test can run alone:

# βœ… GOOD: Uses fixture, gets fresh login state
def test_add_product_to_cart(logged_in_page: Page):
    page = logged_in_page
    # Test starts already logged in
    page.locator('[data-test="add-to-cart-sauce-labs-backpack"]').click()
    expect(page.locator('[data-test="shopping-cart-badge"]')).to_have_text('1')

Why this matters:

  • Tests can run in any order
  • Can run single test for debugging
  • Parallel execution works reliably

4. Bug-Focused Assertions

Each assertion validates a specific bug:

def test_login_with_valid_credentials(page: Page):
    page.goto("https://www.saucedemo.com")
    page.locator('[data-test="username"]').fill('standard_user')
    page.locator('[data-test="password"]').fill('secret_sauce')
    page.locator('[data-test="login-button"]').click()

    # Assert 1: Redirected to correct page
    # Bug caught: Wrong redirect (e.g., stays on login page)
    expect(page).to_have_url(re.compile(r".*/inventory.html"))

    # Assert 2: Products page title visible
    # Bug caught: Page loads but content doesn't render
    expect(page.locator('[data-test="title"]')).to_have_text('Products')

Generic assertions don't help:

# ❌ BAD: What bug does this catch?
assert True

# ❌ BAD: Too vague
assert page.locator('.title').is_visible()

# βœ… GOOD: Specific, explains what breaks
expect(page.locator('[data-test="title"]')).to_have_text('Products')

πŸ§ͺ Test Coverage

Login Tests (test_login.py)

Test Purpose Bug Detected
Valid credentials Successful login redirects to inventory Login doesn't redirect
Invalid credentials Error message appears No error feedback
Locked user Locked user cannot login Security bypass

Key validations:

  • βœ… URL redirects correctly
  • βœ… Error messages display
  • βœ… User stays on login page when auth fails

Product Tests (test_products.py)

Test Purpose Bug Detected
Products display Inventory page shows 6 products Empty catalog
Add single product Cart badge shows "1" Badge doesn't update
Add multiple products Cart badge shows "3" Counter broken

Key validations:

  • βœ… Product count is correct (detects missing items)
  • βœ… Cart badge appears and increments
  • βœ… Page title confirms correct page

Cart Tests (test_cart.py)

Test Purpose Bug Detected
Product appears in cart Added item shows in cart Data loss
Remove product Item disappears from cart Remove button broken
Empty cart Removing all items clears badge Badge persists
Cart persistence (advanced) Cart survives logout/login Session bug

Key validations:

  • βœ… Items added to cart are visible
  • βœ… Badge disappears when cart empty
  • βœ… Cart state persists across sessions

πŸš€ Getting Started

Prerequisites

  • Python 3.8 or higher
  • pip
  • Playwright

Installation

  1. Clone repository:
   git clone https://github.com/your-username/ui-testing-playwright.git
   cd ui-testing-playwright
  1. Create virtual environment:
   python -m venv venv

   # Windows
   venv\Scripts\activate

   # Linux/Mac
   source venv/bin/activate
  1. Install dependencies:
   pip install -r requirements.txt
   playwright install chromium

▢️ Running Tests

Run all tests:

pytest tests/ -v

Run specific file:

pytest tests/test_login.py -v

Run single test:

pytest tests/test_cart.py::test_product_appears_in_cart -v

Run with headed browser (visible):

pytest tests/ -v --headed

Run with slowmo (debugging):

pytest tests/ -v --headed --slowmo=1000

πŸ“Š Example Test Output

tests/test_login.py::test_login_with_valid_credentials PASSED
tests/test_login.py::test_login_with_invalid_credentials PASSED
tests/test_login.py::test_login_with_locked_user PASSED
tests/test_products.py::test_products_page_displays_correctly PASSED
tests/test_products.py::test_add_single_product_to_cart PASSED
tests/test_products.py::test_add_multiple_products_to_cart PASSED
tests/test_cart.py::test_product_appears_in_cart PASSED
tests/test_cart.py::test_remove_product_from_cart PASSED
tests/test_cart.py::test_cart_is_empty_after_removing_all_items PASSED
tests/test_cart.py::test_cart_persists_after_logout_login PASSED

======================== 10 passed in 15.23s ========================

πŸŽ“ What This Project Demonstrates

QA Skills:

  • βœ… Choosing stable selectors (prevents flaky tests)
  • βœ… Writing independent tests (parallel execution)
  • βœ… Bug-focused testing (each assert has purpose)
  • βœ… Avoiding common pitfalls (no sleep, no text selectors)

Technical Skills:

  • βœ… Playwright with Python
  • βœ… Pytest framework and fixtures
  • βœ… Test organization and structure
  • βœ… Async/await patterns (handled by Playwright)

NOT Demonstrated (Intentionally):

  • ❌ Custom framework abstractions (over-engineering)
  • ❌ 50+ test cases (quality > quantity)
  • ❌ Advanced Playwright configurations (keep it simple)

βœ… Highlighted Feature: Page Object Model (POM)

This project has been refactored to implement a clean Page Object Model layer under the pages/ directory.

Why? Separating locators and action logic from test code prevents test fragility. If a locator changes on the site, we only fix it in the Page Class without modifying test assertions.

# βœ… Clean test interacting with Page Objects
def test_login_with_valid_credentials(page: Page, login_page: LoginPage, inventory_page: InventoryPage):
    login_page.navigate()
    login_page.login(USERS['standard']['username'], USERS['standard']['password'])

    # Assert 1: Redirected to correct page
    expect(page).to_have_url(re.compile(r".*/inventory.html"))

    # Assert 2: Products page title visible
    expect(inventory_page.title).to_have_text('Products')

No CI/CD Pipeline

Why? This project focuses on selector quality and test design, not DevOps.

If you need CI/CD: See my other projects (TODO API, Postman Newman).


No Screenshot Automation

Why? Visual testing isn't the focus here.

If screenshot fails: Test fails. That's enough.


πŸ” Common Pitfalls Avoided

1. Fragile Selectors

# ❌ BAD: Breaks when CSS changes
page.locator('div.inventory > div:nth-child(1) > button').click()

# βœ… GOOD: Semantic, won't break
page.locator('[data-test="add-to-cart-sauce-labs-backpack"]').click()

2. Test Dependencies

# ❌ BAD: test_add_to_cart depends on test_login running first
def test_login():
    # Login here

def test_add_to_cart():
    # Assumes already logged in from test_login

# βœ… GOOD: Each test is independent
def test_add_to_cart(logged_in_page: Page):
    # Gets fresh login state via fixture

3. Artificial Waits

# ❌ BAD: Slow and unreliable
page.click('#submit')
time.sleep(5)
assert page.locator('.success').is_visible()

# βœ… GOOD: Fast and reliable
page.click('#submit')
expect(page.locator('.success')).to_be_visible()

πŸ“š Resources


πŸ‘€ Chande De Vargas GitHub: https://github.com/ChandeDeVargas LinkedIn: https://www.linkedin.com/in/chande-de-vargas-b8a51838a/


πŸ“„ License

This project is open source and available under the MIT License.


⭐ If this project helps you write better UI tests, give it a star!

About

This repository showcases a professional UI automation framework built with Playwright and Python. Focused on the SauceDemo e-commerce application, it includes comprehensive test coverage for user authentication (including negative scenarios), product management, and shopping cart functionality, emphasizing maintenance, reliability.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages