Переиспользование страниц

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

Создание и управление страницами

Стандартное создание страницы выглядит так:

const browser = await puppeteer.launch(); const page = await
browser.newPage(); await page.goto(&

При каждом вызове browser.newPage() создается новая вкладка, что увеличивает потребление памяти и время запуска. В больших тестовых наборах часто возникает необходимость переиспользовать страницы, чтобы минимизировать накладные расходы.

Преимущества переиспользования страниц

  1. Снижение времени запуска тестов. Создание новой страницы требует инициализации контекста, загрузки ресурсов и скриптов. Переиспользование существующей страницы позволяет сразу работать с контентом.
  2. Снижение потребления памяти. Каждая новая вкладка занимает отдельный объект памяти, включая ресурсы браузера.
  3. Сохранение состояния. Переиспользуемая страница может хранить состояние сессии, cookies и localStorage, что удобно для последовательных сценариев тестирования.

Реализация переиспользования страниц

На практике переиспользование можно реализовать несколькими способами:

  1. Глобальная страница для тестового набора
let page;

beforeAll(async () => {
    browser = await puppeteer.launch();
    page = await browser.newPage();
});

afterAll(async () => {
    await browser.close();
});

test('Проверка заголовка', async () => {
    await page.goto('https://example.com');
    const title = await page.title();
    expect(title).toBe('Example Domain');
});

test('Проверка ссылки', async () => {
    await page.goto('https://example.com');
    const link = await page.$('a');
    const href = await page.evaluate(el => el.href, link);
    expect(href).toBe('https://www.iana.org/domains/example');
});

В этом примере одна страница используется для всех тестов, что позволяет избежать повторного создания вкладок.

  1. Пул страниц для параллельных тестов

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

const pages = [];
const MAX_PAGES = 3;

beforeAll(async () => {
    browser = await puppeteer.launch();
    for (let i = 0; i < MAX_PAGES; i++) {
        pages.push(await browser.newPage());
    }
});

afterAll(async () => {
    await browser.close();
});

async function getAvailablePage() {
    return pages.shift(); // взять страницу из пула
}

async function releasePage(page) {
    pages.push(page); // вернуть страницу в пул
}

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

Очистка состояния страницы

При повторном использовании важно сбрасывать состояние страницы, чтобы тесты не влияли друг на друга:

await page.evaluate(() => {
    localStorage.clear();
    sessionStorage.clear();
});
const client = await page.target().createCDPSession();
await client.send('Network.clearBrowserCookies');

Это гарантирует, что cookies и данные сессии не сохранятся между тестами, что важно для изоляции сценариев.

Навигация и переиспользование

Страницу можно переиспользовать для перехода между различными URL без закрытия вкладки:

await page.goto('https://example.com');
await page.waitForSelector('h1');
await page.goto('https://example.com/about');
await page.waitForSelector('h2');

Метод page.goto() автоматически очищает предыдущий контент и выполняет загрузку нового, что позволяет использовать один объект страницы для последовательных тестов.

Подводные камни

  1. Неожиданное сохранение состояния. Если не очищать cookies, localStorage или sessionStorage, тесты могут давать ложные результаты.
  2. Ошибки навигации. Переиспользуемая страница может оставаться в «зависшем» состоянии после ошибки в предыдущем тесте. Рекомендуется предусматривать механизм восстановления.
  3. Проблемы с асинхронностью. При параллельной работе с одной страницей необходимо синхронизировать доступ, иначе промисы могут конфликтовать.

Советы по оптимизации

  • Использовать одну страницу на тестовый поток при последовательных тестах.
  • Для параллельных сценариев — пул страниц фиксированного размера, чтобы избежать перегрузки браузера.
  • Перед переиспользованием страницы очищать состояние, чтобы тесты оставались независимыми.
  • Отслеживать ошибки навигации через page.on(‘error’, handler) и page.on(‘pageerror’, handler).

Переиспользование страниц в Puppeteer позволяет значительно повысить эффективность тестирования, снизить нагрузку на ресурсы и ускорить выполнение сценариев, при этом сохраняя контроль над состоянием и стабильностью тестов.