Timeout и обработка их превышения

Таймауты — фундаментальный механизм в автоматизированном тестировании с WebdriverIO. Они позволяют задать максимальное время ожидания различных событий: появления элементов, завершения асинхронных действий или ответа сервера. Правильная настройка таймаутов обеспечивает стабильность тестов и предотвращает ложные падения из-за временных задержек.

Виды таймаутов в WebdriverIO

1. waitforTimeout (устаревший, в новых версиях WebdriverIO рекомендуется timeouts) Задает глобальное время ожидания для команд waitFor*. Если элемент не появился или не достиг ожидаемого состояния за это время, возникает ошибка TimeoutError.

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

browser.setTimeout({
    implicit: 5000,  // для поиска элементов
    pageLoad: 10000, // для загрузки страницы
    script: 3000     // для выполнения скриптов
});
  • implicit — устанавливает максимальное время ожидания при поиске элемента через $ или $$. Если элемент не найден, WebdriverIO будет повторять попытки до истечения времени.
  • pageLoad — время ожидания полной загрузки страницы при вызове browser.url().
  • script — время ожидания выполнения асинхронных скриптов через browser.executeAsync().

Локальные таймауты для отдельных команд

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

const button = await $('#submit');
await button.waitForDisplayed({ timeout: 7000 });
await button.click();

Параметр timeout здесь указывает максимально допустимое время ожидания видимости элемента. Если элемент не появляется, возникает ошибка Error: element ("#submit") still not displayed after 7000ms.

Использование waitUntil для кастомных условий

Метод waitUntil позволяет ожидать выполнение произвольного условия:

await browser.waitUntil(
    async () => (await $('#status').getText()) === 'Готово',
    {
        timeout: 10000,
        timeoutMsg: 'Статус не изменился на "Готово" за 10 секунд'
    }
);
  • timeout — максимальное время ожидания.
  • timeoutMsg — сообщение об ошибке при превышении времени.
  • Условие проверяется с частотой по умолчанию каждые 500 мс, её можно изменить с помощью interval.

Обработка превышения таймаута

При превышении таймаута WebdriverIO выбрасывает исключение, которое можно перехватывать через try/catch:

try {
    await $('#element').waitForClickable({ timeout: 5000 });
    await $('#element').click();
} catch (error) {
    console.error('Элемент не стал кликабельным вовремя:', error.message);
    // Дополнительная логика: скриншот, логирование, альтернативные действия
}

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

Важные моменты при настройке таймаутов

  • Не использовать слишком короткие значения, иначе тесты будут падать при минимальной задержке сети или загрузки.
  • Не ставить слишком длинные таймауты без необходимости, чтобы тесты не тормозили при явных ошибках.
  • Для динамически изменяющихся элементов предпочтительнее локальные waitFor* или waitUntil, а не глобальные таймауты.
  • Логи и скриншоты при превышении таймаута помогают анализировать причины падений тестов и улучшать стабильность.

Таймауты в асинхронных сценариях

Асинхронные действия требуют отдельного контроля времени. В WebdriverIO можно использовать таймауты для ожидания завершения AJAX-запросов, загрузки данных и появления элементов:

await browser.waitUntil(async () => {
    const isLoaded = await browser.execute(() => window.dataLoaded);
    return isLoaded === true;
}, { timeout: 15000, timeoutMsg: 'Данные не загрузились за 15 секунд' });

Использование таймаутов вместе с waitUntil позволяет избежать жесткой привязки к конкретным событиям страницы и работать с динамическим контентом.

Таймауты и производительность

Чрезмерное использование больших таймаутов увеличивает общее время тестового прогона. Рекомендуется:

  • Настраивать таймауты индивидуально для критических элементов.
  • Использовать waitFor* с разумными значениями, оптимизированными под скорость приложения.
  • Комбинировать глобальные и локальные таймауты для баланса стабильности и скорости тестов.

Заключение по практике таймаутов

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