💻 Проект по шагам

← К оглавлению урока

⚡ Структура проекта

shop_e2e/
├── pages/
│   ├── login_page.py
│   ├── inventory_page.py
│   ├── cart_page.py
│   └── checkout_page.py
├── tests/
│   └── test_order.py
└── conftest.py

Шаг 1. Классы страниц

# pages/inventory_page.py
from playwright.sync_api import Page

class InventoryPage:
    def __init__(self, page: Page):
        self.page = page
        self.items = page.locator(".inventory_item")
        self.cart_link = page.locator(".shopping_cart_link")
        self.cart_badge = page.locator(".shopping_cart_badge")

    def add_to_cart(self, name: str):
        self.items.filter(has_text=name) \
            .get_by_role("button", name="Add to cart").click()

    def go_to_cart(self):
        self.cart_link.click()
# pages/checkout_page.py
from playwright.sync_api import Page

class CheckoutPage:
    def __init__(self, page: Page):
        self.page = page
        self.first = page.get_by_placeholder("First Name")
        self.last = page.get_by_placeholder("Last Name")
        self.zip = page.get_by_placeholder("Zip/Postal Code")
        self.continue_btn = page.get_by_role("button", name="Continue")
        self.finish_btn = page.get_by_role("button", name="Finish")
        self.complete = page.get_by_text("Thank you for your order!")

    def fill_info(self, first, last, zip_code):
        self.first.fill(first)
        self.last.fill(last)
        self.zip.fill(zip_code)
        self.continue_btn.click()

    def finish(self):
        self.finish_btn.click()

Шаг 2. conftest.py — авторизация и фикстуры

# conftest.py
import pytest
from pages.inventory_page import InventoryPage
from pages.cart_page import CartPage
from pages.checkout_page import CheckoutPage

@pytest.fixture(scope="session")
def storage_state(browser, tmp_path_factory):
    path = tmp_path_factory.mktemp("auth") / "state.json"
    ctx = browser.new_context()
    page = ctx.new_page()
    page.goto("https://www.saucedemo.com/")
    page.get_by_placeholder("Username").fill("standard_user")
    page.get_by_placeholder("Password").fill("secret_sauce")
    page.get_by_role("button", name="Login").click()
    page.wait_for_url("**/inventory.html")
    ctx.storage_state(path=str(path))
    ctx.close()
    return str(path)

@pytest.fixture
def browser_context_args(browser_context_args, storage_state):
    return {**browser_context_args, "storage_state": storage_state}

@pytest.fixture
def inventory_page(page):
    page.goto("https://www.saucedemo.com/inventory.html")
    return InventoryPage(page)

Шаг 3. E2E-тест полного заказа

# tests/test_order.py
from playwright.sync_api import expect
from pages.cart_page import CartPage
from pages.checkout_page import CheckoutPage

def test_full_order(page, inventory_page):
    # 1. добавляем товар, проверяем бейдж
    inventory_page.add_to_cart("Sauce Labs Backpack")
    expect(inventory_page.cart_badge).to_have_text("1")

    # 2. идём в корзину, проверяем состав
    inventory_page.go_to_cart()
    cart = CartPage(page)
    expect(cart.items).to_have_count(1)
    cart.checkout()

    # 3. заполняем данные доставки
    checkout = CheckoutPage(page)
    checkout.fill_info("Иван", "Петров", "12345")

    # 4. завершаем и проверяем подтверждение
    checkout.finish()
    expect(checkout.complete).to_be_visible()

Шаг 4. Data-driven

import pytest
from playwright.sync_api import expect

@pytest.mark.parametrize("product", [
    "Sauce Labs Backpack",
    "Sauce Labs Bike Light",
    "Sauce Labs Bolt T-Shirt",
])
def test_add_each_product(inventory_page, product):
    inventory_page.add_to_cart(product)
    expect(inventory_page.cart_badge).to_have_text("1")

Запуск: pytest --base-url https://www.saucedemo.com --tracing=retain-on-failure -n auto

⚠️ CartPage здесь предполагается с items и методом checkout() — допишете в заданиях. Локаторы сверяйте через codegen.