Автоматизация тестирования на Python: гайд по Pytest и Playwright

📝 Кратко: Современная автоматизация тестирования на Python требует инструментов, способных обрабатывать сложные SPA и динамический контент. Мы научимся объединять мощь Playwright с гибкостью Pytest, настраивать профессиональные отчеты Allure и запускать тесты в несколько потоков для максимальной эффективности.
Иллюстрация к руководству по автоматизации тестирования на Python с использованием связки Pytest и Playwright.

Всем привет! Если вы уже пробовали писать скрипты для парсинга, то знаете, насколько мощным инструментом может быть браузерная автоматизация. Но сегодня я хочу предложить вам взглянуть на этот процесс под другим углом. Мы часто используем код, чтобы собрать данные, но не менее важно уметь проверять, насколько стабильно работают наши собственные (или чужие) веб-сервисы. В этой статье мы разберем, как автоматизация тестирования на Python превращается из простого набора скриптов в профессиональную систему с помощью связки Pytest и Playwright. Я поделюсь своим опытом настройки этой среды, чтобы ваши тесты были быстрыми, надежными и понятными.

Почему связка Pytest и Playwright — это стандарт в 2026 году?

Долгое время королем автоматизации был Selenium, но времена меняются. Сегодня веб-приложения стали невероятно сложными, с кучей асинхронных запросов и динамических элементов. Playwright от Microsoft пришел в этот мир, чтобы решить главные «боли» QA-инженеров: нестабильность тестов (flaky tests) и медленную скорость работы. Он нативно поддерживает асинхронность и умеет «ждать» появления элементов без костылей в виде time.sleep().

Однако сам по себе Playwright — это просто инструмент управления браузером. Чтобы превратить его в полноценный тестовый фреймворк, нам нужен Pytest. Это самый популярный движок для тестов в экосистеме Python. Он берет на себя все организационные вопросы: поиск тестовых функций, запуск проверок, управление состоянием через фикстуры и интеграцию с внешними плагинами. Если вы уже читали мою статью про автоматизацию браузера на Python через Playwright, то база у вас уже есть.

Использование этой связки позволяет сократить время разработки тестов в разы. Вместо того чтобы писать сотни строк кода для авторизации или перехода по страницам, мы можем использовать мощные абстракции. Это особенно актуально, когда вы тестируете сложные системы, например, созданные с помощью FastAPI Python, где фронтенд и бэкенд тесно связаны.

Установка и базовая настройка окружения

Прежде чем начнется настоящая автоматизация тестирования на Python, нам нужно подготовить фундамент. Нам понадобятся три основных компонента: Python, плагин pytest-playwright и браузерные бинарные файлы. Я всегда рекомендую использовать виртуальные окружения.

Для установки лучше всего использовать менеджер пакетов uv, который справится с задачей мгновенно:

# Устанавливаем pytest и официальный плагин
pip install pytest-playwright allure-pytest

# Загружаем браузеры
playwright install chromium

📚 Документация: Playwright Python Intro
«Плагин Pytest для Playwright — это рекомендуемый способ написания сквозных (end-to-end) тестов. Он предоставляет изолированные контексты браузера для каждого теста прямо „из коробки“, что гарантирует чистоту и независимость проверок.»

Фикстуры: сердце профессионального тестирования

Фикстуры (fixtures) в Pytest — это функции, которые подготавливают среду для тестов. Представьте, что для каждого теста вам нужно авторизоваться. Писать логин/пароль в каждом файле — плохая практика. О том, как писать структурированный код, я упоминал в статье про чистый и читаемый код на Python.

Пример создания фикстуры авторизации

Мы будем использовать реальный демо-сайт the-internet.herokuapp.com. Создадим фикстуру, которая будет выполнять вход в систему перед началом теста.

import pytest
from playwright.sync_api import Page

@pytest.fixture
def login_user(page: Page):
    # Предусловие: логинимся
    page.goto("https://the-internet.herokuapp.com/login")
    page.fill("#username", "tomsmith")
    page.fill("#password", "SuperSecretPassword!")
    page.click("button[type='submit']")
    yield page  # Здесь начинается выполнение самого теста
    # Постусловие: например, логаут или чистка куки
    print("\nТест завершен, контекст очищен")

Написание теста с использованием Web-First Assertions

В Playwright есть концепция «Web-First Assertions». Это умные проверки, которые сами ждут, пока элемент примет нужное состояние. Это избавляет от 99% ошибок, связанных с тем, что «кнопка еще не прогрузилась». Если вы часто сталкиваетесь с ошибками загрузки, загляните в наш гайд про 10 ошибок новичков в Python.

from playwright.sync_api import expect

def test_login_success_message(login_user):
    page = login_user
    # Проверяем наличие сообщения об успехе
    # expect будет ждать появления элемента до 5 секунд (по умолчанию)
    success_msg = page.locator("#flash")
    expect(success_msg).to_contain_text("You logged into a secure area!")

Параллельный запуск и отчеты Allure

Автоматизация тестирования на Python должна быть быстрой, и если у вас 100 тестов, запускать их по очереди — преступление против вашего времени. Мы используем плагин pytest-xdist для параллельного запуска.

# Запуск в 3 потока
pytest -n 3

Чтобы сделать отчеты понятными даже для не-программистов, мы интегрируем Allure. Он покажет шаги теста, скриншоты ошибок и время выполнения.

import allure

@allure.feature("Панель управления")
def test_secure_page_ui(login_user):
    with allure.step("Проверка URL после логина"):
        expect(login_user).to_have_url("https://the-internet.herokuapp.com/secure")

Чтобы сгенерировать отчет, запустите тесты с флагом --alluredir=results, а затем выполните allure serve results. Если в процессе тестов вам нужно будет сохранять файлы, посмотрите статью про автоматическое скачивание через Playwright.

Полный код проекта (Демо: the-internet.herokuapp.com)

Ниже представлен готовый файл test_web.py, который вы можете запустить прямо сейчас. Он демонстрирует работу с авторизацией, проверку чекбоксов и работу с динамическим контентом.

import pytest
import allure
import sys
from playwright.sync_api import Page, expect

# 1. ФИКСТУРА: Подготовка страницы с авторизацией
@pytest.fixture(scope="function")
def authenticated_page(page: Page):
    with allure.step("Переход на страницу входа и авторизация"):
        page.goto("https://the-internet.herokuapp.com/login")
        page.fill("#username", "tomsmith")
        page.fill("#password", "SuperSecretPassword!")
        page.click("button[type='submit']")
        
        # Умная проверка: ждем, пока появится сообщение об успехе
        expect(page.locator("#flash")).to_be_visible()
    yield page # Передаем готовую страницу в тесты, которые используют эту фикстуру
    # Здесь можно добавить код очистки (например, удаление данных)

# 2. ТЕСТ: Успешный логин (использует фикстуру authenticated_page)
@allure.suite("Тесты авторизации")
@allure.title("Успешный вход в защищенную зону")
def test_successful_login(authenticated_page: Page):
    with allure.step("Проверка текста приветствия"):
        # Expect сам будет ждать появления текста до 5 секунд
        expect(authenticated_page.locator("h2")).to_have_text("Secure Area")

# 3. ТЕСТ: Работа с чекбоксами (использует стандартную фикстуру page)
@allure.suite("Тесты интерфейса")
@allure.title("Взаимодействие с чекбоксами")
def test_checkboxes(page: Page):
    with allure.step("Открытие страницы с чекбоксами"):
        page.goto("https://the-internet.herokuapp.com/checkboxes")
    
    # Находим первый чекбокс через локатор
    checkbox1 = page.locator("input[type='checkbox']").first
    
    with allure.step("Установка галочки"):
        checkbox1.check()
        expect(checkbox1).to_be_checked()

# 4. ТЕСТ: Динамическое ожидание
@allure.suite("Тесты динамики")
@allure.title("Ожидание загрузки элемента")
def test_dynamic_wait(page: Page):
    with allure.step("Запуск процесса загрузки"):
        page.goto("https://the-internet.herokuapp.com/dynamic_loading/1")
        page.click("button")
    
    with allure.step("Ожидание появления текста 'Hello World!'"):
        # Этот элемент появляется не сразу, Playwright дождется его автоматически
        finish_text = page.locator("#finish h4")
        expect(finish_text).to_have_text("Hello World!")

# =========================================================
# БЛОК ЗАПУСКА (то, чего не хватало для запуска через кнопку)
# =========================================================
if __name__ == "__main__":
    # Аргументы запуска: 
    # -v (подробный вывод)
    # --headed (показать браузер, иначе запустится в фоне)
    # --alluredir (папка для отчетов Allure)
    sys.exit(pytest.main(["-v", "--headed", "--alluredir=allure-results", __file__]))

Разбор ключевых моментов:

  1. Локаторы: Мы используем #id и input[type='checkbox']. Это стабильные селекторы.
  2. Expect: Все проверки идут через expect. Это «умные» ассерты.
  3. Изоляция: Каждый тест получает чистый объект page, что исключает влияние тестов друг на друга. Если вам нужно обходить сложные защиты в тестах, изучите как обойти Cloudflare на Python.
  4. Как запустить этот код?
    Есть два способа, и теперь оба будут работать:

    Способ А (Через терминал): Просто напишите в консоли: pytest --headed test_web.py. Фреймворк сам найдет все функции с префиксом test_ и выполнит их.

    Способ Б (Нажатием кнопки «Run» в IDE): Благодаря блоку if __name__ == "__main__":, вы можете запустить файл как обычный скрипт. Команда pytest.main() сама инициирует процесс тестирования внутри вашей среды.
  5. Что делает блок запуска?
    pytest.main([...]) — это программный вызов Pytest. Он заменяет ввод команд в консоли.

    --headed — критически важный параметр. Без него браузер запустится в «фоновом» режиме, и вы не увидите, как Playwright кликает по кнопкам.

    __file__ — указывает Pytest, что нужно запустить тесты именно в этом текущем файле.
  6. Почему функции не вызываются по порядку?
    В автоматизации тестирования на Python функции не вызывают друг друга. Pytest работает как диспетчер: он видит функции test_..., создает для каждой изолированную вкладку браузера (через фикстуру page) и запускает их. Если вам нужно, чтобы один тест зависел от другого (например, сначала логин, потом настройки), вы используете фикстуры (как authenticated_page в примере), которые готовят состояние страницы перед тестом.

Заключение

Автоматизация тестирования на Python — это инвестиция, которая окупается стабильностью вашего проекта. Используя Pytest и Playwright, вы получаете мощную систему, которая не боится динамических сайтов и легко масштабируется. Не забывайте про отчеты Allure и фикстуры — они делают ваш код профессиональным и понятным. Если вам нужно работать с API в рамках тестов, обязательно почитайте про работу с API на Python.

🔁 Другие крутые фишки автоматизации браузера:
Автоматическое заполнение форм — как научить скрипт работать с инпутами и кнопками
Обход Cloudflare и защиты от ботов — критически важный навык для любого автоматизатора в 2026 году
Автоматическое скачивание файлов — учим скрипт сохранять отчеты и документы на диск
💬 Остались вопросы? Пишите в комментариях — с радостью уточню, дополню или помогу с вашим кодом.
📢 Подписывайтесь на Telegram-канал PythonAuto, чтобы не пропустить новые гайды по автоматизации, парсингу и разные трюки на Python.
👉 Ваш интерес — лучшая мотивация для новых статей!

Оставьте комментарий