Тесты – полезная вещь. Но в Cypress они выполняются довольно долго, даже компонентные. Чтобы их ускорить можно использовать многопоточность. В этой статье будем знакомиться с инструментами для параллельного запуска тестов с целью сокращения времени их выполнения.
Содержание
Cypress Cloud
Есть штатное решение для запуска тестов используя несколько процессов. Вам нужно будет зарегистрироваться в сервисе Cypress Cloud и создать там проект. Взять там projectId
и recordKey
.
Можем сделать это на примере проекта Vue3 Realworld Example App. Пока что будем пробовать делать все локально. Без привязки к какой-либо системе CI-CD.
- Клонируем репозиторий
- Создаем проект в
Cypress Cloud
- В файл
cypress.config.ts
вписываем нашprojectId
- Устанавливаем зависимости. Для устранения ошибки
ERESOLVE unable to resolve dependency tree
сeslint
должно помочьnpm install eslint-plugin-vitest@^0.3.26
- Запускаем сборку командой
npm run build
(которая выполняетvite build
) - Запускаем сервер командой
npm run serve
(которая выполняетvite preview --port 4173
) - Пробуем открыть
http://localhost:4173/
- Запустим тесты вручную
npx cypress run
и смотрим как они выполнились в 1 поток - Теперь запустим тесты используя
recordKey
из проектаCypress Cloud
.
npx cypress run --record --key dd9afb0c-f594-4d3a-8401-a8b28569b94c --parallel --ci-build-id build-01
В последнем шаге, если открыть следом несколько консолей и запустить эту же команду, то каждый процесс возьмет себе часть тестов и будет выполнять свою порцию. Таким образом тесты будут выполняться параллельно.
Здесь важно, чтобы в каждом параллельном запуске значение --ci-build-id
было одним и тем же. Это идентификатор, который будет одинаковым у всех потоков. Если дождаться пока все процессы закончатся и запустить команду снова, то она не выполнит ни одного теста. Для этой сборки все тесты уже будут помечены как запущенные. Поэтому новому процессу просто нечего будет брать в работу. Чтобы тесты запустились снова нужно поменять значение для --ci-build-id
и тогда можно снова запускать несколько потоков.
Sorry Cypress
Этот проект предлагает замену Cypress Cloud (для распараллеливания запуска тестов и хранения результатов), которую можно напустить на своем севере (self hosted).
Есть различные варианты запуска
- basic director – базовый вариант запуска. Хранит результаты тестов в памяти.
- dashboard – хранит результаты в БД и имеет веб-панель управления.
Вариант в basic director
Параметры --key
и projectId
не оказывают никакого эффекта на работу этого способа запуска.
Для запуска нам нужно клонировать репозиторий с проектом и повторить пункты 4 – 7 из предыдущего раздела статьи, где описывался запуск через Cypress Cloud.
Затем запустить докер-контейнер:
docker run -p 1234:1234 agoldis/sorry-cypress-director
Установить cypress-cloud
npm install cypress-cloud cypress
Создать файл currents.config.js
export default {
projectId: "yyy", // Произвольное значение projectId
recordKey: "xxx", // Произвольное значение
cloudServiceUrl: "http://localhost:1234", // Адрес с портом, на которых доступен процесс из docker
};
Добавить cypress-cloud/plugin
в cypress.config.{js|ts|mjs}config.ts
:
import { defineConfig } from 'cypress'
import { cloudPlugin } from 'cypress-cloud/plugin'
export default defineConfig({
e2e: {
specPattern: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
baseUrl: 'http://localhost:4173',
defaultCommandTimeout: 8000,
setupNodeEvents(on, config) {
return cloudPlugin(on, config);
},
},
})
После этого в нескольких терминалах нам нужно запустить команду типа
npx cypress-cloud run --parallel --record --key somekey --ci-build-id hello-sorry-cypress
И снова в каждом из терминалов запустится свой набор тестов, как это было с Cypress Cloud.
Вариант с dashboard
Для этого варианта вам понадобится совокупность docker-контейнеров (sorry-cypress kit), для согласованного запуска которых нужно использовать docker-compose.yml
из документации Sorry Cypress.
Набор sorry-cypress kit состоит из следующих вещей:
- Сервис
director
, который использует MongoDB для хранения результатов тестов. - Сервис
API
(GraphQL-интерфейс к MongoDB), который позволяет выполнять запросы и получать результаты тестов. - Сервис
Dashboard
— веб-интерфейс для просмотра результатов. - Сервис
minio
, который позволяет хранить файлы — видео и скриншоты, создаваемые агентом cypress.
Инструкция по запуску из документации выглядит так:
# get docker-compose file
curl --output docker-compose.minio.yml https://raw.githubusercontent.com/sorry-cypress/sorry-cypress/master/docker-compose.minio.yml
# start the services
docker-compose -f ./docker-compose.minio.yml up
Однако, если сделать в точности так, то запуска не произойдет из-за ряда ошибок. Причем затем нужно будет удалять оставшиеся после запуска данные из папки с docker-compose.yml
.
Об этом в документации (на момент написания статьи) не было сказано, но чтобы запустить сервисы корректно, нужно заменить все плейсхолдеры в файле (выделенные знаками “больше” и “меньше”) на верные значения.
У меня получился следующий список замен:
Плейсхолдер | Что поставить |
---|---|
<mongo-user> | например admin |
<mongo-pass> | любой пароль, например admin123 |
<minio-user> | например minioadmin |
<minio-pass> | например minio123 |
<minio-ip-address> | localhost |
<graphql-ip-address> | localhost |
В итоге файл стал выглядеть так:
version: '3.6'
services:
mongo:
image: mongo:4.4
environment:
MONGO_INITDB_ROOT_USERNAME: 'admin'
MONGO_INITDB_ROOT_PASSWORD: 'admin123'
volumes:
- ./data/data-mongo-cypress:/data/db
ports:
- 27017:27017
director:
image: agoldis/sorry-cypress-director:latest
environment:
DASHBOARD_URL: http://localhost:8080
EXECUTION_DRIVER: '../execution/mongo/driver'
MONGODB_URI: 'mongodb://admin:admin123@mongo:27017'
MONGODB_DATABASE: 'sorry-cypress'
SCREENSHOTS_DRIVER: '../screenshots/minio.driver'
GITLAB_JOB_RETRIES: 'false'
MINIO_ACCESS_KEY: 'minioadmin'
MINIO_SECRET_KEY: 'minio123'
MINIO_ENDPOINT: 'localhost'
MINIO_URL: 'http://localhost'
MINIO_PORT: '9000'
MINIO_USESSL: 'false'
MINIO_BUCKET: sorry-cypress
PROBE_LOGGER: "false"
ports:
- 1234:1234
- 9000:9000
- 9090:9090
depends_on:
- mongo
api:
image: agoldis/sorry-cypress-api:latest
environment:
MONGODB_URI: 'mongodb://admin:admin123@mongo:27017'
MONGODB_DATABASE: 'sorry-cypress'
APOLLO_PLAYGROUND: 'false'
ports:
- 4000:4000
depends_on:
- mongo
dashboard:
image: agoldis/sorry-cypress-dashboard:latest
environment:
GRAPHQL_SCHEMA_URL: http://localhost:4000
GRAPHQL_CLIENT_CREDENTIALS: ''
PORT: 8080
CI_URL: ''
ports:
- 8080:8080
depends_on:
- mongo
- api
storage:
image: minio/minio
network_mode: service:director
environment:
MINIO_ROOT_USER: 'minioadmin'
MINIO_ROOT_PASSWORD: 'minio123'
volumes:
- ./data/data-minio-cypress:/data
command: minio server --console-address ":9090" /data
createbuckets:
image: minio/mc
network_mode: service:director
depends_on:
- storage
entrypoint: >
/bin/sh -c "
sleep 3;
/usr/bin/mc config host add myminio http://localhost:9000 minioadmin minio123;
/usr/bin/mc rm -r --dangerous --force myminio/sorry-cypress;
/usr/bin/mc mb myminio/sorry-cypress;
/usr/bin/mc anonymous set download myminio/sorry-cypress;
/usr/bin/mc anonymous set public myminio/sorry-cypress;
exit 0;
"
Затем запускаем через команду
docker compose -f ./docker-compose.minio.yml up
После запуска сможет открыть панель (dashboard) по адресу http://localhost:8080
В панели нужно создать проект с projectId, который указан в вашем currents.config.js
.
Для сохранения снимков экрана нужно в /etc/hosts
добавить
127.0.0.1 storage
Теперь можем в нескольких консолях запустить
npx cypress-cloud run --parallel --record --key somekey --ci-build-id sorry-cypress-dashboard-01
Результаты будут отображаться теперь в панели.
Есть проблема. При запуске тестов возникли ошибки из-за которых в панели не отображается информация о тестах проекта. Добавлено сообщение об этой проблеме на Github.
Cypress-parallel
Следующее решение для параллельного запуска тестов Cypress менее известно – это npm-пакет cypress-parallel
Установим его как обычную dev-зависимость:
npm i cypress-parallel -D
Добавим в секцию scripts в package.json
следующее:
"scripts": {
...
"cy:run": "cypress run",
"cy:parallel" : "cypress-parallel -s cy:run -t 3 -d cypress/e2e"
}
После того как мы запустим наш тестовый проект через npm run serve
и он станет доступен тут http://localhost:4173
можно запустить npm run cy:parallel
. На этот раз нам не нужно открывать несколько окон терминала. Код пакета сам создает указанное число параллельных процессов.
Это решение наиболее легко установить и начать использовать. Вопрос только в том на сколько хорошо поддерживается пакет. На момент написания статьи последние изменения были 18 марта 2025 (4 месяца назад).
Итоги
И так у нас кроме штатного способа запуска тестов Cypress параллельно есть, как минимум еще 2 бесплатных варианта.
В статье описывался только запуск тестов на своей локальной машине. Но предстоит еще выяснить как настроить это для запуска в CI-CD (например, в Gitlab). Для Sorry Cypress нужно также где-то запустить все сервисы ( в том числе веб-панель) и ограничить к ним доступ.
Еще одной проблемой Sorry Cypress является ошибка Error: Cannot return null for non-nullable field InstanceStats.wallClockDuration.
Таким образом самым простым и дешевым, наверное, является вариант с Cypress-parallel.