Page Object Model на Playwright
Идея та же, что в уроке 11: каждая страница — класс, локаторы хранятся в одном месте, тесты вызывают методы. Отличие — вместо driver.find_element используются Locator-ы, объявленные в конструкторе.
# pages/login_page.py
from playwright.sync_api import Page
class LoginPage:
def __init__(self, page: Page):
self.page = page
self.username = page.get_by_placeholder("Username")
self.password = page.get_by_placeholder("Password")
self.login_btn = page.get_by_role("button", name="Login")
def open(self):
self.page.goto("/") # относительный путь — работает с base_url
def login(self, user: str, pwd: str):
self.username.fill(user)
self.password.fill(pwd)
self.login_btn.click()
__init__ один раз, даже до загрузки страницы. Реальный поиск произойдёт при действии.
Фикстуры pytest-playwright
Плагин даёт готовые фикстуры. Главное — они изолируют тесты: на каждый тест создаётся свежий context и page.
| Фикстура | Назначение |
|---|---|
page | Вкладка (на каждый тест новая) |
context | Изолированная сессия теста |
browser | Браузер (на всю сессию) |
browser_context_args | Настройки контекста (viewport, locale, storage_state…) |
# conftest.py
import pytest
@pytest.fixture(scope="session")
def browser_context_args(browser_context_args):
return {**browser_context_args, "viewport": {"width": 1440, "height": 900}}
# своя фикстура страницы логина
@pytest.fixture
def login_page(page):
from pages.login_page import LoginPage
return LoginPage(page)
Базовый URL задаётся флагом --base-url (тогда в коде — относительные пути page.goto("/inventory")).
Трассировка и отладка
Trace — это запись всего прогона: снимки DOM на каждом шаге, действия, сеть, консоль. Открывается в Trace Viewer.
# записывать трассировку только для упавших тестов
pytest --tracing=retain-on-failure
# открыть результат
playwright show-trace test-results/.../trace.zip
Также доступны --video=retain-on-failure и --screenshot=only-on-failure.
retain-on-failure и сохраняйте папку артефактов — по трассировке падение чинится за минуты.
Параллельный запуск
Так как тесты изолированы контекстами, их легко гонять параллельно через pytest-xdist:
pip install pytest-xdist
pytest -n auto # по числу ядер
pytest -n 4 # 4 воркера
Условие — тесты независимы (не делят глобальное состояние, не зависят от порядка).
Мостик к API: APIRequestContext
Playwright умеет ходить в REST API без браузера — удобно готовить данные для UI-теста или проверять результат через API.
# подготовить данные через API, проверить в UI
def test_setup_via_api(api_request_context, page):
api_request_context.post("/issues", data={"title": "Bug"})
page.goto("/issues")
expect(page.get_by_text("Bug")).to_be_visible()