Параллельный запуск тестов Cypress

Тесты – полезная вещь. Но в Cypress они выполняются довольно долго, даже компонентные. Чтобы их ускорить можно использовать многопоточность. В этой статье будем знакомиться с инструментами для параллельного запуска тестов с целью сокращения времени их выполнения.

Содержание

Cypress Cloud

Есть штатное решение для запуска тестов используя несколько процессов. Вам нужно будет зарегистрироваться в сервисе Cypress Cloud и создать там проект. Взять там projectId и recordKey.

Можем сделать это на примере проекта Vue3 Realworld Example App. Пока что будем пробовать делать все локально. Без привязки к какой-либо системе CI-CD.

Панель Cypress Cloud. Список проектов
  1. Клонируем репозиторий
  2. Создаем проект в Cypress Cloud
  3. В файл cypress.config.ts вписываем наш projectId
  4. Устанавливаем зависимости. Для устранения ошибки ERESOLVE unable to resolve dependency tree с eslint должно помочь npm install eslint-plugin-vitest@^0.3.26
  5. Запускаем сборку командой npm run build (которая выполняет vite build)
  6. Запускаем сервер командой npm run serve (которая выполняет vite preview --port 4173)
  7. Пробуем открыть http://localhost:4173/
  8. Запустим тесты вручную npx cypress run и смотрим как они выполнились в 1 поток
  9. Теперь запустим тесты используя 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 состоит из следующих вещей:

  1. Сервис director , который использует MongoDB для хранения результатов тестов.
  2. Сервис API (GraphQL-интерфейс к MongoDB), который позволяет выполнять запросы и получать результаты тестов.
  3. Сервис Dashboard — веб-интерфейс для просмотра результатов.
  4. Сервис 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.

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии