Ретраи и их настройка

Одной из важнейших составляющих при автоматизации тестирования является стабильность тестов. Иногда тесты могут падать не из-за ошибок в приложении, а из-за нестабильности внешних факторов, таких как загрузка страницы, асинхронные операции или сетевые проблемы. В таких случаях использование механизма повторных попыток (retry) помогает повысить стабильность тестов, автоматически повторяя их в случае неудачи.

Что такое ретраи в Playwright?

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

Playwright поддерживает несколько уровней ретраев:

  1. Ретраи на уровне всего теста — повторный запуск всего теста в случае его неудачи.
  2. Ретраи на уровне отдельных шагов — возможность повторить только определённые операции или шаги внутри теста.

Настройка ретраев на уровне теста

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

Пример конфигурации:

// config.js
module.exports = {
  retries: 3, // Максимальное количество попыток для всего набора тестов
};

В данном случае, если тест не пройден с первой попытки, Playwright автоматически попытается выполнить его ещё два раза.

Ретраи на уровне тестов и хука beforeEach

Если необходимо задать ретраи только для определённого набора тестов или отдельных тестов, это можно сделать внутри тестового файла, указав значение параметра retries на уровне теста:

// test.spec.js
import { test } from '@playwright/test';

test('Тест с ретраями', { retries: 2 }, async ({ page }) => {
  await page.goto('https://example.com');
  await page.click('button');
  // Ассерты для проверки
});

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

Ретраи с учётом ошибок

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

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

test('Тест с выборочным повтором', async ({ page }) => {
  try {
    await page.goto('https://example.com');
    await page.click('button');
  } catch (error) {
    if (error.message.includes('NetworkError')) {
      test.retry(); // Попробовать снова в случае сетевой ошибки
    }
    throw error; // Прокинуть ошибку, если это не сетевая ошибка
  }
});

Повторные попытки с интервалом

В некоторых случаях может быть полезно настроить интервал между попытками, чтобы дать время на восстановление страницы или сервера. Playwright позволяет задать задержку между повторными попытками с помощью хука beforeEach или при настройке повторов на уровне конфигурации.

// config.js
module.exports = {
  retries: 3,
  timeout: 30000, // Таймаут на выполнение теста
  workerTimeout: 60000, // Таймаут на выполнение каждого worker
};

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

Логирование при повторе

Для того, чтобы отслеживать, какие тесты были повторены, можно включить логирование. Playwright автоматически выводит сообщение в консоль при каждом запуске теста, но можно настроить более подробное логирование, чтобы отслеживать количество попыток и причины, по которым тест не прошёл.

test('Тест с логированием ретраев', async ({ page }) => {
  let attempt = 0;
  try {
    attempt++;
    await page.goto('https://example.com');
    await page.click('button');
  } catch (error) {
    console.log(`Попытка ${attempt} не удалась. Ошибка: ${error.message}`);
    if (attempt < 3) {
      test.retry();
    } else {
      throw error;
    }
  }
});

Ожидания и асинхронные операции

Ретраи могут быть особенно полезны в случаях, когда тесты не могут быть выполнены из-за асинхронных операций. Например, если на странице есть динамическая загрузка контента, то возможны ситуации, когда тест не может найти нужный элемент сразу после перехода на страницу. В таких случаях стоит использовать дополнительные ожидания или обработку ошибок, чтобы увеличить шанс успешного прохождения теста на следующей попытке.

Пример с ожиданием появления элемента:

test('Тест с ожиданием элемента и ретраем', async ({ page }) => {
  await page.goto('https://example.com');
  try {
    await page.waitForSelector('button', { timeout: 5000 });
    await page.click('button');
  } catch (error) {
    console.log('Не удалось найти кнопку. Попытка будет повторена');
    test.retry(); // Повторить тест
  }
});

Настройка ретраев для всего набора тестов

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

// test.config.js
module.exports = {
  retries: 3, // Попытки на уровне всего набора тестов
  reporter: [['json', { outputFile: 'result.json' }]], // Дополнительная настройка отчёта
};

В этом случае все тесты будут выполняться с настройкой повторных попыток.

Проблемы с ретраями

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

Заключение

Ретраи в Playwright — это мощный инструмент для повышения стабильности тестирования, который помогает избежать ложных сбоев, вызванных временными проблемами или нестабильностью внешних факторов. Гибкая настройка повторных попыток на уровне тестов или всей конфигурации помогает создавать надёжные и стабильные тесты, которые можно использовать в реальных условиях, где не всегда можно гарантировать 100%-ную стабильность работы приложения или тестовой среды.