Перейти к основному содержимому

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

Введение

Testplane запускает тесты параллельно, используя несколько рабочих процессов (воркеров), которые работают одновременно. По умолчанию тесты распределяются между воркерами и выполняются параллельно. Каждый воркер работает с отдельным экземпляром браузера.

Модель параллелизма

Testplane использует двухуровневую модель параллелизма:

Testplane Master Process

├── Worker 1
│ ├── Browser Session A → test-1.js
│ └── Browser Session B → test-2.js

├── Worker 2
│ ├── Browser Session C → test-3.js
│ └── Browser Session D → test-4.js

└── Worker N
└── ...

Мастер-процесс управляет очередью тестов и распределяет их по воркерам. Каждый воркер — это отдельный Node.js-процесс, который может держать одну или несколько браузерных сессий и последовательно выполнять в них тесты.

Тесты внутри одного describe-блока по умолчанию выполняются последовательно — в том порядке, в котором они объявлены. Параллелизм достигается за счет одновременного выполнения тестов из разных файлов и разных браузеров в разных воркерах.

Ключевые параметры

Поведение параллельного запуска контролируется тремя ключевыми настройками в testplane.config.ts.

Рабочие процессы

Параметр workers определяет максимальное количество параллельных процессов, которые Testplane запустит одновременно. Каждый воркер обрабатывает один тест за раз, а после завершения теста переходит к следующему из очереди.

// .testplane.config.ts
module.exports = {
workers: 4, // количество параллельных воркеров
};

Ограничение количества рабочих процессов

Чтобы ограничить количество воркеров, воспользуйтесь командной строкой.

npx testplane --workers 4

Или укажите нужное значение в файле testplane.config.ts

// .testplane.config.ts
module.exports = {
workers: 4, // количество параллельных процессов
// ...
};

Testplane также поддерживает параметр testsPerWorker — максимальное количество тестов, которое один воркер выполнит перед перезапуском.

// .testplane.config.ts
module.exports = {
workers: 4,
testsPerWorker: 50, // воркер перезапустится после 50 тестов
};

Лимит сессий на браузер

Параметр sessionsPerBrowser отвечает за максимальное число одновременно открытых браузерных сессий для одного браузера.

export default {
sessionsPerBrowser: 5, // по умолчанию: 1
browsers: {
chrome: {
sessionsPerBrowser: 10, // переопределение на уровне браузера
desiredCapabilities: {
browserName: "chrome",
},
},
firefox: {
sessionsPerBrowser: 3,
desiredCapabilities: {
browserName: "firefox",
},
},
},
};

Важные моменты:

  • лимит применяется к каждому браузеру независимо;
  • суммарное число активных сессий может превышать значение workers;
  • воркер может управлять несколькими сессиями последовательно, но одновременно — только одной.

Лимит тестов за сессию

Параметр testsPerSession отвечает за максимальное число тестов, которые выполнятся в одной браузерной сессии до ее пересоздания.

export default {
testsPerSession: 20, // по умолчанию: Infinity
browsers: {
chrome: {
testsPerSession: 50,
},
},
};

Варианты использования:

  • 1 — каждый тест в новой сессии (максимальная изоляция, медленнее);
  • Infinity — все тесты в одной сессии (быстро, но есть риск утечек состояния);
  • 20–50 — баланс скорости и изоляции (рекомендуется для большинства проектов).

Отключение параллелизма

Чтобы запустить все тесты последовательно, ограничьте количество воркеров до одного через командную строку.

npx testplane --workers 1

Или напрямую в файле testplane.config.ts.

// .testplane.conf.js
module.exports = {
workers: 1,
};

Рекомендуемые настройки и их расчет

Базовая формула

Отправной точкой для расчета является количество ядер CPU и доступная память на машине, где запускаются браузеры (Selenium Grid, Selenoid, или локальная машина).

sessionsPerBrowser = количество доступных слотов на grid / количество браузеров
workers = sessionsPerBrowser × количество браузеров
testsPerSession = 20–40 (для ускорения) или 1 (для максимальной изоляции)

Пример расчета для CI

Допустим, ваш Selenoid-сервер выдерживает 20 одновременных браузеров, и вы тестируете в 2 браузерах (chrome, firefox).

export default {
workers: 20,

browsers: {
chrome: {
sessionsPerBrowser: 10, // 20 слотов / 2 браузера
testsPerSession: 20, // переиспользуем сессию для 20 тестов
},
firefox: {
sessionsPerBrowser: 10,
testsPerSession: 20,
},
},
};

Пример расчета для локального запуска

На локальной машине ресурсы ограничены. Рекомендуется:

export default {
workers: 4, // ~количество ядер CPU / 2

browsers: {
chrome: {
sessionsPerBrowser: 4,
testsPerSession: 5,
},
},
};

Рекомендации по testsPerSession

СценарийРекомендуемое значение
Тесты полностью изолированы, нет глобального состояния20–50
Тесты частично изолированы (авторизация через beforeEach)10–20
Тесты меняют глобальное состояние браузера1
Отладка нестабильных тестов1
Максимальное ускорение на CI40–100

Шардирование

При наличии тысяч тестов время одного запуска может быть неприемлемо большим даже при максимальном параллелизме. В таких случаях используют шардирование — разбивку всего набора тестов на несколько независимых частей (чанков), которые запускаются параллельно на разных машинах или в разных CI-джобах.

Плагин testplane-chunks

Для шардирования в Testplane используется официальный плагин @testplane/chunks.

Установка и подключение

Чтобы установить плагин @testplane/chunks, выполните команду.

npm install -D @testplane/chunks

И укажите параметры в файле testplane.config.ts.

// testplane.config.ts
export default {
plugins: {
"@testplane/chunks": {
enabled: true,
},
},
// остальные настройки...
};

Как работает шардирование

Плагин делит список всех тестов на равные части по количеству тестов. Каждый запуск получает свой номер чанка и выполняет только свою часть тестов.

Все тесты (1000 штук)

├── Чанк 1/4: тесты 1–250 → CI Job 1
├── Чанк 2/4: тесты 251–500 → CI Job 2
├── Чанк 3/4: тесты 501–750 → CI Job 3
└── Чанк 4/4: тесты 751–1000 → CI Job 4

Все 4 джобы выполняются параллельно, что теоретически сокращает общее время в 4 раза.

Запуск с указанием чанка

Номер чанка и общее количество чанков передаются через переменные окружения или CLI-параметры:

# Запустить первый чанк из четырех
npx testplane --chunks 4 --chunk 1

# Запустить второй чанк из четырех
npx testplane --chunks 4 --chunk 2

Или через переменные окружения:

TESTPLANE_CHUNKS=4 TESTPLANE_CHUNK=1 npx testplane

Пример конфигурации GitHub Actions

# .github/workflows/tests.yml
jobs:
test:
strategy:
matrix:
chunk: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v3
- run: npm ci
- run: npx testplane --chunks 4 --chunk ${{ matrix.chunk }}

Как рассчитать оптимальное количество чанков

Количество чанков = ceil(Общее время запуска / Целевое время запуска)

Пример:

2000 тестов выполняются за 60 минут на одной машине
Цель: уложиться в 10 минут
Необходимо: ceil(60 / 10) = 6 чанков

При этом убедитесь, что в каждом чанке достаточно тестов для эффективной загрузки воркеров:

Тестов в одном чанке = Общее число тестов / Количество чанков
= 2000 / 6 ≈ 333 теста на чанк

333 теста на чанк при sessionsPerBrowser: 10 и testsPerSession: 20 — разумное соотношение.

Сводная таблица настроек

НастройкаУровеньЗа что отвечаетВлияет на
workersГлобальныйКоличество параллельных Node.js-процессовCPU, память на машине с тестами
sessionsPerBrowserБраузерКоличество одновременных браузерных сессийНагрузку на grid, скорость прохождения
testsPerSessionБраузерСколько тестов выполнить в одной сессии до ее пересозданияСкорость (меньше накладных расходов) vs изоляция
chunks (плагин)CI-уровеньРазбивка всего набора на независимые частиГоризонтальное масштабирование на несколько машин