Шардинг в Playwright

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

Параллелизм

В Playwright предусмотрен параллельный запуск тестов, и по умолчанию в файле playwright.config.js установлено значение true. При включении этой опции запускается несколько worker-процессов, выполняющихся одновременно. Тесты в одном файле запускаются последовательно в одном worker-процессе.

Параллельные тесты выполняются в отдельных рабочих процессах и могут не иметь общих состояний или общих глобальных переменных. 

Существует несколько способов настроить параллельное выполнение тестов.

  1. Использование test.describe.configure({ mode: 'parallel' });
  2. Также можем использовать fullyParallel: true, чтобы включить параллельность для всех тестов
  3. Или включить fullyParallel: true для некоторых проектов, например chromium, firefox, webkit и т. д.

Чтобы отключить этот параллелизм, мы можем настроить запуск тестов с использованием только одного worker-а, через конфигурационный файл, установив для worker-ов значение 1, или передать то же самое из командной строки: npx playwright test — workers=1.

Подробнее о параллельном запуске — на сайте Playwright.

Что такое шардинг

Sharding происходит от концепции архитектуры баз данных, в которой мы разбиваем большую базу данных на несколько «кусков» или шардов, чтобы распределить и оптимизировать нагрузку, повысить эффективность и масштабируемость системы. Это можно назвать горизонтальным масштабированием, когда каждый шард ведет себя как независимая единица со своими собственными ресурсами и управляет данными соответствующим образом. Таким образом улучшается производительность запросов и устраняются точки отказа при использовании отдельного сервера базы данных, который обрабатывает огромные объемы данных.

Подробнее о шардинге здесь, а также замечательное видео.

Теперь, перейдя в мир Playwright, мы можем использовать концепцию шардинга для ускорения выполнения тестов путем разделения этих тестов по отдельным шардам, то есть машинам. Мы можем сделать это с помощью параметра shard, то есть shard=x/y, где x — индекс-shard, а y — общее количество шардов.

npx playwright test --shard=1/4
npx playwright test --shard=2/4
npx playwright test --shard=3/4
npx playwright test --shard=4/4

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

Для демонстрационных целей я установил Playwright на локальной машине и буду использовать пример boilerplate-кода, представленный в папке tests-examples, где у нас есть несколько тестов, которые настроены для запуска на сайте playwright to-do mvc (URL: https://demo.playwright.dev/todomvc

Здесь у нас 24 теста, которые запускаются на 3 браузерах, поэтому в целом 72 теста для одного файла, я скопировал один и тот же файл дважды, поэтому с 3 файлами спецификаций у нас 216 тестов в 3 браузерах — chromium, firefox и webkit. Я переименовал файлы спецификаций, как показано ниже.

В файле playwright.config.js я задал следующие конфигурации, установив значение parallel в true и значение workers в 6.

fullyParallel: true

workers: process.env.CI ? 6 : 6

Это означает, что когда я выполню команду: npx playwright test, все 216 тестов будут запущены 6 worker-ами локально и в CI. Приведенные ниже тесты выполняются на локальной машине с использованием 6 worker-ов.

Теперь, когда я выполню команду npx playwright test вместе с параметром shard, указав общее количество шардов как 4, то сначала 216 тестов будут разделены на 4 куска по 54 теста в каждом. Затем эти 54 теста будут выполнены с помощью 6 worker-а в шарде 1, 54 теста с помощью 6 worker-ов в шарде 2, как показано ниже. Поскольку каждый шард будет выполняться на своей собственной машине-агенте, уровень параллелизма будет гораздо выше, и наши тесты будут выполняться значительно быстрее, чем при использовании 6 worker-ов в стандартной конфигурации.

Но с шардингом мы столкнулись с проблемой при создании репортов (с помощью стандартной опции html-репорта). После выполнения теста, выполнив команду ‘npx playwright show-report‘, мы увидим, что в сгенерированном отчете будут показаны только результаты последнего запущенного шарда, содержащего всего 54 теста, как показано ниже. А как быть с остальными, в предыдущих шардах?

Чтобы решить эту проблему, нам нужно сконфигурировать наш репортер как ‘blob’, когда мы используем шардинг. По умолчанию каждый шард будет генерировать свои собственные blob-репорты в папку под названием blob-report. Затем нам нужно будет объединить все эти отдельные blob-репорты со всех шардов, чтобы получить консолидированный репорт по всем тестам, которые были выполнены на всех шардах.

export default defineConfig({
  reporter: process.env.CI ? 'blob' : 'html'
});

Чтобы объединить репорты из нескольких шардов, поместите файлы blob-репортов в один каталог, например, в нашем случае all-blob-reports, тогда окончательный HTML-репорт будет доступен в папке playwright-report.

npx playwright merge-reports --reporter html ./all-blob-reports

Шардинг в CI с помощью Github Actions

Теперь, чтобы еще эффективнее использовать шардинг, применим такие инструменты CI, как Github Actions, которые позволяют удобно настраивать и запускать тесты на нескольких машинах-агентах. Для этого нам нужно включить следующие пункты в наш файл рабочего процесса Github actions:

  1. Добавление стратегии с опцией matrix в задачу со значениями shardIndex и shardTotal.
  2. Запуск команды npx playwright test с указанием параметров shardindex и shardTotal.
  3. Загрузить блоб-репорт отдельных шардов в артефакты Github actions, чтобы задача merge-report могла подхватить его и сгенерировать консолидированный HTML-отчет.
name: Sharding Tests
on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]

jobs:
  run-tests:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        shardIndex: [1, 2, 3, 4, 5, 6 ]
        shardTotal: [6]
    steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-node@v3
      with:
        node-version: 20
    
    - name: Install dependencies
      run: npm ci

    - name: Install Playwright Browsers
      run: npx playwright install --with-deps

    - name: Run Playwright tests
      run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
    
    - name: Upload blob report to GitHub Actions Artifacts
      if: always()
      uses: actions/upload-artifact@v4
      with:
        name: blob-report-${{ matrix.shardIndex }}
        path: blob-report
        retention-days: 1

Для задачи «run-tests» мы будем использовать в общей сложности 6 шардов, указанных в matrix, с параметром fail-fast, установленным на false. Затем мы выполним npx playwright test, используя определенные значения shardIndex и shardTotal, например 1/6, 2/6 и т. д. Наконец, когда все шарды будут выполнены, blob-репорты по каждому шарду будут загружены в артефакты Actions в разделе blob-report с суффиксом shardIndex.

Далее нам нужно добавить задачу «merge-reports«, которая будет зависеть от задачи run-tests. Эта задача будет загружать все отдельные blob-репорты шардов в указанную папку под названием all-blob-reports, а затем выполнять команду merge-reports, чтобы получить объединенный HTML-репорт и загрузить его на вкладку GitHub Actions Artifacts.

merge-reports:             
      if: always()
      needs: [run-tests]
          
      runs-on: ubuntu-latest
      steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      - name: Install dependencies
        run: npm ci
          
      - name: Download blob reports from GitHub Actions Artifacts
        uses: actions/download-artifact@v4
        with:
          path: all-blob-reports 
          pattern: blob-report-*
          merge-multiple: true
          
      - name: Merge into HTML Report
        run: npx playwright merge-reports --reporter html ./all-blob-reports 
          
      - name: Upload HTML report
        uses: actions/upload-artifact@v4
        with:
          name: html-report--attempt-${{ github.run_attempt }}
          path: playwright-report
          retention-days: 7

Вот мой полный файл workflow вместе с задачами:

name: Playwright tests using sharding
on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]
jobs:
  run-tests:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        shardIndex: [1, 2, 3, 4, 5, 6 ]
        shardTotal: [6]
    steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-node@v3
      with:
        node-version: 20
    - name: Install dependencies
      run: npm ci
    - name: Install Playwright Browsers
      run: npx playwright install --with-deps
    - name: Run Playwright tests
      run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
    
    - name: Upload blob report to GitHub Actions Artifacts
      if: always()
      uses: actions/upload-artifact@v4
      with:
        name: blob-report-${{ matrix.shardIndex }}
        path: blob-report
        retention-days: 1

  merge-reports:             
      if: always()
      needs: [run-tests]
          
      runs-on: ubuntu-latest
      steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      - name: Install dependencies
        run: npm ci
          
      - name: Download blob reports from GitHub Actions Artifacts
        uses: actions/download-artifact@v4
        with:
          path: all-blob-reports 
          pattern: blob-report-*
          merge-multiple: true
          
      - name: Merge into HTML Report
        run: npx playwright merge-reports --reporter html ./all-blob-reports 
          
      - name: Upload HTML report
        uses: actions/upload-artifact@v4
        with:
          name: html-report--attempt-${{ github.run_attempt }}
          path: playwright-report
          retention-days: 7

Как только файл workflow будет отправлен на Github, все тесты (216) будут распределены и запущены на определенных машинах шарда, в нашем случае на 6 машинах. Как видно ниже, 36 тестов выполняются на машине run-tests (1,6). Аналогично 36 тестов будут выполнены с помощью 6 worker-ов на другой машине шарда. После выполнения всех тестов будет запущена задача слияния репортов, которая сгенерирует консолидированный HTML-репорт.

Ниже приведены артефакты, которые были загружены в рамках выполнения workflow: индивидуальный блоб-репорт по шардам и итоговый консолидированный html-репорт.

Загрузив и открыв репорт, вы обнаружите полный отчет о прогоне тестов, содержащий 216 тестов, выполненных на 6 шард-машинах.

Вот что умеет Playwright. Спасибо за прочтение и надеемся, что эта статья была вам полезна.»

Источник

Официальная документация Playwright 


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

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

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

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

Мы в Telegram

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

? Популярное

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

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

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

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

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

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

live

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