Параллельность в E2E - это не только про скорость, но и про честность. Когда тесты идут по одному, скрытые зависимости между ними незаметны: общий пользователь, общий заказ, общий счётчик спокойно переживают последовательный прогон. Стоит запустить те же тесты одновременно - и эти зависимости всплывают падениями. Поэтому параллельность работает как детектор: она не создаёт проблемы с общим состоянием, а обнажает те, что уже были.
У Playwright два разных механизма масштабирования. Workers - это независимые процессы на одной машине: флаг --workers=4 гоняет четыре теста одновременно, каждый в своём процессе с изолированным состоянием. Shards делят весь набор между разными машинами CI: --shard=1/3 запускает первую треть тестов, и три параллельные CI-job'ы вместе проходят весь набор втрое быстрее. Первое масштабирует внутри машины, второе - между машинами.
Оба механизма опираются на fullyParallel и требуют дисциплины данных. Чтобы четыре worker'а или три шарда не мешали друг другу, данные должны иметь namespace - каждый тест работает со своими сущностями, помеченными его идентификатором. Именно та уникальность из главы про данные - email с workerIndex, отдельные аккаунты - делает параллельность безопасной. Без неё параллельный прогон превращается в гонку за общие записи.
Полезно один раз собрать команды масштабирования вместе, чтобы различать их назначение. Ниже - локальный прогон в четыре worker'а и разбиение набора на три шарда для CI. К этой карте возвращаются, настраивая производительность прогона: workers увеличивают загрузку одной машины, sharding раскладывает набор по нескольким, и выбирают их под то, чем вы располагаете - мощной машиной или несколькими раннерами.
Условия безопасной параллельности выходят за пределы данных. Аккаунты не должны конфликтовать - иначе два теста, вошедшие под одним пользователем и меняющие его, столкнутся. Внешняя среда должна выдерживать нагрузку - тестовая база, API, сторонние sandbox получают в разы больше запросов одновременно. Если хоть одно из этих условий не выполнено, параллельность не ускорит набор, а сделает его нестабильным и начнёт ронять на ресурсных лимитах.
Ключевой принцип - масштабировать после измерения, а не по интуиции. Кажется, что больше worker'ов всегда быстрее, но это неверно за пределами ресурсов среды. Если четыре worker'а уже упирают тестовую базу в потолок соединений, восемь не ускорят прогон, а замедлят его и добавят флака на таймаутах и блокировках. Оптимум - там, где параллелизм и ёмкость среды сбалансированы, и находят его замером, а не удвоением наугад.
Измеряют конкретные величины, а не общее ощущение. Длительность прогона при разном числе worker'ов, загрузку CPU, размер пула соединений к базе, лимиты частоты у внешних сервисов. Эти цифры показывают узкое место: если при добавлении worker'ов время перестаёт падать, дело не в параллелизме, а в ёмкости базы или внешней среды - наращивать дальше бессмысленно.
Типичные провалы параллельности предсказуемы. Общие изменяемые данные и аккаунты, всплывающие падениями ровно при параллельном прогоне, - тесты зелёные по одному и красные вместе. Наращивание worker'ов без измерения, упирающее тестовую базу и добавляющее флак вместо скорости. И игнорирование лимитов внешней среды под параллельной нагрузкой. Давайте тестам namespace-данные, разводите аккаунты и масштабируйте по замеру, а не по вере в "чем больше, тем быстрее".
# Локально: четыре независимых процесса на одной машине
npx playwright test --workers=4
# CI: разбить набор на три шарда по разным машинам
npx playwright test --shard=1/3
npx playwright test --shard=2/3
npx playwright test --shard=3/3