QA Interview Hub · База знань · Тести

CI/CD

Docker для автотестів

Playwright в офіційному Docker-образі

Офіційний образ mcr.microsoft.com/playwright містить Node, браузери потрібної ревізії та системні бібліотеки. Тег має збігатися з версією @playwright/test у package-lock.json: кожна версія Playwright чекає свої збірки браузерів, і при розбіжності тести падають із помилкою «browser not found».

docker run --rm --init --ipc=host \
  -v "$PWD":/work -w /work \
  mcr.microsoft.com/playwright:v1.64.0-noble \
  sh -c "npm ci && npx playwright test"

(Версію v1.64.0 замініть на свою; noble — база Ubuntu 24.04.) Навіщо прапорці: --ipc=host дає Chromium нормальну спільну пам'ять (інакше падіння на важких сторінках), --init прибирає зомбі-процеси.

Чому це розв'язує «скріншоти різні локально і в CI». Рендеринг тексту залежить від ОС, шрифтів і бібліотек. Якщо baseline зроблений на macOS чи Windows, а порівняння йде на Linux-раннері, піксельні відмінності неминучі. Образ дає ідентичне середовище: baseline створюють і оновлюють у тому самому образі (npx playwright test --update-snapshots всередині контейнера), а CI запускає той самий образ.

У GitHub Actions образ вказують на рівні job: container: { image: mcr.microsoft.com/playwright:v1.64.0-noble }. Тоді npx playwright install не потрібен — браузери вже всередині. Тег піднімають разом з оновленням @playwright/test в одному PR.

docker compose для e2e: app + db + тести

Compose піднімає застосунок, базу й сам тест-раннер однією командою, а потім усе прибирає. Ідея: ефемерне оточення на кожен прогін — порожня БД, відомий стан, жодних спільних stage-даних, тому паралельні PR не заважають один одному.

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: test
      POSTGRES_DB: app_test
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U postgres -d app_test']
      interval: 2s
      timeout: 3s
      retries: 15

  app:
    build: .
    environment:
      DATABASE_URL: postgres://postgres:test@db:5432/app_test
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ['CMD-SHELL', 'curl -fs http://localhost:3000/health || exit 1']
      interval: 2s
      timeout: 3s
      retries: 30

  e2e:
    image: mcr.microsoft.com/playwright:v1.64.0-noble
    working_dir: /work
    volumes:
      - ./:/work
    ipc: host
    environment:
      BASE_URL: http://app:3000
    depends_on:
      app:
        condition: service_healthy
    command: sh -c "npm ci && npx playwright test"
docker compose up --build --abort-on-container-exit --exit-code-from e2e
docker compose down -v

Ключові моменти:

  • Сервіси бачать один одного за іменем сервісу (db, app), а не за localhost;
  • depends_on без condition гарантує лише порядок запуску контейнерів. Готовність забезпечують healthcheck + condition: service_healthy;
  • --exit-code-from e2e віддає код виходу тестів у CI; без нього пайплайн може бути зеленим при впалих тестах;
  • Секрети й конфіг передаються через environment / env_file (у CI — зі secrets), не вшиваються в образ;
  • Звіти потрапляють на хост завдяки volume (./:/work): папка playwright-report/ доступна наступному кроку CI для upload-artifact;
  • down -v видаляє volumes, щоб наступний прогін стартував з чистою БД.