Debugging зависших тестов

Зависание тестов — одна из самых частых проблем при автоматизированном тестировании веб-приложений. В Playwright это проявляется, когда сценарий останавливается на определённом шаге, браузер виснет или ожидание элементов не завершается. Основная цель отладки — выявить причину зависания и определить, происходит ли оно из-за приложения, среды тестирования или самого скрипта.


Использование таймаутов

Каждое действие в Playwright может быть ограничено временем ожидания. По умолчанию глобальный таймаут для page.goto, locator.click и других методов составляет 30 секунд. Если тест зависает дольше этого времени, необходимо явно указывать таймауты:

await page.goto('https://example.com', { timeout: 10000 });
await page.locator('#submit').click({ timeout: 5000 });

Ключевой момент: задавать таймауты, исходя из реального времени загрузки приложения. Слишком короткий таймаут приведёт к ложным падениям теста, слишком длинный — к долгому зависанию.


Логи и трассировка действий

Playwright предоставляет встроенные возможности для логирования действий и записи трассировки:

await page.context().tracing.start({ screenshots: true, snapshots: true });
await page.goto('https://example.com');
await page.locator('#button').click();
await page.context().tracing.stop({ path: 'trace.zip' });

Трассировка позволяет пошагово воспроизвести сценарий и увидеть, на каком этапе происходит зависание. Скриншоты и снимки состояния DOM дают информацию о том, загружается ли элемент или страница полностью.

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


Отладка с помощью debug() и pause()

Playwright предоставляет методы для интерактивной отладки:

await page.pause();

pause() останавливает выполнение теста и открывает DevTools, где можно:

  • Проверить состояние DOM.
  • Выполнить команды в консоли браузера.
  • Проверить наличие элементов или ошибки JavaScript на странице.

Метод debug() позволяет выводить детальные логи о выполняемых действиях в терминале:

require('playwright').devices;
debug('Проверка локатора:', await page.locator('#input').count());

Ключевой момент: интерактивная отладка эффективна для сложных сценариев, где зависание не воспроизводится постоянно.


Работа с ожиданиями и waitFor*

Зависания часто происходят из-за некорректных ожиданий. Playwright поддерживает различные методы ожидания:

await page.waitForSelector('#element', { timeout: 5000 });
await page.waitForResponse(response => response.url().includes('api/data') && response.status() === 200);
await page.waitForLoadState('networkidle');
  • waitForSelector — ждет появления элемента на странице.
  • waitForResponse — позволяет дождаться ответа от сервера.
  • waitForLoadState — ожидает полной загрузки страницы или завершения сетевых запросов.

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


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

Длинные и комплексные тесты чаще зависают. Оптимальная стратегия — разбивать сценарий на отдельные шаги и проверять каждый из них отдельно:

test('логин', async ({ page }) => {
    await page.goto('/login');
    await page.fill('#username', 'user');
    await page.fill('#password', 'pass');
    await page.click('#submit');
});

test('проверка профиля', async ({ page }) => {
    await page.goto('/profile');
    await expect(page.locator('#welcome')).toHaveText('Добро пожаловать');
});

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


Работа с браузерной средой

Иногда зависания связаны не с кодом теста, а с состоянием браузера:

  • Использование headless режима может скрывать проблемы с рендерингом.
  • Очистка контекста перед каждым тестом снижает вероятность «утечки» состояния:
const context = await browser.newContext();
const page = await context.newPage();
  • Логи браузера помогают выявить ошибки Jav * aScript:
page.on('console', msg => console.log('Browser log:', msg.text()));
page.on('pageerror', err => console.log('Page error:', err));

Анализ зависаний через CI/CD

Если тесты зависают только в CI/CD, причины могут быть связаны с ресурсами:

  • Недостаточная память или CPU.
  • Ограничения времени выполнения.
  • Сетевые задержки при обращении к внешним сервисам.

В таких случаях полезно:

  • Увеличить таймауты для CI.
  • Использовать фиктивные или локальные серверы для внешних API.
  • Включать трассировку только для проблемных тестов.

Полезные практики

  • Всегда фиксировать версии браузера и Playwright, чтобы избежать несовместимостей.
  • Логировать действия, особенно сетевые запросы и ответы.
  • Использовать селекторы, максимально устойчивые к изменениям DOM.
  • Сравнивать результаты локально и на CI, чтобы понять влияние окружения.

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