Puppeteer предоставляет возможность управлять экземплярами браузеров Chrome или Chromium через API высокого уровня. В больших проектах автоматизированного тестирования одной инстанции браузера часто недостаточно: для ускорения выполнения тестов, параллельного запуска и распределения нагрузки применяется концепция пулов браузеров.
Пул браузеров — это структура, управляющая несколькими экземплярами браузеров, которые могут одновременно обслуживать множество тестовых сценариев. Основная задача пула — экономия ресурсов, снижение накладных расходов на создание новых инстанций и повышение стабильности тестов.
Ключевые моменты:
Типичный пул состоит из трёх уровней:
Браузерный уровень Каждый элемент пула — это
полноценный экземпляр Chromium или Chrome, запущенный через
puppeteer.launch().
Уровень страниц (Page) Для каждого теста обычно
создаётся отдельная страница browser.newPage(). Иногда
используются несколько страниц на одном браузере, но это требует
аккуратного управления ресурсами.
Очередь задач Пул реализует очередь тестов, которые ожидают свободного браузера или страницы. Очередь гарантирует, что все задания будут выполнены без конфликта ресурсов.
const puppeteer = require(&
class BrowserPool {
constructor(size = 2) {
this.size = size;
this.pool = [];
this.queue = [];
}
async init() {
for (let i = 0; i < this.size; i++) {
const browser = await puppeteer.launch({ headless: true });
this.pool.push({ browser, busy: false });
}
}
async acquire() {
const freeBrowser = this.pool.find(b => !b.busy);
if (freeBrowser) {
freeBrowser.busy = true;
return freeBrowser.browser;
}
return new Promise(resolve => {
this.queue.push(resolve);
});
}
release(browser) {
const browserObj = this.pool.find(b => b.browser === browser);
if (browserObj) {
browserObj.busy = false;
if (this.queue.length > 0) {
const next = this.queue.shift();
browserObj.busy = true;
next(browserObj.browser);
}
}
}
async closeAll() {
for (const b of this.pool) {
await b.browser.close();
}
this.pool = [];
}
}
// Использование
(async () => {
const pool = new BrowserPool(3);
await pool.init();
const browser = await pool.acquire();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'example.png' });
await page.close();
pool.release(browser);
await pool.closeAll();
})();
page.goto(‘about:blank’), page.deleteCookie()
и очистка localStorage).
Пулы браузеров эффективно интегрируются с Jest, Mocha или другими
фреймворками через хуки beforeAll, afterAll,
beforeEach, afterEach. Такой подход позволяет
запускать тесты параллельно, сокращая общее время выполнения.
Пример для Jest:
let pool;
let browser;
beforeAll(async () => {
pool = new BrowserPool(2);
await pool.init();
});
beforeEach(async () => {
browser = await pool.acquire();
});
afterEach(async () => {
pool.release(browser);
});
afterAll(async () => {
await pool.closeAll();
});
test('Example test', async () => {
const page = await browser.newPage();
await page.goto('https://example.com');
const title = await page.title();
expect(title).toBe('Example Domain');
await page.close();
});
Использование пулов браузеров значительно повышает масштабируемость тестирования, сокращает время запуска и уменьшает нагрузку на систему, сохраняя при этом изоляцию и предсказуемость результатов.