Большой E2E-набор - это не сумма отдельных тестов, а система со своей архитектурой. На масштабе в сотни сценариев начинают работать паттерны, которых не видно на десяти тестах: как готовить состояние, как делить объекты, как организовать setup, где проходит граница реального и контролируемого, как не дать тестам мешать друг другу и как сохранять контекст падения. Все они собраны из принципов предыдущих глав в готовые решения.
App Actions - паттерн подготовки состояния через действия, а не клики. Бизнес-действия, нужные лишь чтобы привести систему в нужное состояние, - создать пользователя, наполнить корзину, оформить заказ - выполняют через API, а не прокликивают в UI. Через интерфейс проходит только то, что сам тест и проверяет. Сценарии становятся быстрыми и устойчивыми: setup не ломается от правки вёрстки, потому что вёрстку не трогает.
Component Objects развивают идею page object на масштаб. Вместо одного всезнающего класса на приложение заводят маленькие предметные объекты: навигация, таблица, модальное окно, checkout - у каждого свой узкий API на языке домена. Тест собирает нужные из них, а меняющаяся часть интерфейса затрагивает лишь один соответствующий объект, а не весь набор. Композиция маленьких объектов масштабируется там, где God Page Object рушится.
Project Dependencies делают setup наблюдаемым. Вместо невидимого global-хука, который что-то готовит до тестов и молчит при сбое, setup оформляют отдельным проектом с зависимостью - как авторизацию из главы про storageState. Такой setup виден в отчёте, пишет собственный trace, падает явно и диагностируемо. Разница принципиальна: невидимый хук при поломке роняет всё без объяснения, наблюдаемый setup показывает, что именно не собралось.
Полезно один раз свести ключевые паттерны большого suite в одну карту, чтобы опираться на неё при проектировании набора. Ниже - шесть паттернов и то, какую задачу каждый решает. К этой карте возвращаются, когда набор перерастает десяток тестов и разрозненные приёмы пора превратить в осознанную архитектуру, а не в стихийно сложившуюся кучу helper'ов.
| Паттерн | Что решает |
|---|---|
| App Actions | Setup через API, UI - только проверяемый путь |
| Component Objects | Маленькие предметные API вместо God Page Object |
|---|
| Project Dependencies | Наблюдаемый setup с trace вместо невидимого хука |
|---|
| Contract Boundary | Своё реально, опасная third-party - sandbox |
|---|
| Worker Namespace | Префикс данных и аккаунтов на worker - без пересечений |
|---|
| Failure Attachments | Доменный контекст и request id при падении |
|---|
Три оставшихся паттерна закрывают границы, изоляцию и диагностику. Contract Boundary фиксирует, что своя система в тестах настоящая, а опасная third-party заменена управляемым sandbox, - это дисциплина из главы про сеть, поднятая до принципа архитектуры. Worker Namespace даёт каждому worker'у собственный префикс данных, аккаунтов и tenant'ов, чтобы параллельные тесты физически не пересекались. Оба превращают ранее описанные приёмы в системное правило набора.
Failure Attachments решают проблему разбора падений на масштабе. Automatic fixture при падении сама прикладывает к результату теста доменный контекст: состояние сущностей, логи, идентификатор запроса. Тогда красный тест несёт не только trace, но и бизнес-контекст - под каким пользователем, с каким заказом, с каким request id он упал. Это превращает разбор из раскопок в чтение приложенного контекста, что на сотнях тестов экономит часы.
Главный антипаттерн этого уровня - универсальный helper. Функция вроде clickAndWait(selector, timeout) выглядит удобной, но скрывает намерение и размазывает причины нестабильности: по вызову не видно, что за действие и чего оно ждёт, а фиксированный timeout возвращает флак из главы про ожидания. Такие "универсальные" обёртки маскируют смысл под общей формой. Используйте предметные действия и web-first ожидания - паттерны выше именно про это.