From 578c847d9e6e5a0dbb2b96a21f7e6517e36d5ec5 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Fri, 20 Mar 2026 14:39:52 +0300 Subject: [PATCH 01/19] docs: parallelism-add --- docs/basic-guides/parallelism.mdx | 1 + .../current/basic-guides/parallelism.mdx | 309 ++++++++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 docs/basic-guides/parallelism.mdx create mode 100644 i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx diff --git a/docs/basic-guides/parallelism.mdx b/docs/basic-guides/parallelism.mdx new file mode 100644 index 0000000..5c3fb84 --- /dev/null +++ b/docs/basic-guides/parallelism.mdx @@ -0,0 +1 @@ +# Parallelism diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx new file mode 100644 index 0000000..2eabc78 --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -0,0 +1,309 @@ +# Параллельный запуск тестов + +## Введение + +Testplane запускает тесты параллельно, используя несколько рабочих процессов (воркеров), которые работают одновременно. По умолчанию тесты распределяются между воркерами и выполняются параллельно. Каждый воркер работает с отдельным экземпляром браузера. + +## Модель параллелизма + +Testplane использует двухуровневую модель параллелизма: + +```css +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 запустит одновременно. Каждый воркер обрабатывает один тест за раз, а после завершения теста переходит к следующему из очереди. + +```typescript +// .testplane.config.ts +module.exports = { + workers: 4, // количество параллельных воркеров +}; +``` + +#### Ограничение количества рабочих процессов + +Чтобы ограничить количество воркеров, воспользуйтесь командной строкой. + +```bash +npx testplane --workers 4 +``` + +Или укажите нужное значение в файле `testplane.config.ts` + +```typescript +// .testplane.config.ts +module.exports = { + workers: 4, // количество параллельных процессов + // ... +}; +``` + +Testplane также поддерживает параметр `testsPerWorker` — максимальное количество тестов, которое один воркер выполнит перед перезапуском. + +```typescript +// .testplane.config.ts +module.exports = { + workers: 4, + testsPerWorker: 50, // воркер перезапустится после 50 тестов +}; +``` + +#### Лимит сессий на браузер + +Параметр `sessionsPerBrowser` отвечает за максимальное число одновременно открытых браузерных сессий для одного браузера. + +```typescript +export default { + sessionsPerBrowser: 5, // по умолчанию: 1 + browsers: { + chrome: { + sessionsPerBrowser: 10, // переопределение на уровне браузера + desiredCapabilities: { + browserName: "chrome", + }, + }, + firefox: { + sessionsPerBrowser: 3, + desiredCapabilities: { + browserName: "firefox", + }, + }, + }, +}; +``` + +Важные моменты: + +- лимит применяется к каждому браузеру независимо; +- суммарное число активных сессий может превышать значение workers; +- воркер может управлять несколькими сессиями последовательно, но одновременно — только одной. + +#### Лимит тестов за сессию + +Параметр `testsPerSession` отвечает за максимальное число тестов, которые выполнятся в одной браузерной сессии до ее пересоздания. + +```typescript +export default { + testsPerSession: 20, // по умолчанию: Infinity + browsers: { + chrome: { + testsPerSession: 50, + }, + }, +}; +``` + +Варианты использования: + +- 1 — каждый тест в новой сессии (максимальная изоляция, медленнее); +- `Infinity` — все тесты в одной сессии (быстро, но есть риск утечек состояния); +- 20–50 — баланс скорости и изоляции (рекомендуется для большинства проектов). + +## Отключение параллелизма + +Чтобы запустить все тесты последовательно, ограничьте количество воркеров до одного через командную строку. + +```bash +npx testplane --workers 1 +``` + +Или напрямую в файле `testplane.config.ts`. + +```typescript +// .testplane.conf.js +module.exports = { + workers: 1, +}; +``` + +## Рекомендуемые настройки и их расчет + +#### Базовая формула + +Отправной точкой для расчета является количество ядер CPU и доступная память на машине, где запускаются браузеры (Selenium Grid, Selenoid, или локальная машина). + +```text +sessionsPerBrowser = количество доступных слотов на grid / количество браузеров +workers = sessionsPerBrowser × количество браузеров +testsPerSession = 20–40 (для ускорения) или 1 (для максимальной изоляции) +``` + +#### Пример расчета для CI + +Допустим, ваш Selenoid-сервер выдерживает 20 одновременных браузеров, и вы тестируете в 2 браузерах (chrome, firefox). + +```typescript +export default { + workers: 20, + + browsers: { + chrome: { + sessionsPerBrowser: 10, // 20 слотов / 2 браузера + testsPerSession: 20, // переиспользуем сессию для 20 тестов + }, + firefox: { + sessionsPerBrowser: 10, + testsPerSession: 20, + }, + }, +}; +``` + +#### Пример расчета для локального запуска + +На локальной машине ресурсы ограничены. Рекомендуется: + +```typescript +export default { + workers: 4, // ~количество ядер CPU / 2 + + browsers: { + chrome: { + sessionsPerBrowser: 4, + testsPerSession: 5, + }, + }, +}; +``` + +#### Рекомендации по testsPerSession + +| Сценарий | Рекомендуемое значение | +| ----------------------------------------------------------- | ---------------------- | +| Тесты полностью изолированы, нет глобального состояния | 20–50 | +| Тесты частично изолированы (авторизация через `beforeEach`) | 10–20 | +| Тесты меняют глобальное состояние браузера | 1 | +| Отладка нестабильных тестов | 1 | +| Максимальное ускорение на `CI` | 40–100 | + +## Шардирование + +При наличии тысяч тестов время одного запуска может быть неприемлемо большим даже при максимальном параллелизме. В таких случаях используют шардирование — разбивку всего набора тестов на несколько независимых частей (чанков), которые запускаются параллельно на разных машинах или в разных `CI`-джобах. + +#### Плагин testplane-chunks + +Для шардирования в Testplane используется официальный плагин `@testplane/chunks`. + +#### Установка и подключение + +Чтобы установить плагин `@testplane/chunks`, выполните команду. + +```bash +npm install -D @testplane/chunks +``` + +И укажите параметры в файле `testplane.config.ts`. + +```typescript +// testplane.config.ts +export default { + plugins: { + "@testplane/chunks": { + enabled: true, + }, + }, + // остальные настройки... +}; +``` + +#### Как работает шардирование + +Плагин делит список всех тестов на равные части по количеству тестов. Каждый запуск получает свой номер чанка и выполняет только свою часть тестов. + +```yaml +Все тесты (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-параметры: + +```bash +# Запустить первый чанк из четырех +npx testplane --chunks 4 --chunk 1 + +# Запустить второй чанк из четырех +npx testplane --chunks 4 --chunk 2 +``` + +Или через переменные окружения: + +```bash +TESTPLANE_CHUNKS=4 TESTPLANE_CHUNK=1 npx testplane +``` + +#### Пример конфигурации GitHub Actions + +```yaml +# .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 }} +``` + +#### Как рассчитать оптимальное количество чанков + +```scss +Количество чанков = ceil(Общее время запуска / Целевое время запуска) +``` + +Пример: + +```text +2000 тестов выполняются за 60 минут на одной машине +Цель: уложиться в 10 минут +Необходимо: ceil(60 / 10) = 6 чанков +``` + +При этом убедитесь, что в каждом чанке достаточно тестов для эффективной загрузки воркеров: + +```text +Тестов в одном чанке = Общее число тестов / Количество чанков + = 2000 / 6 ≈ 333 теста на чанк +``` + +333 теста на чанк при `sessionsPerBrowser`: 10 и `testsPerSession`: 20 — разумное соотношение. + +## Сводная таблица настроек + +| Настройка | Уровень | За что отвечает | Влияет на | +| -------------------- | ------------ | ---------------------------------------------------------- | ------------------------------------------------- | +| `workers` | Глобальный | Количество параллельных `Node.js`-процессов | CPU, память на машине с тестами | +| `sessionsPerBrowser` | Браузер | Количество одновременных браузерных сессий | Нагрузку на `grid`, скорость прохождения | +| `testsPerSession` | Браузер | Сколько тестов выполнить в одной сессии до ее пересоздания | Скорость (меньше накладных расходов) vs изоляция | +| `chunks` (плагин) | `CI`-уровень | Разбивка всего набора на независимые части | Горизонтальное масштабирование на несколько машин | From fa7c1be60aeeb3fc407836ec469b325be30a2f41 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Mon, 6 Apr 2026 12:14:35 +0300 Subject: [PATCH 02/19] docs: perallelism-fix --- .../current/basic-guides/parallelism.mdx | 502 ++++++++++-------- 1 file changed, 294 insertions(+), 208 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index 2eabc78..cec6b06 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -1,202 +1,171 @@ # Параллельный запуск тестов -## Введение +## Параллельность в Testplane -Testplane запускает тесты параллельно, используя несколько рабочих процессов (воркеров), которые работают одновременно. По умолчанию тесты распределяются между воркерами и выполняются параллельно. Каждый воркер работает с отдельным экземпляром браузера. +Параллельность в Testplane — это возможность одновременно выполнять несколько тестовых сценариев в разных браузерных сессиях, чтобы сократить общее время прогона тестов. -## Модель параллелизма +#### sessionsPerBrowser -Testplane использует двухуровневую модель параллелизма: +В конфигурационном файле объявляются типы браузеров в поле `browsers`. Для каждого типа браузера независимо настраивается, сколько экземпляров может работать одновременно: -```css -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 - └── ... +```typescript +// .testplane.config.ts +export default { + browsers: { + chrome: { + sessionsPerBrowser: 5, // до 5 параллельных сессий Chrome + }, + firefox: { + sessionsPerBrowser: 2, // до 2 параллельных сессий Firefox + }, + }, +}; ``` -Мастер-процесс управляет очередью тестов и распределяет их по воркерам. Каждый воркер — это отдельный `Node.js`-процесс, который может держать одну или несколько браузерных сессий и последовательно выполнять в них тесты. +Параметр `sessionsPerBrowser` является ключевым в рамках управления параллельностью. Он определяет, сколько браузеров одного типа Testplane запустит одновременно. По умолчанию значение: `1`. -Тесты внутри одного `describe`-блока по умолчанию выполняются последовательно — в том порядке, в котором они объявлены. Параллелизм достигается за счет одновременного выполнения тестов из разных файлов и разных браузеров в разных воркерах. +#### Воркеры -## Ключевые параметры +Параметр `workers` определяет, сколько дочерних процессов-воркеров будет запущено. Архитектурно это выглядит так: -Поведение параллельного запуска контролируется тремя ключевыми настройками в `testplane.config.ts`. +* `Master`-процесс — координирует запуск, формирует очереди тестов и раздает задания воркерам +* `Worker`-процессы — непосредственно исполняют тесты -#### Рабочие процессы +Каждый воркер — это отдельный поток, но внутри одного воркера тесты выполняются конкурентно: когда тест ждет ответа от браузера (`await`), воркер не простаивает, а переключается на следующий тест. Поэтому даже один воркер способен обслуживать множество параллельных браузерных сессий. -Параметр `workers` определяет максимальное количество параллельных процессов, которые Testplane запустит одновременно. Каждый воркер обрабатывает один тест за раз, а после завершения теста переходит к следующему из очереди. +:::warning Важно +`workers` и `sessionsPerBrowser` — независимые ограничения. Увеличение числа воркеров не увеличивает реальную параллельность, если `sessionsPerBrowser` остается прежним. +::: -```typescript -// .testplane.config.ts -module.exports = { - workers: 4, // количество параллельных воркеров -}; -``` - -#### Ограничение количества рабочих процессов +#### testsPerSession -Чтобы ограничить количество воркеров, воспользуйтесь командной строкой. +Параметр `testsPerSession` отвечает за то, сколько тестов можно запускать последовательно в одной сессии браузера. Параметр ограничивает переиспользование сессии, чтобы не допустить падения тестов из-за деградации браузера, и не имеет отношения к параллельному запуску тестов. -```bash -npx testplane --workers 4 -``` +#### Пример -Или укажите нужное значение в файле `testplane.config.ts` +В рамках примера исполнять тесты будет один воркер: ```typescript -// .testplane.config.ts -module.exports = { - workers: 4, // количество параллельных процессов - // ... -}; +system: { + workers: 1, + }, ``` - -Testplane также поддерживает параметр `testsPerWorker` — максимальное количество тестов, которое один воркер выполнит перед перезапуском. +Параметру sessionsPerBrowser присвоены значения `5`: ```typescript -// .testplane.config.ts -module.exports = { - workers: 4, - testsPerWorker: 50, // воркер перезапустится после 50 тестов -}; +chrome: { + headless: true, + desiredCapabilities: { + browserName: "chrome" + }, + sessionsPerBrowser: 5, // 5 параллельных сессий Chrome + testsPerSession: 3, + waitTimeout: 10000, + } ``` - -#### Лимит сессий на браузер - -Параметр `sessionsPerBrowser` отвечает за максимальное число одновременно открытых браузерных сессий для одного браузера. +и `2`: ```typescript -export default { - sessionsPerBrowser: 5, // по умолчанию: 1 - browsers: { - chrome: { - sessionsPerBrowser: 10, // переопределение на уровне браузера +firefox: { + headless: true, desiredCapabilities: { - browserName: "chrome", + browserName: "firefox" }, - }, - firefox: { - sessionsPerBrowser: 3, - desiredCapabilities: { - browserName: "firefox", - }, - }, - }, -}; + sessionsPerBrowser: 2, // 2 параллельные сессии Firefox + testsPerSession: 3, + waitTimeout: 10000, + } ``` -Важные моменты: - -- лимит применяется к каждому браузеру независимо; -- суммарное число активных сессий может превышать значение workers; -- воркер может управлять несколькими сессиями последовательно, но одновременно — только одной. - -#### Лимит тестов за сессию - -Параметр `testsPerSession` отвечает за максимальное число тестов, которые выполнятся в одной браузерной сессии до ее пересоздания. +Далее тесты: ```typescript -export default { - testsPerSession: 20, // по умолчанию: Infinity - browsers: { - chrome: { - testsPerSession: 50, - }, - }, -}; -``` +describe("test examples", () => { + it("Поиск элемента по data-testid", async ({ browser }) => { + // Открываем страницу и ждем ее загрузки + await browser.openAndWait("https://testplane.io/"); -Варианты использования: + // Ищем элемент по атрибуту data-testid + const element = await browser.$('[data-testid="main-content"]'); -- 1 — каждый тест в новой сессии (максимальная изоляция, медленнее); -- `Infinity` — все тесты в одной сессии (быстро, но есть риск утечек состояния); -- 20–50 — баланс скорости и изоляции (рекомендуется для большинства проектов). + // Проверяем существование элемента в DOM + const isExisting = await element.isExisting(); + console.log("Элемент с data-testid существует:", isExisting); + }); -## Отключение параллелизма + it("Поиск элемента на главной странице", async ({ browser }) => { + await browser.openAndWait("https://testplane.io/"); -Чтобы запустить все тесты последовательно, ограничьте количество воркеров до одного через командную строку. + // Ищем элемент по классу "navbar" + const navbar = await browser.$(".navbar"); -```bash -npx testplane --workers 1 -``` + // Проверяем, отображается ли элемент на странице + const isDisplayed = await navbar.isDisplayed(); + console.log("Навбар отображается:", isDisplayed); + }); -Или напрямую в файле `testplane.config.ts`. + it("Поиск элемента по id на главной странице", async ({ browser }) => { + await browser.openAndWait("https://testplane.io/"); -```typescript -// .testplane.conf.js -module.exports = { - workers: 1, -}; -``` + // Ищем элемент по id "__docusaurus" + const main = await browser.$("#__docusaurus"); -## Рекомендуемые настройки и их расчет + // Проверяем, отображается ли элемент на странице + const isDisplayed = await main.isDisplayed(); + console.log("Элемент отображается:", isDisplayed); + }); -#### Базовая формула + it("Поиск элемента по типу атрибута", async ({ browser }) => { + await browser.openAndWait("https://testplane.io/"); -Отправной точкой для расчета является количество ядер CPU и доступная память на машине, где запускаются браузеры (Selenium Grid, Selenoid, или локальная машина). + // Ищем кнопку по атрибуту type="button" + // Формат селектора: element[type="value"] + const button = await browser.$('button[type="button"]'); -```text -sessionsPerBrowser = количество доступных слотов на grid / количество браузеров -workers = sessionsPerBrowser × количество браузеров -testsPerSession = 20–40 (для ускорения) или 1 (для максимальной изоляции) -``` + // Проверяем существование элемента в DOM + const isExisting = await button.isExisting(); + console.log("Кнопка существует:", isExisting); + }); -#### Пример расчета для CI + it("Поиск элемента по тексту", async ({ browser }) => { + await browser.openAndWait("https://testplane.io/"); -Допустим, ваш Selenoid-сервер выдерживает 20 одновременных браузеров, и вы тестируете в 2 браузерах (chrome, firefox). + // Ищем элемент по тексту внутри него + const link = await browser.$('//a[text()="Docs"]'); -```typescript -export default { - workers: 20, + // Проверяем существование элемента в DOM + const isExisting = await link.isExisting(); + console.log("Элемент с текстом существует:", isExisting); + }); - browsers: { - chrome: { - sessionsPerBrowser: 10, // 20 слотов / 2 браузера - testsPerSession: 20, // переиспользуем сессию для 20 тестов - }, - firefox: { - sessionsPerBrowser: 10, - testsPerSession: 20, - }, - }, -}; -``` + it("Поиск элемента по атрибуту", async ({ browser }) => { + await browser.openAndWait("https://testplane.io/"); -#### Пример расчета для локального запуска + // Ищем элемент по атрибуту type + const button = await browser.$('//button[@type="button"]'); -На локальной машине ресурсы ограничены. Рекомендуется: + // Проверяем существование элемента в DOM + const isExisting = await button.isExisting(); + console.log("Элемент с атрибутом существует:", isExisting); + }); -```typescript -export default { - workers: 4, // ~количество ядер CPU / 2 + it("Поиск кнопки с помощью метода getByRole", async ({ browser }) => { + await browser.url("https://testplane.io/"); - browsers: { - chrome: { - sessionsPerBrowser: 4, - testsPerSession: 5, - }, - }, -}; + const button = await browser.getByRole("button", { name: "Get started" }); + + await button.click(); + }); +}); ``` -#### Рекомендации по testsPerSession +#### Как работает параллелизм в данном примере + +Когда воркер получает тесты для Chrome, он открывает до 5 окон браузера одновременно. Каждое окно — это отдельная независимая сессия со своим `sessionId`. Для Firefox логика та же, но одновременно работают только 2 окна. -| Сценарий | Рекомендуемое значение | -| ----------------------------------------------------------- | ---------------------- | -| Тесты полностью изолированы, нет глобального состояния | 20–50 | -| Тесты частично изолированы (авторизация через `beforeEach`) | 10–20 | -| Тесты меняют глобальное состояние браузера | 1 | -| Отладка нестабильных тестов | 1 | -| Максимальное ускорение на `CI` | 40–100 | +:::warning Важно +`workers` управляет количеством `Node.js`-процессов, а `sessionsPerBrowser` — количеством одновременных браузерных сессий внутри каждого воркера. При workers: 1 все 7 сессий управляются одним процессом. +::: ## Шардирование @@ -204,11 +173,11 @@ export default { #### Плагин testplane-chunks -Для шардирования в Testplane используется официальный плагин `@testplane/chunks`. +Плагин `@testplane/chunks` позволяет распараллелить запуск тестов на нескольких серверах, тем самым ускорив процесс. Однако сам плагин не занимается какой-либо оркестрацией, распараллеливанием запуска или слиянием получившихся отдельных отчетов в один итоговый отчет. #### Установка и подключение -Чтобы установить плагин `@testplane/chunks`, выполните команду. +Для установки выполните команду: ```bash npm install -D @testplane/chunks @@ -217,93 +186,210 @@ npm install -D @testplane/chunks И укажите параметры в файле `testplane.config.ts`. ```typescript -// testplane.config.ts -export default { +module.exports = { plugins: { - "@testplane/chunks": { - enabled: true, + '@testplane/chunks': { + count: 7, // Разбить тесты на 7 порций (чанков) + run: 1 // Запустить первую порцию }, + + // другие плагины Testplane... }, - // остальные настройки... + + // другие настройки Testplane... }; ``` -#### Как работает шардирование +#### Расшифровка параметров конфигурации -Плагин делит список всех тестов на равные части по количеству тестов. Каждый запуск получает свой номер чанка и выполняет только свою часть тестов. +| Параметр | Тип | По умолчанию | Описание | +| --- | --- | --- | --- | +| `count` | `Number` | `1` | Количество порций (чанков), на которые нужно разбить набор тестов | +| `run` | `Number` | `1` | Номер чанка, тесты из которого нужно запустить | -```yaml -Все тесты (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 раза. +В качестве примера будет использован следующий набор тестов: -#### Запуск с указанием чанка +```typescript +describe("test examples", () => { + it("Поиск элемента по data-testid", async ({ browser }) => { + // Открываем страницу и ждем ее загрузки + await browser.openAndWait("https://testplane.io/"); -Номер чанка и общее количество чанков передаются через переменные окружения или CLI-параметры: + // Ищем элемент по атрибуту data-testid + const element = await browser.$('[data-testid="main-content"]'); -```bash -# Запустить первый чанк из четырех -npx testplane --chunks 4 --chunk 1 + // Проверяем существование элемента в DOM + const isExisting = await element.isExisting(); + console.log("Элемент с data-testid существует:", isExisting); + }); -# Запустить второй чанк из четырех -npx testplane --chunks 4 --chunk 2 -``` + it("Поиск элемента на главной странице", async ({ browser }) => { + await browser.openAndWait("https://testplane.io/"); -Или через переменные окружения: + // Ищем элемент по классу "navbar" + const navbar = await browser.$(".navbar"); -```bash -TESTPLANE_CHUNKS=4 TESTPLANE_CHUNK=1 npx testplane + // Проверяем, отображается ли элемент на странице + const isDisplayed = await navbar.isDisplayed(); + console.log("Навбар отображается:", isDisplayed); + }); + + it("Поиск элемента по id на главной странице", async ({ browser }) => { + await browser.openAndWait("https://testplane.io/"); + + // Ищем элемент по id "__docusaurus" + const main = await browser.$("#__docusaurus"); + + // Проверяем, отображается ли элемент на странице + const isDisplayed = await main.isDisplayed(); + console.log("Элемент отображается:", isDisplayed); + }); + + it("Поиск элемента по типу атрибута", async ({ browser }) => { + await browser.openAndWait("https://testplane.io/"); + + // Ищем кнопку по атрибуту type="button" + // Формат селектора: element[type="value"] + const button = await browser.$('button[type="button"]'); + + // Проверяем существование элемента в DOM + const isExisting = await button.isExisting(); + console.log("Кнопка существует:", isExisting); + }); + + it("Поиск элемента по тексту", async ({ browser }) => { + await browser.openAndWait("https://testplane.io/"); + + // Ищем элемент по тексту внутри него + const link = await browser.$('//a[text()="Docs"]'); + + // Проверяем существование элемента в DOM + const isExisting = await link.isExisting(); + console.log("Элемент с текстом существует:", isExisting); + }); + + it("Поиск элемента по атрибуту", async ({ browser }) => { + await browser.openAndWait("https://testplane.io/"); + + // Ищем элемент по атрибуту type + const button = await browser.$('//button[@type="button"]'); + + // Проверяем существование элемента в DOM + const isExisting = await button.isExisting(); + console.log("Элемент с атрибутом существует:", isExisting); + }); + + it("Поиск кнопки с помощью метода getByRole", async ({ browser }) => { + await browser.url("https://testplane.io/"); + + const button = await browser.getByRole("button", { name: "Get started" }); + + await button.click(); + }); +}); ``` +Резделение тестов на чанки: -#### Пример конфигурации GitHub Actions - -```yaml -# .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 }} +```css +Чанк 0 → тесты 1, 2, 3 (≈ первая треть) +Чанк 1 → тесты 4, 5 (≈ вторая треть) +Чанк 2 → тесты 6, 7 (≈ третья треть) ``` -#### Как рассчитать оптимальное количество чанков +Запуск каждого чанка отдельно через терминал: -```scss -Количество чанков = ceil(Общее время запуска / Целевое время запуска) +```bash +# Терминал 1 — Чанк 0 +CHUNKS_COUNT=3 CHUNKS_CURRENT=0 npx testplane + +# Терминал 2 — Чанк 1 +CHUNKS_COUNT=3 CHUNKS_CURRENT=1 npx testplane + +# Терминал 2 — Чанк 2 +CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane ``` -Пример: +#### Как плагин делит тесты -```text -2000 тестов выполняются за 60 минут на одной машине -Цель: уложиться в 10 минут -Необходимо: ceil(60 / 10) = 6 чанков +```css +Все тесты (после сортировки по fullTitle): +┌───┬────────────────────────────────────────────────────────┐ +│ 1 │ test examples. Поиск кнопки с помощью метода getByRole │ +├───┼────────────────────────────────────────────────────────┤ +│ 2 │ test examples. Поиск элемента на главной странице │ +├───┼────────────────────────────────────────────────────────┤ +│ 3 │ test examples. Поиск элемента по атрибуту │ +├───┼────────────────────────────────────────────────────────┤ +│ 4 │ test examples. Поиск элемента по data-testid │ +├───┼────────────────────────────────────────────────────────┤ +│ 5 │ test examples. Поиск элемента по id на главной стр. │ +├───┼────────────────────────────────────────────────────────┤ +│ 6 │ test examples. Поиск элемента по тексту │ +├───┼────────────────────────────────────────────────────────┤ +│ 7 │ test examples. Поиск элемента по типу атрибута │ +└───┴────────────────────────────────────────────────────────┘ + + │ + ▼ CHUNKS_COUNT=3 + +┌──────────┬──────────┬──────────┐ +│ Чанк 0 │ Чанк 1 │ Чанк 2 │ +├──────────┼──────────┼──────────┤ +│ тест 1 │ тест 4 │ тест 6 │ +│ тест 2 │ тест 5 │ тест 7 │ +│ тест 3 │ │ │ +└──────────┴──────────┴──────────┘ ``` -При этом убедитесь, что в каждом чанке достаточно тестов для эффективной загрузки воркеров: +:::tip Примечание +Главная идея чанков: если `workers` распределяет тесты внутри одного процесса, то чанки делят тесты между несколькими независимыми процессами — например, на разных `CI`-агентах или на одной машине через `concurrently`. +::: + +## Рекомендуемые настройки и их расчет + +| Параметр | Значение | Объяснение | +|---------------------|-------------------------------------------------------|-------------------------------------------------------------------------------------------------------------| +| `workers` | 8 | Рекомендованное значение — 8, но не больше количества ядер CPU | +| `sessionsPerBrowser`| min(слоты_грида_для_браузера, доступная_RAM / RAM_одного_браузера) | Реальное ограничение — ресурсы грида (слоты и RAM) | +| `testsPerSession` | min(тесты_до_деградации_браузера, тесты_за_время_жизни_сессии_грида) | Сессию нельзя переиспользовать бесконечно — браузер деградирует. Если грид принудительно закрывает сессию по времени, нужно вписаться в этот лимит. Параметр не влияет на параллельность, но влияет на стабильность прогона. | -```text -Тестов в одном чанке = Общее число тестов / Количество чанков - = 2000 / 6 ≈ 333 теста на чанк + +#### Пример + +```css +// CPU: 16 ядер +// Грид: Chrome 20 слотов, Firefox 10 слотов +// RAM грида: 8GB, Chrome ~500MB, Firefox ~300MB +// Грид убивает сессию через 10 минут +// Средний тест: 30 секунд +// Деградация браузера: после 100 тестов + +system: { + workers: 8 // min(8, 16) +}, +browsers: { + chrome: { + sessionsPerBrowser: 16, // min(20, 8000/500) + testsPerSession: 20 // min(100, 600/30) + }, + firefox: { + sessionsPerBrowser: 10, // min(10, 8000/300=26) + testsPerSession: 20 // min(100, 600/30) + } +} ``` -333 теста на чанк при `sessionsPerBrowser`: 10 и `testsPerSession`: 20 — разумное соотношение. -## Сводная таблица настроек -| Настройка | Уровень | За что отвечает | Влияет на | -| -------------------- | ------------ | ---------------------------------------------------------- | ------------------------------------------------- | -| `workers` | Глобальный | Количество параллельных `Node.js`-процессов | CPU, память на машине с тестами | -| `sessionsPerBrowser` | Браузер | Количество одновременных браузерных сессий | Нагрузку на `grid`, скорость прохождения | -| `testsPerSession` | Браузер | Сколько тестов выполнить в одной сессии до ее пересоздания | Скорость (меньше накладных расходов) vs изоляция | -| `chunks` (плагин) | `CI`-уровень | Разбивка всего набора на независимые части | Горизонтальное масштабирование на несколько машин | + + + + + + + + + + From 7440dd51bc24ca6ec3c8062a97366444fcbac3fe Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Mon, 6 Apr 2026 12:15:32 +0300 Subject: [PATCH 03/19] docs: character-fix --- .../current/basic-guides/parallelism.mdx | 101 +++++++----------- 1 file changed, 39 insertions(+), 62 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index cec6b06..37d4074 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -11,14 +11,14 @@ ```typescript // .testplane.config.ts export default { - browsers: { - chrome: { - sessionsPerBrowser: 5, // до 5 параллельных сессий Chrome - }, - firefox: { - sessionsPerBrowser: 2, // до 2 параллельных сессий Firefox + browsers: { + chrome: { + sessionsPerBrowser: 5, // до 5 параллельных сессий Chrome + }, + firefox: { + sessionsPerBrowser: 2, // до 2 параллельных сессий Firefox + }, }, - }, }; ``` @@ -28,8 +28,8 @@ export default { Параметр `workers` определяет, сколько дочерних процессов-воркеров будет запущено. Архитектурно это выглядит так: -* `Master`-процесс — координирует запуск, формирует очереди тестов и раздает задания воркерам -* `Worker`-процессы — непосредственно исполняют тесты +- `Master`-процесс — координирует запуск, формирует очереди тестов и раздает задания воркерам +- `Worker`-процессы — непосредственно исполняют тесты Каждый воркер — это отдельный поток, но внутри одного воркера тесты выполняются конкурентно: когда тест ждет ответа от браузера (`await`), воркер не простаивает, а переключается на следующий тест. Поэтому даже один воркер способен обслуживать множество параллельных браузерных сессий. @@ -43,13 +43,14 @@ export default { #### Пример -В рамках примера исполнять тесты будет один воркер: +В рамках примера исполнять тесты будет один воркер: ```typescript system: { workers: 1, }, ``` + Параметру sessionsPerBrowser присвоены значения `5`: ```typescript @@ -63,6 +64,7 @@ chrome: { waitTimeout: 10000, } ``` + и `2`: ```typescript @@ -188,9 +190,9 @@ npm install -D @testplane/chunks ```typescript module.exports = { plugins: { - '@testplane/chunks': { + "@testplane/chunks": { count: 7, // Разбить тесты на 7 порций (чанков) - run: 1 // Запустить первую порцию + run: 1, // Запустить первую порцию }, // другие плагины Testplane... @@ -202,10 +204,10 @@ module.exports = { #### Расшифровка параметров конфигурации -| Параметр | Тип | По умолчанию | Описание | -| --- | --- | --- | --- | -| `count` | `Number` | `1` | Количество порций (чанков), на которые нужно разбить набор тестов | -| `run` | `Number` | `1` | Номер чанка, тесты из которого нужно запустить | +| Параметр | Тип | По умолчанию | Описание | +| -------- | -------- | ------------ | ----------------------------------------------------------------- | +| `count` | `Number` | `1` | Количество порций (чанков), на которые нужно разбить набор тестов | +| `run` | `Number` | `1` | Номер чанка, тесты из которого нужно запустить | #### Как разбить запуск тестов @@ -290,6 +292,7 @@ describe("test examples", () => { }); }); ``` + Резделение тестов на чанки: ```css @@ -314,33 +317,21 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane #### Как плагин делит тесты ```css -Все тесты (после сортировки по fullTitle): -┌───┬────────────────────────────────────────────────────────┐ -│ 1 │ test examples. Поиск кнопки с помощью метода getByRole │ -├───┼────────────────────────────────────────────────────────┤ -│ 2 │ test examples. Поиск элемента на главной странице │ -├───┼────────────────────────────────────────────────────────┤ -│ 3 │ test examples. Поиск элемента по атрибуту │ -├───┼────────────────────────────────────────────────────────┤ -│ 4 │ test examples. Поиск элемента по data-testid │ -├───┼────────────────────────────────────────────────────────┤ -│ 5 │ test examples. Поиск элемента по id на главной стр. │ -├───┼────────────────────────────────────────────────────────┤ -│ 6 │ test examples. Поиск элемента по тексту │ -├───┼────────────────────────────────────────────────────────┤ -│ 7 │ test examples. Поиск элемента по типу атрибута │ -└───┴────────────────────────────────────────────────────────┘ - - │ - ▼ CHUNKS_COUNT=3 - -┌──────────┬──────────┬──────────┐ -│ Чанк 0 │ Чанк 1 │ Чанк 2 │ -├──────────┼──────────┼──────────┤ -│ тест 1 │ тест 4 │ тест 6 │ -│ тест 2 │ тест 5 │ тест 7 │ -│ тест 3 │ │ │ -└──────────┴──────────┴──────────┘ +всетесты (после сортировки по fullTitle): ┌───┬────────────────────────────────────────────────────────┐ + │ 1 │ test examples. Поиск кнопки с помощью метода getByRole │ + ├───┼────────────────────────────────────────────────────────┤ │ 2 │ test examples. Поиск + элемента на главной странице │ ├───┼────────────────────────────────────────────────────────┤ │ + 3 │ test examples. Поиск элемента по атрибуту │ + ├───┼────────────────────────────────────────────────────────┤ │ 4 │ test examples. Поиск + элемента по data-testid │ ├───┼────────────────────────────────────────────────────────┤ │ 5 │ + test examples. Поиск элемента по id на главной стр. │ + ├───┼────────────────────────────────────────────────────────┤ │ 6 │ test examples. Поиск + элемента по тексту │ ├───┼────────────────────────────────────────────────────────┤ │ 7 │ test + examples. Поиск элемента по типу атрибута │ + └───┴────────────────────────────────────────────────────────┘ │ ▼ CHUNKS_COUNT=3 + ┌──────────┬──────────┬──────────┐ │ Чанк 0 │ Чанк 1 │ Чанк 2 │ + ├──────────┼──────────┼──────────┤ │ тест 1 │ тест 4 │ тест 6 │ │ тест 2 │ тест 5 │ тест 7 │ │ + тест 3 │ │ │ └──────────┴──────────┴──────────┘; ``` :::tip Примечание @@ -349,12 +340,11 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane ## Рекомендуемые настройки и их расчет -| Параметр | Значение | Объяснение | -|---------------------|-------------------------------------------------------|-------------------------------------------------------------------------------------------------------------| -| `workers` | 8 | Рекомендованное значение — 8, но не больше количества ядер CPU | -| `sessionsPerBrowser`| min(слоты_грида_для_браузера, доступная_RAM / RAM_одного_браузера) | Реальное ограничение — ресурсы грида (слоты и RAM) | -| `testsPerSession` | min(тесты_до_деградации_браузера, тесты_за_время_жизни_сессии_грида) | Сессию нельзя переиспользовать бесконечно — браузер деградирует. Если грид принудительно закрывает сессию по времени, нужно вписаться в этот лимит. Параметр не влияет на параллельность, но влияет на стабильность прогона. | - +| Параметр | Значение | Объяснение | +| -------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `workers` | 8 | Рекомендованное значение — 8, но не больше количества ядер CPU | +| `sessionsPerBrowser` | min(слоты*грида*для*браузера, доступная_RAM / RAM*одного_браузера) | Реальное ограничение — ресурсы грида (слоты и RAM) | +| `testsPerSession` | min(тесты*до*деградации*браузера, тесты*за*время*жизни*сессии*грида) | Сессию нельзя переиспользовать бесконечно — браузер деградирует. Если грид принудительно закрывает сессию по времени, нужно вписаться в этот лимит. Параметр не влияет на параллельность, но влияет на стабильность прогона. | #### Пример @@ -380,16 +370,3 @@ browsers: { } } ``` - - - - - - - - - - - - - From c98a6c52c47067eb20340dfe74a2521c37c1d3da Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Mon, 6 Apr 2026 12:20:51 +0300 Subject: [PATCH 04/19] docs: character-fix --- .../current/basic-guides/parallelism.mdx | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index 37d4074..1624bcc 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -317,21 +317,35 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane #### Как плагин делит тесты ```css -всетесты (после сортировки по fullTitle): ┌───┬────────────────────────────────────────────────────────┐ - │ 1 │ test examples. Поиск кнопки с помощью метода getByRole │ - ├───┼────────────────────────────────────────────────────────┤ │ 2 │ test examples. Поиск - элемента на главной странице │ ├───┼────────────────────────────────────────────────────────┤ │ - 3 │ test examples. Поиск элемента по атрибуту │ - ├───┼────────────────────────────────────────────────────────┤ │ 4 │ test examples. Поиск - элемента по data-testid │ ├───┼────────────────────────────────────────────────────────┤ │ 5 │ - test examples. Поиск элемента по id на главной стр. │ - ├───┼────────────────────────────────────────────────────────┤ │ 6 │ test examples. Поиск - элемента по тексту │ ├───┼────────────────────────────────────────────────────────┤ │ 7 │ test - examples. Поиск элемента по типу атрибута │ - └───┴────────────────────────────────────────────────────────┘ │ ▼ CHUNKS_COUNT=3 - ┌──────────┬──────────┬──────────┐ │ Чанк 0 │ Чанк 1 │ Чанк 2 │ - ├──────────┼──────────┼──────────┤ │ тест 1 │ тест 4 │ тест 6 │ │ тест 2 │ тест 5 │ тест 7 │ │ - тест 3 │ │ │ └──────────┴──────────┴──────────┘; +все тесты (после сортировки по fullTitle): + +┌───┬────────────────────────────────────────────────────────┐ +│ 1 │ test examples. Поиск кнопки с помощью метода getByRole │ +├───┼────────────────────────────────────────────────────────┤ +│ 2 │ test examples. Поиск элемента на главной странице │ +├───┼────────────────────────────────────────────────────────┤ +│ 3 │ test examples. Поиск элемента по атрибуту │ +├───┼────────────────────────────────────────────────────────┤ +│ 4 │ test examples. Поиск элемента по data-testid │ +├───┼────────────────────────────────────────────────────────┤ +│ 5 │ test examples. Поиск элемента по id на главной стр. │ +├───┼────────────────────────────────────────────────────────┤ +│ 6 │ test examples. Поиск элемента по тексту │ +├───┼────────────────────────────────────────────────────────┤ +│ 7 │ test examples. Поиск элемента по типу атрибута │ +└───┴────────────────────────────────────────────────────────┘ + + │ + ▼ CHUNKS_COUNT=3 + +┌──────────┬──────────┬──────────┐ +│ Чанк 0 │ Чанк 1 │ Чанк 2 │ +├──────────┼──────────┼──────────┤ +│ тест 1 │ тест 4 │ тест 6 │ +│ тест 2 │ тест 5 │ тест 7 │ +│ тест 3 │ │ │ +└──────────┴──────────┴──────────┘ + ``` :::tip Примечание From 4468c114fb1793150804cbbcfd4d048212225a32 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Mon, 6 Apr 2026 12:26:45 +0300 Subject: [PATCH 05/19] docs: character-fix --- .../current/basic-guides/parallelism.mdx | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index 1624bcc..ef0d6f6 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -316,28 +316,9 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane #### Как плагин делит тесты -```css -все тесты (после сортировки по fullTitle): - -┌───┬────────────────────────────────────────────────────────┐ -│ 1 │ test examples. Поиск кнопки с помощью метода getByRole │ -├───┼────────────────────────────────────────────────────────┤ -│ 2 │ test examples. Поиск элемента на главной странице │ -├───┼────────────────────────────────────────────────────────┤ -│ 3 │ test examples. Поиск элемента по атрибуту │ -├───┼────────────────────────────────────────────────────────┤ -│ 4 │ test examples. Поиск элемента по data-testid │ -├───┼────────────────────────────────────────────────────────┤ -│ 5 │ test examples. Поиск элемента по id на главной стр. │ -├───┼────────────────────────────────────────────────────────┤ -│ 6 │ test examples. Поиск элемента по тексту │ -├───┼────────────────────────────────────────────────────────┤ -│ 7 │ test examples. Поиск элемента по типу атрибута │ -└───┴────────────────────────────────────────────────────────┘ - - │ - ▼ CHUNKS_COUNT=3 +После сортировки по `fullTitle` набор тестов делится на 3 чанка: +```css ┌──────────┬──────────┬──────────┐ │ Чанк 0 │ Чанк 1 │ Чанк 2 │ ├──────────┼──────────┼──────────┤ @@ -345,7 +326,6 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane │ тест 2 │ тест 5 │ тест 7 │ │ тест 3 │ │ │ └──────────┴──────────┴──────────┘ - ``` :::tip Примечание From c0370dc5ce264554741adf6d8b6475557aef2822 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Mon, 6 Apr 2026 13:32:26 +0300 Subject: [PATCH 06/19] docs: settings-fix --- .../current/basic-guides/parallelism.mdx | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index ef0d6f6..ca279f4 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -334,11 +334,10 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane ## Рекомендуемые настройки и их расчет -| Параметр | Значение | Объяснение | -| -------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `workers` | 8 | Рекомендованное значение — 8, но не больше количества ядер CPU | -| `sessionsPerBrowser` | min(слоты*грида*для*браузера, доступная_RAM / RAM*одного_браузера) | Реальное ограничение — ресурсы грида (слоты и RAM) | -| `testsPerSession` | min(тесты*до*деградации*браузера, тесты*за*время*жизни*сессии*грида) | Сессию нельзя переиспользовать бесконечно — браузер деградирует. Если грид принудительно закрывает сессию по времени, нужно вписаться в этот лимит. Параметр не влияет на параллельность, но влияет на стабильность прогона. | +| Параметр | Значение | Объяснение | +| -------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `workers` | 8 | Рекомендованное значение — 8, но не больше количества ядер CPU. | +| `sessionsPerBrowser` | — | Количество сессий подбирается исходя из доступных ресурсов. При этом важно учитывать и возможности, например, вашего dev‑сервера, который раздаёт страницы для тестирования. Например, вы можете поднять 100 браузеров, но ваш сервер не будет успевать отдавать статику каждому браузеру. В итоге при большей параллельности вы получите замедление выполнения тестов. | #### Пример @@ -351,16 +350,17 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane // Деградация браузера: после 100 тестов system: { - workers: 8 // min(8, 16) -}, + workers: 8 // min(8, 16) +; +} +, browsers: { - chrome: { - sessionsPerBrowser: 16, // min(20, 8000/500) - testsPerSession: 20 // min(100, 600/30) - }, + chrome: { + sessionsperbrowser: 16; + } + , firefox: { - sessionsPerBrowser: 10, // min(10, 8000/300=26) - testsPerSession: 20 // min(100, 600/30) - } + sessionsperbrowser: 10; + } } ``` From 9e6ef78d15a2ecebb54c310d29eeeb1b2ab42ed0 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Mon, 6 Apr 2026 14:30:40 +0300 Subject: [PATCH 07/19] docs: sessions-fix --- .../current/basic-guides/parallelism.mdx | 53 +++++++++---------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index ca279f4..270d947 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -163,7 +163,25 @@ describe("test examples", () => { #### Как работает параллелизм в данном примере -Когда воркер получает тесты для Chrome, он открывает до 5 окон браузера одновременно. Каждое окно — это отдельная независимая сессия со своим `sessionId`. Для Firefox логика та же, но одновременно работают только 2 окна. +Когда воркер получает тесты для Chrome, он открывает до 5 окон браузера одновременно. Каждое окно — это отдельная независимая сессия со своим `sessionId`: + +```bash +Тест 1 → сессия chrome:abc123 → открывается окно Chrome #1 +Тест 2 → сессия chrome:def456 → открывается окно Chrome #2 +Тест 3 → сессия chrome:ghi789 → открывается окно Chrome #3 +Тест 4 → сессия chrome:jkl012 → открывается окно Chrome #4 +Тест 5 → сессия chrome:mno345 → открывается окно Chrome #5 +``` + +Логика та же, но одновременно работают только 2 окна Firefox. Это ограничение задано через `sessionsPerBrowser`: + +```bash +Тест 1 → сессия firefox:fb59f7 → открывается окно Firefox #1 +Тест 2 → сессия firefox:660ee0 → открывается окно Firefox #2 +Тест 3 → ждёт в очереди... + как только тест 1 завершился → сессия fb59f7 освободилась +Тест 3 → сессия firefox:fb59f7 → то же окно Firefox #1, новый тест +``` :::warning Важно `workers` управляет количеством `Node.js`-процессов, а `sessionsPerBrowser` — количеством одновременных браузерных сессий внутри каждого воркера. При workers: 1 все 7 сессий управляются одним процессом. @@ -334,33 +352,12 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane ## Рекомендуемые настройки и их расчет -| Параметр | Значение | Объяснение | -| -------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `workers` | 8 | Рекомендованное значение — 8, но не больше количества ядер CPU. | -| `sessionsPerBrowser` | — | Количество сессий подбирается исходя из доступных ресурсов. При этом важно учитывать и возможности, например, вашего dev‑сервера, который раздаёт страницы для тестирования. Например, вы можете поднять 100 браузеров, но ваш сервер не будет успевать отдавать статику каждому браузеру. В итоге при большей параллельности вы получите замедление выполнения тестов. | +#### workers -#### Пример +Рекомендуемым значение — `8`. Любое другое не должно превышать количество ядер CPU. -```css -// CPU: 16 ядер -// Грид: Chrome 20 слотов, Firefox 10 слотов -// RAM грида: 8GB, Chrome ~500MB, Firefox ~300MB -// Грид убивает сессию через 10 минут -// Средний тест: 30 секунд -// Деградация браузера: после 100 тестов +#### sessionsPerBrowser -system: { - workers: 8 // min(8, 16) -; -} -, -browsers: { - chrome: { - sessionsperbrowser: 16; - } - , - firefox: { - sessionsperbrowser: 10; - } -} -``` +При локальном запуске значение не превышает `5`. В ином случает примерное значение можно вычислить путем деления доступных ресурсов на требуемое для конкретного браузера. При расчете помните о затратах на запуск самих тестов. + +#### Рассчет чанков From f96dad948d0a98493cb41178a2fa0575d0108752 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Tue, 7 Apr 2026 09:29:01 +0300 Subject: [PATCH 08/19] docs: character-fix --- .../current/basic-guides/parallelism.mdx | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index 270d947..3e96a97 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -4,7 +4,7 @@ Параллельность в Testplane — это возможность одновременно выполнять несколько тестовых сценариев в разных браузерных сессиях, чтобы сократить общее время прогона тестов. -#### sessionsPerBrowser +### sessionsPerBrowser В конфигурационном файле объявляются типы браузеров в поле `browsers`. Для каждого типа браузера независимо настраивается, сколько экземпляров может работать одновременно: @@ -24,7 +24,7 @@ export default { Параметр `sessionsPerBrowser` является ключевым в рамках управления параллельностью. Он определяет, сколько браузеров одного типа Testplane запустит одновременно. По умолчанию значение: `1`. -#### Воркеры +### Воркеры Параметр `workers` определяет, сколько дочерних процессов-воркеров будет запущено. Архитектурно это выглядит так: @@ -37,21 +37,13 @@ export default { `workers` и `sessionsPerBrowser` — независимые ограничения. Увеличение числа воркеров не увеличивает реальную параллельность, если `sessionsPerBrowser` остается прежним. ::: -#### testsPerSession +### testsPerSession Параметр `testsPerSession` отвечает за то, сколько тестов можно запускать последовательно в одной сессии браузера. Параметр ограничивает переиспользование сессии, чтобы не допустить падения тестов из-за деградации браузера, и не имеет отношения к параллельному запуску тестов. -#### Пример +### Как это работает -В рамках примера исполнять тесты будет один воркер: - -```typescript -system: { - workers: 1, - }, -``` - -Параметру sessionsPerBrowser присвоены значения `5`: +В рамках примера параметру `sessionsPerBrowser` присвоены значения `5`: ```typescript chrome: { @@ -79,6 +71,14 @@ firefox: { } ``` +Значение параметра `workers`: + +```typescript +system: { + workers: 1, + }, +``` + Далее тесты: ```typescript @@ -184,14 +184,14 @@ describe("test examples", () => { ``` :::warning Важно -`workers` управляет количеством `Node.js`-процессов, а `sessionsPerBrowser` — количеством одновременных браузерных сессий внутри каждого воркера. При workers: 1 все 7 сессий управляются одним процессом. +`workers` управляет количеством `Node.js`-процессов, а `sessionsPerBrowser` — количеством одновременных браузерных сессий внутри каждого воркера. При `workers`: `1` все 7 сессий управляются одним процессом. ::: ## Шардирование При наличии тысяч тестов время одного запуска может быть неприемлемо большим даже при максимальном параллелизме. В таких случаях используют шардирование — разбивку всего набора тестов на несколько независимых частей (чанков), которые запускаются параллельно на разных машинах или в разных `CI`-джобах. -#### Плагин testplane-chunks +### Плагин testplane-chunks Плагин `@testplane/chunks` позволяет распараллелить запуск тестов на нескольких серверах, тем самым ускорив процесс. Однако сам плагин не занимается какой-либо оркестрацией, распараллеливанием запуска или слиянием получившихся отдельных отчетов в один итоговый отчет. @@ -227,7 +227,7 @@ module.exports = { | `count` | `Number` | `1` | Количество порций (чанков), на которые нужно разбить набор тестов | | `run` | `Number` | `1` | Номер чанка, тесты из которого нужно запустить | -#### Как разбить запуск тестов +### Как разбить запуск тестов В качестве примера будет использован следующий набор тестов: @@ -350,6 +350,11 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane Главная идея чанков: если `workers` распределяет тесты внутри одного процесса, то чанки делят тесты между несколькими независимыми процессами — например, на разных `CI`-агентах или на одной машине через `concurrently`. ::: +#### Как объединить отчеты чанков + +Чтобы объединить несколько отчетов в один, используйте команду `merge-reports` + + ## Рекомендуемые настройки и их расчет #### workers @@ -360,4 +365,4 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane При локальном запуске значение не превышает `5`. В ином случает примерное значение можно вычислить путем деления доступных ресурсов на требуемое для конкретного браузера. При расчете помните о затратах на запуск самих тестов. -#### Рассчет чанков +#### Расчет чанков From d47f5ce85961b02d50f83f8c870acd951dae506f Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Tue, 7 Apr 2026 09:31:23 +0300 Subject: [PATCH 09/19] docs: character-fix --- .../current/basic-guides/parallelism.mdx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index 3e96a97..e4f95ab 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -39,7 +39,7 @@ export default { ### testsPerSession -Параметр `testsPerSession` отвечает за то, сколько тестов можно запускать последовательно в одной сессии браузера. Параметр ограничивает переиспользование сессии, чтобы не допустить падения тестов из-за деградации браузера, и не имеет отношения к параллельному запуску тестов. +Параметр `testsPerSession` отвечает за то, сколько тестов можно запускать последовательно в одной сессии браузера. Он ограничивает переиспользование сессии, чтобы не допустить падения тестов из-за деградации браузера, и не имеет отношения к параллельному запуску тестов. ### Как это работает @@ -52,7 +52,6 @@ chrome: { browserName: "chrome" }, sessionsPerBrowser: 5, // 5 параллельных сессий Chrome - testsPerSession: 3, waitTimeout: 10000, } ``` @@ -66,7 +65,6 @@ firefox: { browserName: "firefox" }, sessionsPerBrowser: 2, // 2 параллельные сессии Firefox - testsPerSession: 3, waitTimeout: 10000, } ``` @@ -354,7 +352,6 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane Чтобы объединить несколько отчетов в один, используйте команду `merge-reports` - ## Рекомендуемые настройки и их расчет #### workers From 80ec6b9514288f076a151c64d5b2c904138395d5 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Tue, 7 Apr 2026 09:38:06 +0300 Subject: [PATCH 10/19] docs: reports-add --- .../current/basic-guides/parallelism.mdx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index e4f95ab..daacc89 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -330,7 +330,7 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=1 npx testplane CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane ``` -#### Как плагин делит тесты +### Как плагин делит тесты После сортировки по `fullTitle` набор тестов делится на 3 чанка: @@ -348,13 +348,19 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane Главная идея чанков: если `workers` распределяет тесты внутри одного процесса, то чанки делят тесты между несколькими независимыми процессами — например, на разных `CI`-агентах или на одной машине через `concurrently`. ::: -#### Как объединить отчеты чанков +### Как объединить отчеты -Чтобы объединить несколько отчетов в один, используйте команду `merge-reports` +Чтобы объединить несколько отчетов в один, используйте команду `merge-reports`. Она принимает пути к директориям с отчетами, файлам баз данных или к файлам `databaseUrls.json`, после чего создает новый html-отчет в папке назначения с данными из всех переданных отчетов. + +Пример использования: + +```bash +npx html-reporter merge-reports report-dir/ path-to-database.db path-to-databaseUrls.json -d dest-report -h foo=bar +``` ## Рекомендуемые настройки и их расчет -#### workers +#### Воркеры Рекомендуемым значение — `8`. Любое другое не должно превышать количество ядер CPU. From 7cb70b5b3b02f0e73444e8128efd86016e41a937 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Tue, 7 Apr 2026 11:25:25 +0300 Subject: [PATCH 11/19] docs: chunks-fix --- .../current/basic-guides/parallelism.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index daacc89..de6fc9e 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -161,7 +161,7 @@ describe("test examples", () => { #### Как работает параллелизм в данном примере -Когда воркер получает тесты для Chrome, он открывает до 5 окон браузера одновременно. Каждое окно — это отдельная независимая сессия со своим `sessionId`: +Для Chrome открывается до 5 окон браузера одновременно. Каждое из них — это отдельная независимая сессия со своим `sessionId`: ```bash Тест 1 → сессия chrome:abc123 → открывается окно Chrome #1 @@ -171,7 +171,7 @@ describe("test examples", () => { Тест 5 → сессия chrome:mno345 → открывается окно Chrome #5 ``` -Логика та же, но одновременно работают только 2 окна Firefox. Это ограничение задано через `sessionsPerBrowser`: +Для Firefox логика та же, но одновременно работают только 2 окна. Это ограничение задано через `sessionsPerBrowser`: ```bash Тест 1 → сессия firefox:fb59f7 → открывается окно Firefox #1 @@ -369,3 +369,4 @@ npx html-reporter merge-reports report-dir/ path-to-database.db path-to-database При локальном запуске значение не превышает `5`. В ином случает примерное значение можно вычислить путем деления доступных ресурсов на требуемое для конкретного браузера. При расчете помните о затратах на запуск самих тестов. #### Расчет чанков + From 7817151f95fcc84455b63c93e86c6bcd61638a4e Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Tue, 7 Apr 2026 11:29:02 +0300 Subject: [PATCH 12/19] docs: character-fix --- .../current/basic-guides/parallelism.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index de6fc9e..53db17e 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -369,4 +369,3 @@ npx html-reporter merge-reports report-dir/ path-to-database.db path-to-database При локальном запуске значение не превышает `5`. В ином случает примерное значение можно вычислить путем деления доступных ресурсов на требуемое для конкретного браузера. При расчете помните о затратах на запуск самих тестов. #### Расчет чанков - From d1eaf7f4564b2659a73b3d842b2a6d6c70dea328 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Thu, 9 Apr 2026 08:06:32 +0300 Subject: [PATCH 13/19] docs: chunks-fix --- .../current/basic-guides/parallelism.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index 53db17e..f6b7856 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -368,4 +368,4 @@ npx html-reporter merge-reports report-dir/ path-to-database.db path-to-database При локальном запуске значение не превышает `5`. В ином случает примерное значение можно вычислить путем деления доступных ресурсов на требуемое для конкретного браузера. При расчете помните о затратах на запуск самих тестов. -#### Расчет чанков +#### Количество чанков From 4695057e3a6ac90085abe8bd9ba28d4642afb29a Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Mon, 13 Apr 2026 10:48:35 +0300 Subject: [PATCH 14/19] docs: chunks-fix --- .../current/basic-guides/parallelism.mdx | 131 ++++++++---------- 1 file changed, 56 insertions(+), 75 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index f6b7856..e75a078 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -43,7 +43,7 @@ export default { ### Как это работает -В рамках примера параметру `sessionsPerBrowser` присвоены значения `5`: +В рамках примера параметру `sessionsPerBrowser` присвоены значения 5: ```typescript chrome: { @@ -56,7 +56,7 @@ chrome: { } ``` -и `2`: +и 2: ```typescript firefox: { @@ -229,92 +229,64 @@ module.exports = { В качестве примера будет использован следующий набор тестов: -```typescript -describe("test examples", () => { - it("Поиск элемента по data-testid", async ({ browser }) => { - // Открываем страницу и ждем ее загрузки - await browser.openAndWait("https://testplane.io/"); - - // Ищем элемент по атрибуту data-testid - const element = await browser.$('[data-testid="main-content"]'); - - // Проверяем существование элемента в DOM - const isExisting = await element.isExisting(); - console.log("Элемент с data-testid существует:", isExisting); - }); - - it("Поиск элемента на главной странице", async ({ browser }) => { - await browser.openAndWait("https://testplane.io/"); - - // Ищем элемент по классу "navbar" - const navbar = await browser.$(".navbar"); - - // Проверяем, отображается ли элемент на странице - const isDisplayed = await navbar.isDisplayed(); - console.log("Навбар отображается:", isDisplayed); - }); - - it("Поиск элемента по id на главной странице", async ({ browser }) => { - await browser.openAndWait("https://testplane.io/"); +```text +project/ +├── .testplane.conf.js +├── package.json +└── tests/ + ├── registration.testplane.js # 500 тестов + ├── payment.testplane.js # 500 тестов + └── auth.testplane.js # 500 тестов +``` - // Ищем элемент по id "__docusaurus" - const main = await browser.$("#__docusaurus"); +```javascript +//registration.testplane.js - // Проверяем, отображается ли элемент на странице - const isDisplayed = await main.isDisplayed(); - console.log("Элемент отображается:", isDisplayed); - }); +describe("Регистрация", () => { + it("тест 1 - пустой email показывает ошибку", async ({ browser }) => {}); + it("тест 2 - невалидный формат email", async ({ browser }) => {}); + it("тест 3 - пустой пароль показывает ошибку", async ({ browser }) => {}); - it("Поиск элемента по типу атрибута", async ({ browser }) => { - await browser.openAndWait("https://testplane.io/"); + // ... - // Ищем кнопку по атрибуту type="button" - // Формат селектора: element[type="value"] - const button = await browser.$('button[type="button"]'); - - // Проверяем существование элемента в DOM - const isExisting = await button.isExisting(); - console.log("Кнопка существует:", isExisting); - }); - - it("Поиск элемента по тексту", async ({ browser }) => { - await browser.openAndWait("https://testplane.io/"); + // тест 500 +}); +``` - // Ищем элемент по тексту внутри него - const link = await browser.$('//a[text()="Docs"]'); +```javascript +//payment.testplane.js - // Проверяем существование элемента в DOM - const isExisting = await link.isExisting(); - console.log("Элемент с текстом существует:", isExisting); - }); +describe("Оплата", () => { + it("тест 1 - пустой номер карты показывает ошибку", async ({ browser }) => {}); + it("тест 2 - невалидный номер карты", async ({ browser }) => {}); + it("тест 3 - истёкший срок действия карты", async ({ browser }) => {}); - it("Поиск элемента по атрибуту", async ({ browser }) => { - await browser.openAndWait("https://testplane.io/"); + // ... - // Ищем элемент по атрибуту type - const button = await browser.$('//button[@type="button"]'); + // тест 500 +}); +``` - // Проверяем существование элемента в DOM - const isExisting = await button.isExisting(); - console.log("Элемент с атрибутом существует:", isExisting); - }); +```javascript +//auth.testplane.js - it("Поиск кнопки с помощью метода getByRole", async ({ browser }) => { - await browser.url("https://testplane.io/"); +describe("Авторизация", () => { + it("тест 1 - пустой email показывает ошибку", async ({ browser }) => {}); + it("тест 2 - пустой пароль показывает ошибку", async ({ browser }) => {}); + it("тест 3 - неверный пароль показывает ошибку", async ({ browser }) => {}); - const button = await browser.getByRole("button", { name: "Get started" }); + // ... - await button.click(); - }); + // тест 500 }); ``` Резделение тестов на чанки: ```css -Чанк 0 → тесты 1, 2, 3 (≈ первая треть) -Чанк 1 → тесты 4, 5 (≈ вторая треть) -Чанк 2 → тесты 6, 7 (≈ третья треть) +Чанк 0 → тесты 1, 2, ..., 500 (≈ первая треть) +Чанк 1 → тесты 1, 2, ..., 500 (≈ вторая треть) +Чанк 2 → тесты 1, 2, ..., 500 (≈ третья треть) ``` Запуск каждого чанка отдельно через терминал: @@ -338,9 +310,10 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane ┌──────────┬──────────┬──────────┐ │ Чанк 0 │ Чанк 1 │ Чанк 2 │ ├──────────┼──────────┼──────────┤ -│ тест 1 │ тест 4 │ тест 6 │ -│ тест 2 │ тест 5 │ тест 7 │ -│ тест 3 │ │ │ +│ тест 1 │ тест 1 │ тест 1 │ +│ тест 2 │ тест 2 │ тест 2 │ +│ ... │ ... │ ... │ +│ тест 500 │ тест 500 │ тест 500 │ └──────────┴──────────┴──────────┘ ``` @@ -362,10 +335,18 @@ npx html-reporter merge-reports report-dir/ path-to-database.db path-to-database #### Воркеры -Рекомендуемым значение — `8`. Любое другое не должно превышать количество ядер CPU. +Рекомендуемое значение — 8. Любое другое не должно превышать количество ядер CPU. #### sessionsPerBrowser -При локальном запуске значение не превышает `5`. В ином случает примерное значение можно вычислить путем деления доступных ресурсов на требуемое для конкретного браузера. При расчете помните о затратах на запуск самих тестов. +При локальном запуске значение не превышает 5. В ином случает примерное значение можно вычислить путем деления доступных ресурсов на требуемое для конкретного браузера. При расчете помните о затратах на запуск самих тестов. #### Количество чанков + +При расчете количества чанков необходимо отталкиваться от: + +- количества доступных браузеров +- оверхеда на создание чанка +- желаемого общего времени прогона + +Рекомендация — не меньше 500 тестов на чанк. From 5415561e963be2c9b9f317b2ccb9527253cb82cf Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Fri, 17 Apr 2026 11:14:44 +0300 Subject: [PATCH 15/19] docs: cut-fix --- .../current/basic-guides/parallelism.mdx | 281 ++++++++++-------- 1 file changed, 161 insertions(+), 120 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index e75a078..95ffc6f 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -2,7 +2,7 @@ ## Параллельность в Testplane -Параллельность в Testplane — это возможность одновременно выполнять несколько тестовых сценариев в разных браузерных сессиях, чтобы сократить общее время прогона тестов. +Testplane запускает тесты параллельно с помощью запуска нескольких браузеров одновременно, которые управляются одним или нексколькими воркерами. Параллельное выполнение тестов позволяет значительно сократить общее время прогона тестов. ### sessionsPerBrowser @@ -24,7 +24,7 @@ export default { Параметр `sessionsPerBrowser` является ключевым в рамках управления параллельностью. Он определяет, сколько браузеров одного типа Testplane запустит одновременно. По умолчанию значение: `1`. -### Воркеры +### Workers Параметр `workers` определяет, сколько дочерних процессов-воркеров будет запущено. Архитектурно это выглядит так: @@ -41,40 +41,46 @@ export default { Параметр `testsPerSession` отвечает за то, сколько тестов можно запускать последовательно в одной сессии браузера. Он ограничивает переиспользование сессии, чтобы не допустить падения тестов из-за деградации браузера, и не имеет отношения к параллельному запуску тестов. -### Как это работает +### Пример В рамках примера параметру `sessionsPerBrowser` присвоены значения 5: ```typescript -chrome: { - headless: true, - desiredCapabilities: { - browserName: "chrome" - }, - sessionsPerBrowser: 5, // 5 параллельных сессий Chrome - waitTimeout: 10000, - } +const config = { + chrome: { + headless: true, + desiredCapabilities: { + browserName: "chrome", + }, + sessionsPerBrowser: 5, // 5 параллельных сессий Chrome + waitTimeout: 10000, + }, +}; ``` и 2: ```typescript -firefox: { - headless: true, - desiredCapabilities: { - browserName: "firefox" - }, - sessionsPerBrowser: 2, // 2 параллельные сессии Firefox - waitTimeout: 10000, - } +const config = { + firefox: { + headless: true, + desiredCapabilities: { + browserName: "firefox", + }, + sessionsPerBrowser: 2, // 2 параллельные сессии Firefox + waitTimeout: 10000, + }, +}; ``` Значение параметра `workers`: ```typescript -system: { +const config = { + system: { workers: 1, }, +}; ``` Далее тесты: @@ -82,103 +88,72 @@ system: { ```typescript describe("test examples", () => { it("Поиск элемента по data-testid", async ({ browser }) => { - // Открываем страницу и ждем ее загрузки - await browser.openAndWait("https://testplane.io/"); - - // Ищем элемент по атрибуту data-testid - const element = await browser.$('[data-testid="main-content"]'); - - // Проверяем существование элемента в DOM - const isExisting = await element.isExisting(); - console.log("Элемент с data-testid существует:", isExisting); + // тело теста }); it("Поиск элемента на главной странице", async ({ browser }) => { - await browser.openAndWait("https://testplane.io/"); - - // Ищем элемент по классу "navbar" - const navbar = await browser.$(".navbar"); - - // Проверяем, отображается ли элемент на странице - const isDisplayed = await navbar.isDisplayed(); - console.log("Навбар отображается:", isDisplayed); + // тело теста }); it("Поиск элемента по id на главной странице", async ({ browser }) => { - await browser.openAndWait("https://testplane.io/"); - - // Ищем элемент по id "__docusaurus" - const main = await browser.$("#__docusaurus"); - - // Проверяем, отображается ли элемент на странице - const isDisplayed = await main.isDisplayed(); - console.log("Элемент отображается:", isDisplayed); + // тело теста }); it("Поиск элемента по типу атрибута", async ({ browser }) => { - await browser.openAndWait("https://testplane.io/"); - - // Ищем кнопку по атрибуту type="button" - // Формат селектора: element[type="value"] - const button = await browser.$('button[type="button"]'); - - // Проверяем существование элемента в DOM - const isExisting = await button.isExisting(); - console.log("Кнопка существует:", isExisting); + // тело теста }); it("Поиск элемента по тексту", async ({ browser }) => { - await browser.openAndWait("https://testplane.io/"); - - // Ищем элемент по тексту внутри него - const link = await browser.$('//a[text()="Docs"]'); - - // Проверяем существование элемента в DOM - const isExisting = await link.isExisting(); - console.log("Элемент с текстом существует:", isExisting); + // тело теста }); it("Поиск элемента по атрибуту", async ({ browser }) => { - await browser.openAndWait("https://testplane.io/"); - - // Ищем элемент по атрибуту type - const button = await browser.$('//button[@type="button"]'); - - // Проверяем существование элемента в DOM - const isExisting = await button.isExisting(); - console.log("Элемент с атрибутом существует:", isExisting); + // тело теста }); it("Поиск кнопки с помощью метода getByRole", async ({ browser }) => { - await browser.url("https://testplane.io/"); - - const button = await browser.getByRole("button", { name: "Get started" }); - - await button.click(); + // тело теста }); }); ``` #### Как работает параллелизм в данном примере -Для Chrome открывается до 5 окон браузера одновременно. Каждое из них — это отдельная независимая сессия со своим `sessionId`: +Для Chrome и Firefox открывается до 5 и 2 окон браузера одновременно. Каждое из них — это отдельная независимая сессия со своим `sessionId`. -```bash -Тест 1 → сессия chrome:abc123 → открывается окно Chrome #1 -Тест 2 → сессия chrome:def456 → открывается окно Chrome #2 -Тест 3 → сессия chrome:ghi789 → открывается окно Chrome #3 -Тест 4 → сессия chrome:jkl012 → открывается окно Chrome #4 -Тест 5 → сессия chrome:mno345 → открывается окно Chrome #5 +При таких значениях параметров: + +```typescript +const config = { + browsers: { + chrome: { sessionsPerBrowser: 3, testsPerSession: 1 }, + firefox: { sessionsPerBrowser: 2, testsPerSession: 10 }, + }, +}; ``` -Для Firefox логика та же, но одновременно работают только 2 окна. Это ограничение задано через `sessionsPerBrowser`: +Вы получите следующий результат: -```bash -Тест 1 → сессия firefox:fb59f7 → открывается окно Firefox #1 -Тест 2 → сессия firefox:660ee0 → открывается окно Firefox #2 -Тест 3 → ждёт в очереди... - как только тест 1 завершился → сессия fb59f7 освободилась -Тест 3 → сессия firefox:fb59f7 → то же окно Firefox #1, новый тест +```json +CH-* — сессии chrome +FF-* — сессии firefox +[n/m] = занято n из m слотов + +Шаг 1 + chrome [3/3]: открываются окна CH-1, CH-2, CH-3 → запускают test1, test2, test3 + firefox [2/2]: открываются окна FF-1, FF-2 → запускают test1, test2 + +Шаг 2 + chrome [3/3]: CH-1 завершает test1 и закрывается; создается CH-4 → запускается test4 + firefox [2/2]: FF-1 завершает test1 и переиспользуется → запускается test3 + +Шаг 3 + chrome [2/3]: CH-2 завершает test2 и закрывается + firefox [2/2]: FF-2 завершает test2 и переиспользуется → запускается test4 + +Шаг 4 + chrome [0/3]: CH-3 и CH-4 завершают test3 и test4, затем закрываются + firefox [0/2]: FF-1 и FF-2 завершают test3 и test4, затем закрываются ``` :::warning Важно @@ -189,9 +164,9 @@ describe("test examples", () => { При наличии тысяч тестов время одного запуска может быть неприемлемо большим даже при максимальном параллелизме. В таких случаях используют шардирование — разбивку всего набора тестов на несколько независимых частей (чанков), которые запускаются параллельно на разных машинах или в разных `CI`-джобах. -### Плагин testplane-chunks +### Плагин @testplane/chunks -Плагин `@testplane/chunks` позволяет распараллелить запуск тестов на нескольких серверах, тем самым ускорив процесс. Однако сам плагин не занимается какой-либо оркестрацией, распараллеливанием запуска или слиянием получившихся отдельных отчетов в один итоговый отчет. +Плагин разбивает набор тестов проекта на детерминированные фрагменты, упрощая запуск нужной части. #### Установка и подключение @@ -218,13 +193,6 @@ module.exports = { }; ``` -#### Расшифровка параметров конфигурации - -| Параметр | Тип | По умолчанию | Описание | -| -------- | -------- | ------------ | ----------------------------------------------------------------- | -| `count` | `Number` | `1` | Количество порций (чанков), на которые нужно разбить набор тестов | -| `run` | `Number` | `1` | Номер чанка, тесты из которого нужно запустить | - ### Как разбить запуск тестов В качестве примера будет использован следующий набор тестов: @@ -259,7 +227,7 @@ describe("Регистрация", () => { describe("Оплата", () => { it("тест 1 - пустой номер карты показывает ошибку", async ({ browser }) => {}); it("тест 2 - невалидный номер карты", async ({ browser }) => {}); - it("тест 3 - истёкший срок действия карты", async ({ browser }) => {}); + it("тест 3 - истекший срок действия карты", async ({ browser }) => {}); // ... @@ -302,25 +270,6 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=1 npx testplane CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane ``` -### Как плагин делит тесты - -После сортировки по `fullTitle` набор тестов делится на 3 чанка: - -```css -┌──────────┬──────────┬──────────┐ -│ Чанк 0 │ Чанк 1 │ Чанк 2 │ -├──────────┼──────────┼──────────┤ -│ тест 1 │ тест 1 │ тест 1 │ -│ тест 2 │ тест 2 │ тест 2 │ -│ ... │ ... │ ... │ -│ тест 500 │ тест 500 │ тест 500 │ -└──────────┴──────────┴──────────┘ -``` - -:::tip Примечание -Главная идея чанков: если `workers` распределяет тесты внутри одного процесса, то чанки делят тесты между несколькими независимыми процессами — например, на разных `CI`-агентах или на одной машине через `concurrently`. -::: - ### Как объединить отчеты Чтобы объединить несколько отчетов в один, используйте команду `merge-reports`. Она принимает пути к директориям с отчетами, файлам баз данных или к файлам `databaseUrls.json`, после чего создает новый html-отчет в папке назначения с данными из всех переданных отчетов. @@ -328,12 +277,104 @@ CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane Пример использования: ```bash -npx html-reporter merge-reports report-dir/ path-to-database.db path-to-databaseUrls.json -d dest-report -h foo=bar +npx html-reporter merge-reports report-chunk-1/ report-chunk-2/ report-chunk-3/ -d merged-report ``` +### Пример GitHub Actions + +Ниже показан пример запуска `@testplane/chunks` в GitHub Actions. Тесты разбиваются на 3 чанка, каждый чанк выполняется в отдельном `matrix job`, а затем отчеты всех чанков скачиваются из `S3` и объединяются в один итоговый отчет. + +
+Полный пример + +```yaml +name: Testplane + +on: + pull_request: + +permissions: + id-token: write + contents: read + +jobs: + chunks: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + chunk: [1, 2, 3] + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - run: npm ci + + - run: npx testplane --chunks-count 3 --chunks-run ${{ matrix.chunk }} + + - uses: aws-actions/configure-aws-credentials@v5 + with: + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + aws-region: eu-central-1 + + - uses: jakejarvis/s3-sync-action@v0.5.1 + with: + args: --follow-symlinks + env: + AWS_S3_BUCKET: ${{ secrets.S3_BUCKET }} + AWS_REGION: eu-central-1 + SOURCE_DIR: testplane-report + DEST_DIR: testplane/${{ github.run_id }}/chunk-${{ matrix.chunk }} + + merge-report: + runs-on: ubuntu-latest + needs: chunks + if: ${{ always() }} + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - run: npm ci + + - uses: aws-actions/configure-aws-credentials@v5 + with: + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + aws-region: eu-central-1 + + - run: | + mkdir -p reports/chunk-1 reports/chunk-2 reports/chunk-3 + aws s3 cp s3://${{ secrets.S3_BUCKET }}/testplane/${{ github.run_id }}/chunk-1/ reports/chunk-1 --recursive + aws s3 cp s3://${{ secrets.S3_BUCKET }}/testplane/${{ github.run_id }}/chunk-2/ reports/chunk-2 --recursive + aws s3 cp s3://${{ secrets.S3_BUCKET }}/testplane/${{ github.run_id }}/chunk-3/ reports/chunk-3 --recursive + + - run: | + npx testplane merge-reports \ + reports/chunk-1 \ + reports/chunk-2 \ + reports/chunk-3 \ + --output merged-report + + - uses: jakejarvis/s3-sync-action@v0.5.1 + with: + args: --follow-symlinks + env: + AWS_S3_BUCKET: ${{ secrets.S3_BUCKET }} + AWS_REGION: eu-central-1 + SOURCE_DIR: merged-report + DEST_DIR: testplane/${{ github.run_id }}/merged +``` + +
+ ## Рекомендуемые настройки и их расчет -#### Воркеры +#### Workers Рекомендуемое значение — 8. Любое другое не должно превышать количество ядер CPU. From c724ccca3dd939d6cf3d40ccdae469697758fa0b Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Sun, 3 May 2026 19:41:14 +0300 Subject: [PATCH 16/19] docs: settings-fix --- .../current/basic-guides/parallelism.mdx | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index 95ffc6f..d7f8e66 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -257,17 +257,22 @@ describe("Авторизация", () => { Чанк 2 → тесты 1, 2, ..., 500 (≈ третья треть) ``` -Запуск каждого чанка отдельно через терминал: +Запуск каждого чанка отдельно через терминал с помощью переменных окружения или аргументов командной строки: ```bash -# Терминал 1 — Чанк 0 -CHUNKS_COUNT=3 CHUNKS_CURRENT=0 npx testplane +testplane_chunks_count=3 testplane_chunks_run=0 npx testplane -# Терминал 2 — Чанк 1 -CHUNKS_COUNT=3 CHUNKS_CURRENT=1 npx testplane +testplane_chunks_count=3 testplane_chunks_run=1 npx testplane -# Терминал 2 — Чанк 2 -CHUNKS_COUNT=3 CHUNKS_CURRENT=2 npx testplane +testplane_chunks_count=3 testplane_chunks_run=2 npx testplane +``` + +```bash +npx testplane --chunks-count 3 --chunks-run 0 + +npx testplane --chunks-count 3 --chunks-run 1 + +npx testplane --chunks-count 3 --chunks-run 2 ``` ### Как объединить отчеты @@ -380,7 +385,7 @@ jobs: #### sessionsPerBrowser -При локальном запуске значение не превышает 5. В ином случает примерное значение можно вычислить путем деления доступных ресурсов на требуемое для конкретного браузера. При расчете помните о затратах на запуск самих тестов. +При использовании локальных браузеров отталкивайтесь от мощностей своего оборудования. Для отладки/запуска единичных тестов это значение обычно находится в диапазоне 1—5. При использовании локальных браузеров в CI/докер образах, отталкивайтесь от примерной оценки — одна сессия `linux desktop` браузера потребляет 1.2 ядра CPU. Если вы используете удаленный грид, обычно сам провайдер сообщает количество доступных слотов — например, 400. Далее рассчитайте количество одновременно запущенных прогонов задач в CI, например, до 10. Тогда в конфиге для CI можно указать суммарный `sessionsPerBrowser`=40. #### Количество чанков From 49b0ec598965d63d97af2c12ae5b755b215744dd Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Mon, 4 May 2026 10:27:35 +0300 Subject: [PATCH 17/19] docs:settings-fix --- .../current/basic-guides/parallelism.mdx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index d7f8e66..510b5e6 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -385,7 +385,18 @@ jobs: #### sessionsPerBrowser -При использовании локальных браузеров отталкивайтесь от мощностей своего оборудования. Для отладки/запуска единичных тестов это значение обычно находится в диапазоне 1—5. При использовании локальных браузеров в CI/докер образах, отталкивайтесь от примерной оценки — одна сессия `linux desktop` браузера потребляет 1.2 ядра CPU. Если вы используете удаленный грид, обычно сам провайдер сообщает количество доступных слотов — например, 400. Далее рассчитайте количество одновременно запущенных прогонов задач в CI, например, до 10. Тогда в конфиге для CI можно указать суммарный `sessionsPerBrowser`=40. +При использовании локальных браузеров отталкивайтесь от мощностей своего оборудования. Для отладки/запуска единичных тестов это значение обычно находится в диапазоне 1-5. При использовании локальных браузеров в CI/Docker-образах отталкивайтесь от примерной оценки: одна сессия `LinuxDesktop`-браузера потребляет 1.2 ядра CPU. Если вы используете удаленный грид, обычно сам провайдер сообщает количество доступных слотов — например, 400. Далее рассчитайте количество одновременно запущенных прогонов задач в CI, например, до 10. Тогда в конфиге для CI можно указать суммарное значение `sessionsPerBrowser`: + +```typescript +// .testplane.config.ts +export default { + browsers: { + chrome: { + sessionsPerBrowser: 40, + }, + }, +}; +``` #### Количество чанков From e45db6dcd4342d1897e70b4575a7ff02d83f9f97 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Mon, 4 May 2026 12:24:18 +0300 Subject: [PATCH 18/19] docs: eng-version --- docs/basic-guides/parallelism.mdx | 406 ++++++++++++++++++ .../current/basic-guides/parallelism.mdx | 2 +- 2 files changed, 407 insertions(+), 1 deletion(-) diff --git a/docs/basic-guides/parallelism.mdx b/docs/basic-guides/parallelism.mdx index 5c3fb84..bcfb3ad 100644 --- a/docs/basic-guides/parallelism.mdx +++ b/docs/basic-guides/parallelism.mdx @@ -1 +1,407 @@ # Parallelism + +## Parallelism in Testplane + +Testplane runs tests in parallel by launching multiple browsers simultaneously, which are managed by one or several workers. Parallel test execution significantly reduces the overall test run time. + +### sessionsPerBrowser + +In the configuration file, browser types are declared in the `browsers` field. For each browser type, you can independently configure how many instances can run simultaneously: + +```typescript +// .testplane.config.ts +export default { + browsers: { + chrome: { + sessionsPerBrowser: 5, // up to 5 parallel Chrome sessions + }, + firefox: { + sessionsPerBrowser: 2, // up to 2 parallel Firefox sessions + }, + }, +}; +``` + +The `sessionsPerBrowser` parameter is key for managing parallelism. It determines how many browsers of the same type Testplane will launch simultaneously. The default value is `1`. + +### Workers + +The workers parameter determines how many child worker processes will be launched. Architecturally, it works as follows: + +- Master process — coordinates the launch, forms test queues and assigns tasks to workers; +- Worker processes — execute the tests directly. + +Each worker is a separate thread, but within a single worker, tests run concurrently: when a test is waiting for a response from the browser (`await`), the worker doesn’t stay idle — it switches to the next test. Therefore, even a single worker can handle multiple parallel browser sessions. + +:::warning Warning +workers and sessionsPerBrowser are independent limits. Increasing the number of workers won’t boost actual concurrency if sessionsPerBrowser remains unchanged. +::: + +### testsPerSession + +The `testsPerSession` parameter determines how many tests can be run sequentially in a single browser session. It limits session reuse to prevent test failures caused by browser degradation, and it’s not related to parallel test execution. + +### How it works + +In this example, the `sessionsPerBrowser` parameter is set to 5: + +```typescript +const config = { + chrome: { + headless: true, + desiredCapabilities: { + browserName: "chrome", + }, + sessionsPerBrowser: 5, // 5 parallel Chrome sessions + waitTimeout: 10000, + }, +}; +``` + +and to 2: + +```typescript +const config = { + firefox: { + headless: true, + desiredCapabilities: { + browserName: "firefox", + }, + sessionsPerBrowser: 2, // 2 parallel Firefox sessions + waitTimeout: 10000, + }, +}; +``` + +The value of the `workers`: + +```typescript +const config = { + system: { + workers: 1, + }, +}; +``` + +Next, the tests: + +```typescript +describe("test examples", () => { + it("Find an element by data‑testid", async ({ browser }) => { + // test body + }); + + it("Find an element on the main page", async ({ browser }) => { + // test body + }); + + it("Find an element by ID on the main page", async ({ browser }) => { + // test body + }); + + it("Find an element by attribute type", async ({ browser }) => { + // test body + }); + + it("Find an element by text", async ({ browser }) => { + // test body + }); + + it("Find an element by attribute", async ({ browser }) => { + // test body + }); + + it("Find a button using the getByRole method", async ({ browser }) => { + // test body + }); +}); +``` + +#### How parallelism works in this example + +For Chrome and Firefox, up to 5 and 2 browser windows are opened simultaneously, respectively. Each of them is a separate independent session with its own `sessionId`. + +With the following parameter values: + +```typescript +const config = { + browsers: { + chrome: { sessionsPerBrowser: 3, testsPerSession: 1 }, + firefox: { sessionsPerBrowser: 2, testsPerSession: 10 }, + }, +}; +``` + +You’ll get the following result: + +```json +CH-* — Chrome sessions +FF-* — Firefox sessions +[n/m] = n out of m slots are occupied + +Step 1 + chrome [3/3]: windows CH‑1, CH‑2, CH‑3 are opened → run test1, test2, test3 + firefox [2/2]: windows FF‑1, FF‑2 are opened → run test1, test2 + +Step 2 + chrome [3/3]: CH‑1 completes test1 and closes; CH‑4 is created → test4 is launched + firefox [2/2]: FF‑1 completes test1 and is reused → test3 is launched + +Step 3 + chrome [2/3]: CH‑2 completes test2 and closes + firefox [2/2]: FF‑2 completes test2 and is reused → test4 is launched + +Step 4 + chrome [0/3]: CH‑3 and CH‑4 complete test3 and test4, then close + firefox [0/2]: FF‑1 and FF‑2 complete test3 and test4, then close +``` + +:::warning Warning +workers controls the number of Node.js processes, while sessionsPerBrowser controls the number of concurrent browser sessions within each worker. With workers: 1, all 7 sessions are managed by a single process. +::: + +## Sharding + +When you have thousands of tests, a single run can take an unacceptably long time — even with maximum concurrency. In such cases, sharding is used: the entire test suite is split into several independent parts (chunks) that are run in parallel on different machines or in separate `CI`-jobs. + +### @testplane/chunks plugin + +The plugin splits the project’s test suite into deterministic fragments, making it easier to run a specific part. + +#### Installation and setup + +To install, run the following command: + +```bash +npm install -D @testplane/chunks +``` + +And specify the parameters in the `testplane.config.ts` file: + +```typescript +module.exports = { + plugins: { + "@testplane/chunks": { + count: 7, // Split tests into 7 chunks + run: 1, // Run the first chunk + }, + + // other Testplane plugins... + }, + + // other Testplane settings... +}; +``` + +As an example, the following test suite will be used: + +```text +project/ +├── .testplane.conf.js +├── package.json +└── tests/ + ├── registration.testplane.js # 500 tests + ├── payment.testplane.js # 500 tests + └── auth.testplane.js # 500 tests +``` + +```javascript +// registration.testplane.js + +describe("Registration", () => { + it("test 1 - empty email shows an error", async ({ browser }) => {}); + it("test 2 - invalid email format", async ({ browser }) => {}); + it("test 3 - empty password shows an error", async ({ browser }) => {}); + + // ... + + // test 500 +}); +``` + +```javascript +// payment.testplane.js + +describe("Payment", () => { + it("test 1 - empty card number shows an error", async ({ browser }) => {}); + it("test 2 - invalid card number", async ({ browser }) => {}); + it("test 3 - expired card", async ({ browser }) => {}); + + // ... + + // test 500 +}); +``` + +```javascript +// auth.testplane.js + +describe("Authorization", () => { + it("test 1 - empty email shows an error", async ({ browser }) => {}); + it("test 2 - empty password shows an error", async ({ browser }) => {}); + it("test 3 - incorrect password shows an error", async ({ browser }) => {}); + + // ... + + // test 500 +}); +``` + +Splitting tests into chunks: + +```css +Chunk 0 → tests 1, 2, ..., 500 (≈ first part) +Chunk 1 → tests 1, 2, ..., 500 (≈ second part) +Chunk 2 → tests 1, 2, ..., 500 (≈ third part) +``` + +Running each chunk separately via the terminal using environment variables or command‑line arguments: + +```bash +testplane_chunks_count=3 testplane_chunks_run=0 npx testplane + +testplane_chunks_count=3 testplane_chunks_run=1 npx testplane + +testplane_chunks_count=3 testplane_chunks_run=2 npx testplane +``` + +```bash +npx testplane --chunks-count 3 --chunks-run 0 + +npx testplane --chunks-count 3 --chunks-run 1 + +npx testplane --chunks-count 3 --chunks-run 2 +``` + +### How to merge reports + +To combine several reports into one, use the `merge-reports` command. It accepts paths to report directories, database files, or `databaseUrls.json` files, and then creates a new html-report in the destination folder with data from all the provided reports. + +Example of usage: + +```bash +npx html-reporter merge-reports report-chunk-1/ report-chunk-2/ report-chunk-3/ -d merged-report +``` + +### GitHub Actions example + +Below is an example of running `@testplane/chunks` in GitHub Actions. The tests are split into 3 chunks — each chunk is executed in a separate `matrix job`. Then, the reports from all chunks are downloaded from `S3` and merged into a single final report. + +
+Code + +```yaml +name: Testplane + +on: + pull_request: + +permissions: + id-token: write + contents: read + +jobs: + chunks: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + chunk: [1, 2, 3] + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - run: npm ci + + - run: npx testplane --chunks-count 3 --chunks-run ${{ matrix.chunk }} + + - uses: aws-actions/configure-aws-credentials@v5 + with: + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + aws-region: eu-central-1 + + - uses: jakejarvis/s3-sync-action@v0.5.1 + with: + args: --follow-symlinks + env: + AWS_S3_BUCKET: ${{ secrets.S3_BUCKET }} + AWS_REGION: eu-central-1 + SOURCE_DIR: testplane-report + DEST_DIR: testplane/${{ github.run_id }}/chunk-${{ matrix.chunk }} + + merge-report: + runs-on: ubuntu-latest + needs: chunks + if: ${{ always() }} + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - run: npm ci + + - uses: aws-actions/configure-aws-credentials@v5 + with: + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + aws-region: eu-central-1 + + - run: | + mkdir -p reports/chunk-1 reports/chunk-2 reports/chunk-3 + aws s3 cp s3://${{ secrets.S3_BUCKET }}/testplane/${{ github.run_id }}/chunk-1/ reports/chunk-1 --recursive + aws s3 cp s3://${{ secrets.S3_BUCKET }}/testplane/${{ github.run_id }}/chunk-2/ reports/chunk-2 --recursive + aws s3 cp s3://${{ secrets.S3_BUCKET }}/testplane/${{ github.run_id }}/chunk-3/ reports/chunk-3 --recursive + + - run: | + npx testplane merge-reports \ + reports/chunk-1 \ + reports/chunk-2 \ + reports/chunk-3 \ + --output merged-report + + - uses: jakejarvis/s3-sync-action@v0.5.1 + with: + args: --follow-symlinks + env: + AWS_S3_BUCKET: ${{ secrets.S3_BUCKET }} + AWS_REGION: eu-central-1 + SOURCE_DIR: merged-report + DEST_DIR: testplane/${{ github.run_id }}/merged +``` + +
+ +## Recommended settings and their calculation + +### Workers + +The recommended value is 8. Any other value should not exceed the number of CPU cores. + +### sessionsPerBrowser + +Base the value on your hardware capabilities — for debugging or running individual tests, this value typically falls within the 1–5 range. When using local browsers in CI/Docker images, rely on a rough estimate: one `LinuxDesktop`-browser session consumes 1.2 CPU cores. If you’re using a remote grid, the provider usually specifies the number of available slots — for example, 400. Next, calculate the number of concurrent task runs in CI — say, up to 10. In this case, you can set the total `sessionsPerBrowser` value in the CI config: + +```typescript +// .testplane.config.ts +export default { + browsers: { + chrome: { + sessionsPerBrowser: 40, + }, + }, +}; +``` + +### Number of chunks + +When calculating the number of chunks, you should take the following factors into account: + +- the number of available browsers; +- the overhead for creating a chunk; +- the desired total run time. + +Recommendation: aim for at least 500 tests per chunk. diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx index 510b5e6..2febcdf 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/basic-guides/parallelism.mdx @@ -385,7 +385,7 @@ jobs: #### sessionsPerBrowser -При использовании локальных браузеров отталкивайтесь от мощностей своего оборудования. Для отладки/запуска единичных тестов это значение обычно находится в диапазоне 1-5. При использовании локальных браузеров в CI/Docker-образах отталкивайтесь от примерной оценки: одна сессия `LinuxDesktop`-браузера потребляет 1.2 ядра CPU. Если вы используете удаленный грид, обычно сам провайдер сообщает количество доступных слотов — например, 400. Далее рассчитайте количество одновременно запущенных прогонов задач в CI, например, до 10. Тогда в конфиге для CI можно указать суммарное значение `sessionsPerBrowser`: +Отталкивайтесь от мощностей своего оборудования, для отладки/запуска единичных тестов это значение обычно находится в диапазоне 1-5. При использовании локальных браузеров в CI/Docker-образах отталкивайтесь от примерной оценки: одна сессия `LinuxDesktop`-браузера потребляет 1.2 ядра CPU. Если вы используете удаленный грид, обычно сам провайдер сообщает количество доступных слотов — например, 400. Далее рассчитайте количество одновременно запущенных прогонов задач в CI, например, до 10. Тогда в конфиге для CI можно указать суммарное значение `sessionsPerBrowser`: ```typescript // .testplane.config.ts From 2ff558aad570559db4085386d907e7f0b8096748 Mon Sep 17 00:00:00 2001 From: Nikolaengel Date: Tue, 5 May 2026 11:21:12 +0300 Subject: [PATCH 19/19] docs: workers-fix --- docs/basic-guides/parallelism.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/basic-guides/parallelism.mdx b/docs/basic-guides/parallelism.mdx index bcfb3ad..d6c6bc2 100644 --- a/docs/basic-guides/parallelism.mdx +++ b/docs/basic-guides/parallelism.mdx @@ -34,7 +34,7 @@ The workers parameter determines how many child worker processes will be launche Each worker is a separate thread, but within a single worker, tests run concurrently: when a test is waiting for a response from the browser (`await`), the worker doesn’t stay idle — it switches to the next test. Therefore, even a single worker can handle multiple parallel browser sessions. :::warning Warning -workers and sessionsPerBrowser are independent limits. Increasing the number of workers won’t boost actual concurrency if sessionsPerBrowser remains unchanged. +`workers` and `sessionsPerBrowser` are independent limits. Increasing the number of workers won’t boost actual concurrency if `sessionsPerBrowser` remains unchanged. ::: ### testsPerSession @@ -157,7 +157,7 @@ Step 4 ``` :::warning Warning -workers controls the number of Node.js processes, while sessionsPerBrowser controls the number of concurrent browser sessions within each worker. With workers: 1, all 7 sessions are managed by a single process. +`workers` controls the number of `Node.js` processes, while `sessionsPerBrowser` controls the number of concurrent browser sessions within each worker. With `workers: 1`, all 7 sessions are managed by a single process. ::: ## Sharding