1. Введение в мокирование: роль изоляции в архитектуре автоматизированных тестов
Введение в мокирование: роль изоляции в архитектуре автоматизированных тестов
Представьте, что вы тестируете функционал оформления заказа в крупном интернет-магазине. Для успешного прохождения сценария вам нужно: авторизоваться, выбрать товар, который есть в наличии на складе, применить действующий промокод, выбрать доступный пункт выдачи и, наконец, провести оплату через внешний банковский шлюз. В понедельник утром тест падает, потому что база данных склада ушла на техническое обслуживание. В обед он падает снова, так как тестовый промокод истек. К вечеру — третья неудача: банковский шлюз в песочнице (sandbox) вернул ошибку 503. В итоге за весь день вы не проверили ни строчки собственного кода фронтенда, потратив часы на выяснение причин во внешних системах.
Эта ситуация — классический пример «хрупких тестов» (flaky tests), которые зависят от факторов, находящихся вне зоны контроля тестировщика. Именно здесь на сцену выходит концепция изоляции и мокирования.
Философия изоляции в автоматизации
В современной разработке программное обеспечение редко представляет собой монолит. Чаще это созвездие микросервисов, сторонних API, баз данных и облачных функций. Когда мы пишем автоматизированный тест, перед нами всегда стоит выбор: проверять всю цепочку взаимодействий целиком (End-to-End или E2E) или изолировать тестируемый компонент от его окружения.
Изоляция — это процесс отделения тестируемой системы (System Under Test, SUT) от её зависимостей. Если мы тестируем фронтенд-приложение, нашими зависимостями являются бэкенд-сервисы и сторонние интеграции.
Почему реальные данные — это не всегда хорошо?
Многие начинающие автоматизаторы стремятся к «максимальной реалистичности», полагая, что тесты на реальных данных надежнее. Однако на практике полная зависимость от бэкенда в UI-тестах порождает ряд критических проблем:
Мокирование (Mocking) — это техника, позволяющая заменить реальный ответ сервера заранее подготовленными данными, которые перехватываются на уровне сетевого уровня браузера.
Моки, стабы и спаи: разбираемся в терминологии
В профессиональной среде часто используют термины «мок», «стаб» и «дублер» как синонимы, но для качественного проектирования тестов важно понимать нюансы. Профессор Джерард Месарош в своей книге «Шаблоны тестирования xUnit» выделяет несколько типов тестовых дублеров (Test Doubles).
Dummy (Пустышка)
Объекты, которые передаются в методы, но никогда не используются. В контексте сетевых запросов это может быть пустой JSON-ответ для запроса, результат которого не важен для текущего теста, но необходим, чтобы приложение не «упало» с ошибкой.Stub (Заглушка)
Стаб предоставляет заранее определенные ответы на вызовы во время теста. Если приложение запрашивает профиль пользователя, стаб всегда вернет:Стабы не меняют своего поведения в зависимости от входных параметров и не проверяют, как именно их вызвали.
Mock (Мок)
Это более сложный инструмент. Моки настраиваются так, чтобы они ожидали определенных вызовов. Они могут проверять: * Был ли вызван конкретный URL? * Какие параметры были переданы в теле POST-запроса? * Сколько раз произошел вызов?В Playwright грань между стабом и моком размыта, так как API page.route() позволяет одновременно и подменять данные (stubbing), и проверять факты взаимодействия (mocking).
Spy (Шпион)
Шпионы записывают информацию о вызовах, не подменяя реализацию. В тестировании UI это используется редко, так как обычно нам важнее именно контроль над данными, но иногда полезно «подсмотреть», ушел ли запрос на аналитику, не прерывая его выполнение.Архитектурное место мокирования в пирамиде тестирования
Чтобы понять, когда использовать мокирование в Playwright, нужно взглянуть на пирамиду тестирования. Традиционно UI-тесты находятся на её вершине и считаются самыми дорогими. Однако использование моков позволяет сдвинуть часть этих тестов «ниже», делая их более похожими на интеграционные тесты фронтенда.
> «Мокирование превращает нестабильный E2E-тест в контролируемый контрактный тест пользовательского интерфейса».
Рассмотрим три стратегии:
В рамках этого курса мы сфокусируемся на третьем варианте — UI-изоляции. Это мощнейший инструмент в руках QA-инженера, позволяющий тестировать интерфейс в «лабораторных условиях».
Преимущества мокирования для QA-инженера
1. Тестирование негативных сценариев
Попробуйте заставить реальный банковский сервер вернуть ошибку «Карта просрочена» ровно в 15:00. Это сложно. С моками в Playwright это занимает одну строку кода:route.fulfill({ status: 402, body: JSON.stringify({ error: 'Card Expired' }) });
Вы можете имитировать 404 (не найдено), 500 (ошибка сервера), 403 (нет доступа) и проверять, как UI обрабатывает эти ситуации: рисует ли он красивые «пустые состояния» или падает в «белый экран».2. Моделирование редких состояний данных
Представьте задачу: проверить отображение списка транзакций, если их больше 1000 (пагинация) и если их ровно 0. Вместо того чтобы наполнять базу данных тысячами записей, вы просто подменяете JSON-ответ. Вы можете создать «идеального пользователя», у которого заполнены все поля профиля, и «минималистичного пользователя» без аватара и описания, чтобы проверить верстку.3. Независимость от готовности бэкенда
Часто разработка фичи на фронтенде идет параллельно с бэкендом. Если контракт (формат данных) уже согласован, вы можете начать писать автотесты на еще не существующий функционал, используя моки. Когда бэкенд будет готов, вам останется только включить интеграционные тесты.4. Ускорение цикла обратной связи (Feedback Loop)
Тесты с моками выполняются в разы быстрее. Это позволяет запускать их на каждый коммит в Git, обеспечивая разработчиков мгновенной информацией о том, не сломали ли они UI.Риски и ограничения: когда моки могут навредить
Было бы непрофессионально утверждать, что мокирование — это серебряная пуля. У этого подхода есть существенный риск: ложноположительные результаты.
Представьте, что бэкенд-разработчики изменили формат ответа: поле user_name превратилось в fullName. Если ваши тесты используют старые моки, где всё еще user_name, тесты будут успешно проходить. При этом в реальности приложение сломается, так как фронтенд не найдет нужного поля.
Для минимизации этого риска используются следующие подходы: * Контрактное тестирование: Отдельные тесты проверяют, что реальный бэкенд возвращает данные именно в том формате, который мы используем в моках. * Гибридная стратегия: 80% тестов — быстрые и изолированные (с моками), 20% — полноценные E2E (без моков) для проверки критических путей (Smoke-тесты).
Как Playwright работает с сетью (общий обзор)
Playwright оперирует на уровне протокола CDP (Chrome DevTools Protocol) или аналогичных механизмов в других браузерах. Это позволяет ему вставать «посередине» между движком браузера и сетевой картой.
Когда браузер пытается отправить запрос, Playwright перехватывает его. В этот момент у нас есть три пути:
Этот механизм работает крайне эффективно, так как не требует установки прокси-серверов или изменения кода самого приложения. Приложение даже не «подозревает», что данные, которые оно получило, ненастоящие.
Практический пример: от хаоса к порядку
Рассмотрим кейс: страница личного кабинета, где отображается баланс пользователя.
Без мокирования:
GET /api/v1/balance уходит на сервер. 100.00');.Изоляция как стандарт индустрии
В крупных технологических компаниях (Google, Meta, Яндекс) изоляция тестов является обязательным требованием. Это связано с тем, что инфраструктурные расходы на поддержание «всегда работающего» тестового окружения для тысяч разработчиков колоссальны. Мокирование позволяет каждому инженеру иметь «свой собственный бэкенд» прямо внутри браузера.
Более того, современный подход Backend for Frontend (BFF) отлично сочетается с мокированием. Поскольку UI часто общается с промежуточным слоем, мокирование этого слоя позволяет полностью протестировать логику отображения, фильтрации и первичной обработки данных, не затрагивая тяжелые корпоративные системы.
Математическая модель надежности тестов
Если рассмотреть надежность теста как вероятность успешного прохождения всех его этапов, то для E2E-теста она выглядит так:
Где: * — вероятность отсутствия багов в UI (то, что мы хотим проверить). * — вероятности доступности сети, бэкенда, базы и внешних сервисов.
Если каждая из систем доступна с вероятностью (что неплохо), то итоговая вероятность того, что тест не упадет по «инфраструктурным» причинам, для цепочки из 5 зависимостей составит: . Это значит, что 5% запусков будут ложноотрицательными. В масштабах 1000 тестов — это 50 упавших тестов каждое утро.
При мокировании формула упрощается:
Поскольку (надежность Playwright) стремится к , надежность вашего теста начинает напрямую зависеть только от качества вашего кода.
Подготовка к работе с Playwright
Для того чтобы эффективно использовать мокирование, необходимо понимать, как устроены HTTP-запросы. В следующих главах мы будем постоянно оперировать такими понятиями как: * Method (Метод): GET, POST, PUT, DELETE, PATCH. * Status Code (Код ответа): 200 (OK), 201 (Created), 400 (Bad Request), 401 (Unauthorized), 403 (Forbidden), 404 (Not Found), 500 (Internal Server Error). * Headers (Заголовки): Content-Type, Authorization, Cookie. * Body (Тело запроса/ответа): Обычно в формате JSON.
Playwright предоставляет объект route, который является ключом к управлению сетевым трафиком. Освоение этого объекта — это переход от простого «нажимателя кнопок» к инженеру, который полностью контролирует среду выполнения своего приложения.
Использование моков — это не просто технический прием, это смена парадигмы. Мы перестаем воспринимать приложение как «черный ящик», зависящий от воли случая и состояния серверов, и начинаем рассматривать его как предсказуемую систему, где каждый входной сигнал (ответ API) приводит к четко определенному выходному результату (состоянию интерфейса).
Впереди нас ждет глубокое погружение в синтаксис и методы Playwright, которые сделают ваши тесты быстрыми, надежными и по-настоящему профессиональными.