Jenkins по умолчанию блокирует JavaScript в HTML-отчётах: заголовок Content Security Policy не даёт отчёту Playwright рендериться, пока его явно не ослабишь в Jenkins Script Console или настройках плагина HTML Publisher. Вторая типичная проблема: отсутствие системных библиотек на агенте, которую решает официальный Docker-образ Playwright со всеми зависимостями браузеров. Гайд охватывает полный Jenkinsfile: от минимального рабочего примера до многоэтапного пайплайна с параллельным запуском браузеров, шардингом между агентами, управлением секретами и ночными запусками по расписанию.
Почему Jenkins всё ещё актуален
- Многие Enterprise-компании годами вкладывались в инфраструктуру Jenkins
- On-premise hosting для требований безопасности и комплаенса
- Высокая гибкость настройки: плагины практически под всё
- Часть CI/CD-стеков строится на Jenkins + Kubernetes в масштабе
Если компания использует Jenkins, просто перейти на GitHub Actions не получится. Работаешь с тем что есть.
Предварительные условия
Понадобятся установленный Jenkins (локально или через Jenkins в Docker), Playwright-проект в Git (GitHub, GitLab, Bitbucket и др.) и плагины Jenkins: Pipeline, Git, HTML Publisher, JUnit.
Базовый Jenkinsfile
Пайплайны Jenkins описываются в файле Jenkinsfile в корне репозитория. Есть два синтаксиса: Declarative (структурированный) и Scripted (Groovy). Используй Declarative, если нет потребности в сложной логике.
// Jenkinsfile
pipeline {
agent {
docker {
image 'mcr.microsoft.com/playwright:v1.44.0-jammy'
args '-u root' // Запуск от root чтобы избежать проблем с правами
}
}
environment {
BASE_URL = credentials('staging-base-url') // Из хранилища Jenkins credentials
CI = 'true'
}
stages {
stage('Install') {
steps {
sh 'npm ci'
}
}
stage('Run Tests') {
steps {
sh 'npx playwright test --reporter=list,junit'
}
post {
always {
// Публикуем JUnit-результаты
junit 'test-results/results.xml'
// Публикуем HTML-отчёт
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'playwright-report',
reportFiles: 'index.html',
reportName: 'Playwright Report'
])
}
}
}
}
post {
failure {
// Уведомление при провале
emailext(
subject: "FAILED: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: "Tests failed. See: ${env.BUILD_URL}",
to: 'qa-team@mycompany.com'
)
}
}
}Многоэтапный пайплайн
Реальный пайплайн включает несколько этапов: линтинг, юнит-тесты, затем E2E:
pipeline {
agent {
docker {
image 'mcr.microsoft.com/playwright:v1.44.0-jammy'
args '-u root'
}
}
environment {
BASE_URL = credentials('staging-url')
NODE_ENV = 'test'
}
stages {
stage('Install Dependencies') {
steps {
sh 'npm ci'
}
}
stage('Lint') {
steps {
sh 'npm run lint'
}
}
stage('Unit Tests') {
steps {
sh 'npm run test:unit -- --reporter=junit'
}
post {
always {
junit 'unit-test-results/*.xml'
}
}
}
stage('Smoke Tests') {
steps {
sh '''
npx playwright test \
--grep @smoke \
--project=chromium \
--reporter=list,junit
'''
}
post {
always {
junit 'test-results/results.xml'
}
}
}
stage('Full Regression') {
when {
anyOf {
branch 'main'
branch 'release/*'
}
}
steps {
sh '''
npx playwright test \
--workers=4 \
--reporter=list,junit,html
'''
}
post {
always {
junit 'test-results/results.xml'
publishHTML([
reportDir: 'playwright-report',
reportFiles: 'index.html',
reportName: 'Full Regression Report',
keepAll: true
])
}
}
}
}
}Параллельный запуск тестов
Запуск тестов в нескольких браузерах параллельно через шаг parallel:
stage('Cross-Browser Tests') {
parallel {
stage('Chrome') {
steps {
sh 'npx playwright test --project=chromium --reporter=junit'
}
post {
always {
junit 'test-results/chromium-results.xml'
}
}
}
stage('Firefox') {
steps {
sh 'npx playwright test --project=firefox --reporter=junit'
}
post {
always {
junit 'test-results/firefox-results.xml'
}
}
}
stage('Safari') {
steps {
sh 'npx playwright test --project=webkit --reporter=junit'
}
post {
always {
junit 'test-results/webkit-results.xml'
}
}
}
}
}Для работы playwright.config.ts должен выводить результаты в отдельные файлы для каждого проекта:
reporter: [
['junit', {
outputFile: `test-results/${process.env.BROWSER || 'all'}-results.xml`
}],
],И запускать так:
BROWSER=chromium npx playwright test --project=chromiumШардинг между несколькими агентами
Для больших тест-сьютов разбивай работу между несколькими агентами Jenkins:
pipeline {
agent none // Каждый этап выбирает своего агента
stages {
stage('Test') {
parallel {
stage('Shard 1/3') {
agent { docker { image 'mcr.microsoft.com/playwright:v1.44.0-jammy' } }
steps {
sh 'npm ci'
sh 'npx playwright test --shard=1/3 --reporter=blob'
}
post {
always {
archiveArtifacts 'blob-report/**'
}
}
}
stage('Shard 2/3') {
agent { docker { image 'mcr.microsoft.com/playwright:v1.44.0-jammy' } }
steps {
sh 'npm ci'
sh 'npx playwright test --shard=2/3 --reporter=blob'
}
post {
always {
archiveArtifacts 'blob-report/**'
}
}
}
stage('Shard 3/3') {
agent { docker { image 'mcr.microsoft.com/playwright:v1.44.0-jammy' } }
steps {
sh 'npm ci'
sh 'npx playwright test --shard=3/3 --reporter=blob'
}
post {
always {
archiveArtifacts 'blob-report/**'
}
}
}
}
}
stage('Merge Reports') {
agent { docker { image 'mcr.microsoft.com/playwright:v1.44.0-jammy' } }
steps {
// Скачиваем артефакты со всех шардов
copyArtifacts(projectName: env.JOB_NAME, selector: specific(env.BUILD_NUMBER))
sh 'npx playwright merge-reports --reporter html,junit ./blob-report'
}
post {
always {
junit 'test-results/results.xml'
publishHTML([
reportDir: 'playwright-report',
reportFiles: 'index.html',
reportName: 'Merged Report'
])
}
}
}
}
}Credentials и секреты
Никогда не хардкоди учётные данные в Jenkinsfile. Используй Jenkins Credentials Manager:
environment {
// String credential
BASE_URL = credentials('staging-base-url')
// Credential типа username + password (создаёт две переменные окружения)
ADMIN = credentials('admin-credentials')
// Создаёт: ADMIN_USR (username) и ADMIN_PSW (password)
}
steps {
withCredentials([
string(credentialsId: 'stripe-test-key', variable: 'STRIPE_KEY'),
usernamePassword(
credentialsId: 'db-credentials',
usernameVariable: 'DB_USER',
passwordVariable: 'DB_PASS'
)
]) {
sh 'npx playwright test'
}
}Триггеры запуска
При каждом пуше
triggers {
// Опрос SCM каждые 5 минут (хуже чем webhook)
pollSCM('H/5 * * * *')
}Лучше: настрой webhook в GitHub/GitLab чтобы Jenkins получал триггер автоматически.
Запуск по расписанию (ночные прогоны)
triggers {
// Запуск в 2:00 каждую ночь
cron('0 2 * * *')
}При создании PR
Используй плагин GitHub Branch Source или Multibranch Pipeline. Jenkins автоматически запускает тесты при каждом PR и отправляет статус обратно в GitHub.
Частые проблемы Jenkins + Playwright
"No such file or directory: /home/pwuser/..."
Playwright внутри Docker-образа работает не от root. Добавь args '-u root' к docker-агенту или скорректируй пути.
"Failed to launch chromium: error while loading shared libraries"
Отсутствуют системные зависимости. Используй официальный Docker-образ Playwright: там всё предустановлено.
HTML-отчёт не отображается в Jenkins
Content Security Policy Jenkins блокирует JavaScript в HTML-отчётах. Выполни в Jenkins Script Console:
System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")Или настрой плагин HTML Publisher для ослабления CSP.
Тесты проходят локально, падают в Jenkins
Проверь: переменные окружения, base URL, настройки sandbox браузера. При необходимости добавь флаг --no-sandbox (Docker-контейнерам часто нужен для Chromium).
Минимальный рабочий Jenkinsfile
Если нужно просто что-то работающее:
pipeline {
agent {
docker {
image 'mcr.microsoft.com/playwright:v1.44.0-jammy'
args '-u root'
}
}
stages {
stage('Test') {
steps {
sh 'npm ci'
sh 'npx playwright test --reporter=junit'
}
post {
always {
junit 'test-results/results.xml'
}
}
}
}
}Это минимум. Начинай отсюда, затем добавляй этапы, параллельный запуск и уведомления по мере необходимости.
Краткая справка
| Концепция | Реализация |
|-----------|-----------|
| Агент | Официальный Docker-образ Playwright |
| Секреты | Jenkins Credentials Manager |
| Результаты | Плагин JUnit + publishHTML |
| Параллельность | Блок parallel {} или несколько агентов |
| Шардинг | --shard=X/Y + merge-reports |
| Расписание | Триггер cron() |
| При PR | Плагин GitHub Branch Source + webhook |
Jenkins требует больше настроек чем GitHub Actions, но после конфигурации работает стабильно и гибко. Подход с Jenkinsfile (pipeline-as-code) означает что конфигурация CI живёт в Git рядом с тестами: с версионированием, ревью и воспроизводимостью.
→ See also: CI/CD для QA: сравнение GitHub Actions, Jenkins и GitLab | GitHub Actions для тестов Playwright: полная настройка (2026) | Параллельное выполнение в Playwright: workers, шарды и шардирование для ускорения