Headless vs headed браузер в CI: что выбрать
Headless браузер (без GUI) экономит ресурсы. Headed (с GUI) помогает отлаживать и видеть что происходит. Большинство CI-пайплайнов работают в headless — но есть кейсы где это создаёт проблемы.
Различия на практике
Headless — браузер рендерит страницу, но не показывает её на экране. Внутри Chrome/Firefox это специальный режим.
Headed — обычный браузер с UI. Можно открыть в --headed режиме Playwright или Selenium, увидеть как тесты тапают по элементам.
Что меняется в поведении
Заявленная цель headless — идентичное поведение с headed. На практике есть мелкие различия:
— navigator.webdriver возвращает true в headless по умолчанию (антибот-системы могут это видеть).
— User-Agent: некоторые серверы детектят headless по UA-строке (HeadlessChrome в старых версиях).
— Viewport: по умолчанию headless запускается с фиксированным viewport, headed может зависеть от размера окна.
— WebGL / Canvas: некоторые GPU-операции в headless могут отличаться.
— Fonts: на CI-серверах могут отсутствовать системные шрифты (особенно эмодзи, кириллица) → текст рендерится fallback’ом.
Когда headless подходит
✅ Большая часть тестов — функциональные, accessibility, smoke. В CI быстрее, экономит RAM/CPU.
✅ Headless параллелится лучше — 10 параллельных воркеров без GPU-конкуренции.
✅ Docker-friendly — не нужен X-сервер.
Когда нужен headed (или режим близкий к нему)
⚠️ Visual regression: разница в рендере между headed и headless может вызывать false positives. Делай baselines в том же режиме что и тестовые runs.
⚠️ Антибот-системы (Cloudflare Turnstile, reCAPTCHA): они часто блокируют headless. Если тестируешь сайт защищённый антиботом — используй headed + flag --disable-blink-features=AutomationControlled.
⚠️ WebGL/Three.js приложения: на CI без GPU headless рендерит через SwiftShader (программный), скорость и качество отличаются.
⚠️ Аудио/видео: некоторые медиа-API могут вести себя по-разному без аудиоустройства в системе.
⚠️ Отладка локально: при разработке нового теста лучше headed — видишь что тестируется.
Конфигурация в Playwright
// playwright.config.ts
export default defineConfig({
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
headless: !!process.env.CI, // headless в CI, headed локально
}
}
]
});
Также для visual-тестов лучше всегда headed:
{
name: 'visual',
use: { headless: false },
testMatch: '**/*.visual.spec.ts'
}
Шрифты на CI
Самая частая проблема при переходе на CI — разные шрифты. На Ubuntu в Docker нет MS Arial → тесты рендерят fallback → пиксели не сходятся.
Решение для Playwright:
FROM mcr.microsoft.com/playwright:v1.40.0-jammy
# или
RUN apt-get install -y fonts-noto fonts-noto-cjk fonts-noto-color-emoji
Используй официальный Playwright Docker image — там предустановлены шрифты.
Что делать
✅ В CI — headless по умолчанию. Локально — headed для отладки.
✅ Для visual regression — единый режим (либо везде headless, либо везде headed).
✅ Если приложение защищено антиботом — рассмотри Playwright stealth plugin или headed-режим.
✅ Используй официальный Playwright Docker image — он решает 90% шрифт-проблем.
Подробнее: Playwright Browsers, Chrome headless mode.