Home » Запуск end-to-end тестов с Playwright и Docker
Запуск end-to-end тестов с Playwright и Docker

Запуск end-to-end тестов с Playwright и Docker

Разворачивание end-to-end тестов в продакшене — это то, что рано или поздно приходится делать каждому девопсу. Особенно когда дело касается автоматизации тестирования фронтенда в CI/CD пайплайнах. Playwright в паре с Docker — это мощная комбинация для создания стабильных и изолированных тестовых окружений. В этой статье разберём, как поднять полноценную тестовую среду с нуля, настроить контейнеризацию и избежать классических граблей при работе с браузерной автоматизацией в серверных средах.

Зачем Docker для Playwright-тестов?

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

Docker решает эти проблемы изоляцией:

  • Все браузеры и зависимости упакованы в контейнер
  • Одинаковое окружение на dev/stage/prod
  • Легкое масштабирование тестов
  • Отсутствие конфликтов с системными пакетами

Подготовка окружения

Для работы понадобится сервер с Docker. Если у вас ещё нет подходящего сервера, можно взять VPS или выделенный сервер с достаточными ресурсами.

Минимальные требования:

  • 2 CPU cores
  • 4GB RAM
  • 10GB свободного места
  • Docker 20.10+

Установка Docker (если ещё не установлен):

curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
sudo usermod -aG docker $USER
newgrp docker

Создание базового Dockerfile

Playwright предоставляет готовые Docker-образы с предустановленными браузерами. Создаём структуру проекта:

mkdir playwright-e2e-tests
cd playwright-e2e-tests
mkdir tests
mkdir results

Создаём Dockerfile:

FROM mcr.microsoft.com/playwright:v1.40.0-focal

WORKDIR /app

# Копируем package.json и устанавливаем зависимости
COPY package*.json ./
RUN npm ci

# Копируем тесты
COPY . .

# Устанавливаем браузеры (если нужны дополнительные)
RUN npx playwright install

# Запускаем тесты
CMD ["npx", "playwright", "test"]

Настройка Playwright конфигурации

Создаём package.json с необходимыми зависимостями:

{
  "name": "playwright-e2e-docker",
  "version": "1.0.0",
  "devDependencies": {
    "@playwright/test": "^1.40.0"
  },
  "scripts": {
    "test": "playwright test",
    "test:headed": "playwright test --headed",
    "test:debug": "playwright test --debug"
  }
}

Конфигурация playwright.config.js для работы в Docker:

const { defineConfig } = require('@playwright/test');

module.exports = defineConfig({
  testDir: './tests',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: [
    ['html', { outputFolder: 'results/html-report' }],
    ['json', { outputFile: 'results/results.json' }],
    ['junit', { outputFile: 'results/junit.xml' }]
  ],
  use: {
    baseURL: process.env.BASE_URL || 'http://localhost:3000',
    trace: 'on-first-retry',
    video: 'retain-on-failure',
    screenshot: 'only-on-failure',
    // Важно для Docker - отключаем песочницу
    launchOptions: {
      args: ['--no-sandbox', '--disable-setuid-sandbox']
    }
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
  webServer: process.env.CI ? undefined : {
    command: 'npm run start',
    port: 3000,
  },
});

Создание тестового примера

Создаём простой тест в tests/example.spec.js:

const { test, expect } = require('@playwright/test');

test('homepage has title', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveTitle(/My App/);
});

test('navigation works', async ({ page }) => {
  await page.goto('/');
  await page.click('text=About');
  await expect(page).toHaveURL(/.*about/);
});

test('form submission', async ({ page }) => {
  await page.goto('/contact');
  await page.fill('#name', 'Test User');
  await page.fill('#email', 'test@example.com');
  await page.click('button[type="submit"]');
  await expect(page.locator('.success-message')).toBeVisible();
});

Docker Compose для удобства

Создаём docker-compose.yml для более удобного управления:

version: '3.8'

services:
  playwright-tests:
    build: .
    volumes:
      - ./results:/app/results
      - ./tests:/app/tests
    environment:
      - BASE_URL=https://example.com
      - CI=true
    depends_on:
      - app
    networks:
      - test-network

  app:
    image: nginx:alpine
    ports:
      - "3000:80"
    volumes:
      - ./public:/usr/share/nginx/html
    networks:
      - test-network

networks:
  test-network:
    driver: bridge

Запуск тестов

Теперь можно запускать тесты несколькими способами:

# Сборка образа
docker build -t playwright-e2e .

# Запуск тестов
docker run -v $(pwd)/results:/app/results playwright-e2e

# Или через docker-compose
docker-compose up --build

# Запуск в интерактивном режиме для отладки
docker run -it --entrypoint bash playwright-e2e

Практические кейсы и проблемы

Проблема Решение Рекомендации
Тесты падают с “Browser not found” Добавить RUN npx playwright install в Dockerfile Использовать официальные образы с предустановленными браузерами
Медленная работа в headless режиме Добавить –no-sandbox в launchOptions Для Docker всегда отключать песочницу браузера
Нестабильные тесты Увеличить timeout, добавить retry Использовать явные ожидания вместо sleep
Большой размер образа Использовать multi-stage builds Кэшировать node_modules слой

Оптимизация Docker образа

Для продакшена лучше использовать многоэтапную сборку:

FROM mcr.microsoft.com/playwright:v1.40.0-focal as base

WORKDIR /app

# Установка зависимостей
FROM base as dependencies
COPY package*.json ./
RUN npm ci --only=production

# Финальный образ
FROM base as final
COPY --from=dependencies /app/node_modules ./node_modules
COPY . .

# Создаем пользователя для безопасности
RUN groupadd -r pwuser && useradd -r -g pwuser -G audio,video pwuser \
    && mkdir -p /home/pwuser/Downloads \
    && chown -R pwuser:pwuser /home/pwuser \
    && chown -R pwuser:pwuser /app

USER pwuser

CMD ["npx", "playwright", "test"]

Интеграция с CI/CD

Пример GitHub Actions workflow:

name: E2E Tests

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Run E2E tests
      run: |
        docker build -t playwright-e2e .
        docker run -v $(pwd)/results:/app/results playwright-e2e
    
    - name: Upload test results
      uses: actions/upload-artifact@v3
      if: always()
      with:
        name: test-results
        path: results/

Мониторинг и логирование

Для отслеживания результатов тестов можно настроить отправку метрик:

#!/bin/bash
# test-runner.sh

# Запуск тестов
docker run -v $(pwd)/results:/app/results playwright-e2e

# Парсинг результатов
PASSED=$(jq '.stats.passed' results/results.json)
FAILED=$(jq '.stats.failed' results/results.json)

# Отправка в мониторинг
curl -X POST "http://monitoring:8086/write?db=tests" \
  -d "playwright_tests,environment=prod passed=${PASSED},failed=${FAILED}"

# Уведомления в Slack при провале
if [ $FAILED -gt 0 ]; then
  curl -X POST -H 'Content-type: application/json' \
    --data '{"text":"E2E tests failed: '${FAILED}' tests"}' \
    $SLACK_WEBHOOK_URL
fi

Альтернативные решения

Кроме Playwright + Docker существуют другие варианты:

  • Selenium Grid — классическое решение, но требует больше настройки
  • Cypress — хороший инструмент, но ограничен Chromium-based браузерами
  • Puppeteer — только Chrome/Chromium, но очень быстрый
  • TestCafe — не требует WebDriver, но менее гибкий

Сравнение производительности (среднее время выполнения 100 тестов):

Инструмент Время выполнения Потребление RAM Поддержка браузеров
Playwright ~3 мин ~500MB Chrome, Firefox, Safari
Selenium ~5 мин ~800MB Все основные
Cypress ~4 мин ~400MB Chrome, Edge
Puppeteer ~2 мин ~300MB Chrome/Chromium

Расширенные возможности

Playwright в Docker открывает интересные возможности:

  • Параллельное выполнение — запуск нескольких контейнеров одновременно
  • Скриншоты и видео — автоматическое сохранение при падении тестов
  • Сетевые моки — перехват и подмена API запросов
  • Геолокация и мобильная эмуляция — тестирование responsive дизайна

Пример параллельного запуска:

# docker-compose.parallel.yml
version: '3.8'

services:
  tests-chrome:
    build: .
    environment:
      - BROWSER=chromium
    volumes:
      - ./results/chrome:/app/results

  tests-firefox:
    build: .
    environment:
      - BROWSER=firefox
    volumes:
      - ./results/firefox:/app/results

  tests-webkit:
    build: .
    environment:
      - BROWSER=webkit
    volumes:
      - ./results/webkit:/app/results

Интеграция с внешними сервисами

Playwright + Docker хорошо интегрируется с внешними сервисами:

// tests/api-integration.spec.js
const { test, expect } = require('@playwright/test');

test.describe('API Integration Tests', () => {
  test('should work with external API', async ({ page, request }) => {
    // Мокаем API ответ
    await page.route('**/api/users', route => {
      route.fulfill({
        status: 200,
        body: JSON.stringify([
          { id: 1, name: 'John Doe' },
          { id: 2, name: 'Jane Smith' }
        ])
      });
    });

    await page.goto('/users');
    await expect(page.locator('.user-list')).toContainText('John Doe');
  });

  test('should handle API errors gracefully', async ({ page }) => {
    await page.route('**/api/users', route => {
      route.fulfill({ status: 500 });
    });

    await page.goto('/users');
    await expect(page.locator('.error-message')).toBeVisible();
  });
});

Автоматизация развёртывания

Для автоматизации можно создать bash-скрипт:

#!/bin/bash
# deploy-tests.sh

set -e

ENVIRONMENT=${1:-staging}
TESTS_DIR="/opt/playwright-tests"
RESULTS_DIR="/var/log/playwright-results"

echo "Deploying E2E tests for $ENVIRONMENT environment"

# Подготовка директорий
mkdir -p $RESULTS_DIR
cd $TESTS_DIR

# Получение последних изменений
git pull origin main

# Сборка образа
docker build -t playwright-e2e:$ENVIRONMENT .

# Запуск тестов
docker run \
  --name playwright-tests-$ENVIRONMENT \
  --rm \
  -v $RESULTS_DIR:/app/results \
  -e BASE_URL=$BASE_URL \
  -e ENVIRONMENT=$ENVIRONMENT \
  playwright-e2e:$ENVIRONMENT

echo "Tests completed. Results available in $RESULTS_DIR"

# Очистка старых результатов (старше 30 дней)
find $RESULTS_DIR -name "*.json" -mtime +30 -delete

Заключение и рекомендации

Playwright + Docker — это мощная комбинация для создания надёжных e2e тестов. Основные преимущества:

  • Изоляция — тесты не зависят от окружения сервера
  • Воспроизводимость — одинаковое поведение везде
  • Масштабируемость — легко добавить больше тест-раннеров
  • Безопасность — браузеры изолированы в контейнере

Когда использовать:

  • Для CI/CD пайплайнов
  • При необходимости тестирования в разных браузерах
  • Для регрессионного тестирования
  • При работе с микросервисной архитектурой

Где не стоит использовать:

  • Для простых smoke-тестов (избыточно)
  • При критичности скорости выполнения
  • Для тестирования native мобильных приложений

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

Для получения дополнительной информации обращайтесь к официальной документации: Playwright Docker Guide и Docker Compose Documentation.


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

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

Leave a reply

Your email address will not be published. Required fields are marked