Ускоряем Playwright

Большие тестовые наборы в Playwright выполняются медленно, стопорят CI-конвейер и задерживают обратную связь. В этом руководстве предложены практики, позволяющие определить и устранить распространенные узкие места.

Проблемные места в Playwright

Задержки при запуске браузера:

  • Проблема: Запуск нового экземпляра браузера для каждого теста, при параллельном выполнении нескольких тестов. 
  • Последствия: Ожидание запуска всех экземпляров в больших тестовых наборах.

Время загрузки страницы: 

  • Проблема: Ожидание полной загрузки страниц, включая все связанные с ними ресурсы (CSS, JavaScript, изображения, шрифты), является основным фактором, влияющим на продолжительность теста.
  • Последствия: Сложные страницы с большим количеством контента (с большим количеством сетевых запросов) могут значительно задержать выполнение теста. 

Сетевые запросы: 

  • Проблема: Слишком много сетевых запросов — скрипты, изображения, шрифты и другие ресурсы могут увеличить общую продолжительность набора. 
  • Последствия: Сторонние скрипты, трекеры аналитики и рекламные сети могут создавать дополнительные задержки.

Неоптимальные ожидания: 

  • Проблема: Чрезмерное использование явных (эксплицитных) ожиданий (page.waitForTimeout()) часто указывает на неэффективные селекторы или неправильную логику в ваших тестах. Неявные (имплицитные) ожидания также могут вызывать задержки, если они не настроены должным образом. 
  • Последствия: Неоптимальные ожидания могут значительно увеличить время выполнения теста, что приводит к заметным задержкам в получении результатов тестирования. 

Неправильная структура тестов:

  • Проблема: Плохо структурированные тесты с избыточными действиями, неэффективными ассертами или длительными процедурами установки/настройки и завершения могут значительно увеличивать время выполнения набора. 
  • Последствия: Недостатки структуры, хотя и кажутся незначительными для каждого отдельного теста, могут приводить к значительной суммарной задержке при масштабировании на большой тестовый набор. 

Стратегии ускорения

Используйте параллелизм: 

  • Уровень тестов: Одновременный запуск нескольких тестов в рамках одного worker-процесса, что повышает скорость (если в тестах нет сильных зависимостей):
test.concurrent('should login successfully', async ({ page }) => { ... });
test.concurrent('should display error for invalid credentials', async ({ page }) => { ... });
  • Уровень worker’ов: Распределите тесты между несколькими процессами, чтобы задействовать все ядра процессора:
// playwright.config.js
export default defineConfig({
  workers: 4,  // Use 4 worker processes (adjust to your machine's capabilities)
});
  • Шардинг: Разделите набор тестов на мелкие фрагменты (шарды) и запускайте их отдельно на машинах или CI-узлах:
npx playwright test --shard=1/3  # Run the first shard

По теме: Туториал по шардингу в Playwright

  • Облачное распараллеливание: Для достижения максимальной скорости используйте облачные сервисы, такие как BrowserStack или LambdaTest, чтобы запускать тесты одновременно в сотнях окружений:
// playwright.config.js (example for BrowserStack)
export default defineConfig({
  use: {
    browserStack: {
      username: process.env.BROWSERSTACK_USERNAME,
      accessKey: process.env.BROWSERSTACK_ACCESS_KEY,
    },
  },
  projects: [
    { name: 'chrome', use: { browserName: 'chromium' } },
    { name: 'firefox', use: { browserName: 'firefox' } },
    // ... more browser configurations
  ],
});

Основные селекторы и ожидания: 

  • CSS-селекторы: Точнее таргетируйте элементы, с помощью уникальных селекторов или атрибутов данных:
await page.click('button[data-testid="submit-button"]'); // Best practice
await page.click('text=Submit'); // Alternative using text content
  • Эксплицитные ожидания: Замените стандартный waitForTimeout на более точный waitForSelector или waitForNavigation:
await page.waitForSelector('.success-message'); 
await page.waitForNavigation(); 
  • Умные ожидания: Используйте waitForFunction для ожидания определенных условий на странице:
await page.waitForFunction(() => document.readyState === 'complete');

Кэширование и повторное использование:

  • Контексты браузера: Повторное использование одного и того же контекста браузера для нескольких тестов в одном файле:
// Create the context ONCE at the top level of the file
const context = await browser.newContext();
test('test1', async ({ page }) => {
  // Use the same context for all tests in this file
  await page.goto('https://example.com');
  // ... 
});
test('test2', async ({ page }) => {
  // ...
});
  • Аутентификация: Сохраняйте и повторно используйте статусы и артефакты аутентификации (например, cookie-файлы), чтобы избежать лишних логинов:
const storageState = await context.storageState();
fs.writeFileSync('auth.json', JSON.stringify(storageState));

// ... later in another test ...
const context = await browser.newContext({ storageState: JSON.parse(fs.readFileSync('auth.json')) });
  • Codegen: Записывайте пользовательские потоки для автоматической генерации тестового кода во встроенном генераторе Playwright.

Оптимизация запросов: 

  • Перехват: Имитация или блокировка проблемных сетевых запросов:
await page.route('**/api/**', route => route.fulfill({
  status: 200,
  contentType: 'application/json',
  body: JSON.stringify({ data: 'mocked data' }),
}));

Корректировка тестов:

  • Независимость: Создавайте изолированные тесты, избегая общих статусов для нескольких, которые могут привести к непредвиденным взаимодействиям. 
  • Приоритезируйте: Выполняйте сначала более важные тесты, чтобы быстрее получить обратную связь по основной функциональности
  • Устраняйте всё лишнее: Проанализируйте набор, чтобы убрать ненужные действия и ассерты.

Оборудование и инфраструктура: 

  • Больше ядер: Инвестируйте в мощные машины с большим количеством процессорных ядер, чтобы максимизировать преимущества распараллеливания. 
  • Оперативная память: Обеспечьте достаточный объем памяти.
  • Облачная инфраструктура: Рассмотрите возможность использования провайдеров облачного тестирования, чтобы масштабировать проблемные тесты в облаке у провайдера.

Профилирование и анализ: 

  • Трассировщик: Используйте встроенный в Playwright просмотр трассировки, чтобы получить представление о примерном времени выполнения тестов. Это позволит выявить особо медленные шаги, проблемные места в целом, и возможности для оптимизации. 
  • Инструменты профилирования производительности: Используйте такие инструменты, как Lighthouse или Chrome DevTools, для анализа производительности веб-приложения. Решение общих проблем с производительностью приложения может косвенно привести к ускорению тестов.

Продвинутые методы

Тонкая настройка стратегий загрузки страниц: 

  • Navigation Timing API: Используйте Navigation Timing API для точного измерения событий загрузки страницы и поиска узких мест. Возможно понадобится точнее прописать ожидания — на основе определенных метрик, таких как loadEventEnd или DOMContentLoaded:
await page.evaluate(() => performance.timing.loadEventEnd);
  • Обнаружение простоя сети: Вместо того чтобы ждать загрузки всей страницы, попробуйте ориентироваться на неактивность сети. Это может быть эффективно при работе со страницами, которые загружают динамическое содержимое асинхронно:
await page.waitForLoadState('networkidle');
  • Ленивая загрузка и обнаружение пересечений: Если ваше приложение использует ленивую загрузку (Lazy Loading) для изображений или контента, расположенного ниже активного экрана, эксплицитно запустите загрузку этих элементов перед взаимодействием с ними. Для этого может пригодиться Intersection Observer API.

Настроенные ожидания с помощью jQuery (или других библиотек):

  • Ожидание динамического контента: Если ваше приложение в значительной степени полагается на JavaScript для отображения контента, используйте jQuery (или аналогичные библиотеки) для ожидания появления определенных элементов или выполнения условий:
await page.waitForFunction(() => $('#dynamic-elements').length > 0); 
  • Видимость элементов: Убедитесь, что элементы не только присутствуют в DOM, но и видны перед взаимодействием с ними. Селектор jQuery:visible можно использовать для создания более надежных ожиданий:
await page.waitForSelector('#visibled');  

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

  • Моки и стабы: Для тестов, которые сильно зависят от внешних API-интерфейсов, рассмотрите возможность создания заглушек-моков или стабов, чтобы избежать задержек, связанных с реальными сетевыми запросами. Для этого можно использовать такие библиотеки, как nock или msw (Mock Service Worker). 
  • Service Workers: Обратите внимание на то, как работники сервисов кэшируют данные, если ваше приложение использует их. При проведении тестов, требующих новых данных, очищайте или обходите кэши service worker’ов.
  • Троттлинг ресурсов: Чтобы найти узкие места в производительности тестов и убедиться, что ваше приложение более-менее справляется с нагрузкой, имитируйте медленное подключение в Playwright.

Трассировщик Playwright (Trace Viewer): 

  • Визуализация выполнения теста: В средстве просмотра трассировки можно увидеть временную шкалу сетевых запросов, событий навигации по странице и выполнения JavaScript. Используйте ее, чтобы определить, какие части ваших тестов занимают больше всего времени.
  • Выявление нестабильных тестов: Поищите в трассировщике длительные паузы или некорректные сетевые запросы.

Резюме

Поддержание максимальной скорости и эффективности тестирования требует постоянного мониторинга и совершенствования. Оптимизация производительности — это постоянная работа.

NashTechGlobal


Какой была ваша первая зарплата в QA и как вы искали первую работу?

Мега обсуждение в нашем телеграм-канале о поиске первой работы. Обмен опытом и мнения.

Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

Мы в Telegram

Наш официальный канал
Полезные материалы и тесты
Готовимся к собеседованию
Project- и Product-менеджмент

? Популярное

? Telegram-обсуждения

Наши подписчики обсуждают, как искали первую работу в QA. Некоторые ищут ее прямо сейчас.
Наши подписчики рассказывают о том, как не бояться задавать тупые вопросы и чувствовать себя уверенно в новой команде.
Обсуждаем, куда лучше податься - в менеджмент или по технической ветке?
Говорим о конфликтных ситуациях в команде и о том, как их избежать
$1100*
медианная зарплата в QA в июне 2023

*по результатам опроса QA-инженеров в нашем телеграм-канале

Собеседование

19%*
IT-специалистов переехало или приняло решение о переезде из России по состоянию на конец марта 2022

*по результатам опроса в нашем телеграм-канале

live

Обсуждают сейчас