Почему Jenkins важен для QA
Jenkins — самый широко развёрнутый CI/CD-сервер в мире. С более чем 1800 плагинами и огромным сообществом он остаётся основой пайплайнов автоматизации тестирования в тысячах компаний — от стартапов до таких предприятий как Netflix и Airbnb.
Как QA-инженер, вы почти наверняка столкнётесь с Jenkins в своей карьере. Даже если ваша текущая команда использует другой инструмент, понимание Jenkins даёт передаваемые знания о проектировании CI/CD-пайплайнов, применимые повсюду.
Архитектура Jenkins
Jenkins работает на архитектуре controller-agent:
- Controller (Master): Управляет веб-интерфейсом, планирует сборки, распределяет задания по агентам и хранит результаты
- Agents (Nodes): Выполняют реальную работу по сборке и тестированию. Агенты могут быть физическими машинами, виртуальными машинами, Docker-контейнерами или Kubernetes-подами
Это разделение критично для QA, потому что выполнение тестов может быть ресурсоёмким. Запуск Selenium-тестов на контроллере замедлит всё. Выделенные агенты обеспечивают тесты необходимыми ресурсами без влияния на другие задания.
Ключевые концепции
| Концепция | Описание |
|---|---|
| Job | Настроенная задача автоматизации (сборка, тест, деплой) |
| Pipeline | Серия этапов, определённых в коде (Jenkinsfile) |
| Stage | Логическая группировка шагов (напр., “Build”, “Test”, “Deploy”) |
| Step | Отдельная команда или действие внутри stage |
| Build | Одно выполнение job/pipeline |
| Workspace | Каталог, где Jenkins загружает код и выполняет шаги |
| Artifact | Файлы, сохранённые из сборки (отчёты тестов, скриншоты, логи) |
Декларативный Jenkinsfile
Современный Jenkins использует декларативные Jenkinsfile — определения пайплайнов, хранящиеся в репозитории проекта. Это подход pipeline-as-code.
Базовая структура
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'npm ci'
}
}
stage('Unit Tests') {
steps {
sh 'npm test'
}
}
stage('E2E Tests') {
steps {
sh 'npx playwright test'
}
}
}
post {
always {
junit '**/test-results/*.xml'
archiveArtifacts artifacts: '**/test-reports/**', allowEmptyArchive: true
}
failure {
echo 'Пайплайн упал! Проверьте отчёты тестов.'
}
}
}
Конфигурация агентов
Директива agent указывает Jenkins, где выполнять пайплайн:
// Выполнить на любом доступном агенте
agent any
// Выполнить на агенте с определённой меткой
agent { label 'linux && chrome' }
// Выполнить внутри Docker-контейнера
agent {
docker {
image 'mcr.microsoft.com/playwright:v1.40.0-focal'
}
}
Для QA Docker-агенты особенно полезны, потому что они предоставляют консистентное окружение с предустановленными браузерами и инструментами тестирования.
Переменные окружения
pipeline {
agent any
environment {
BASE_URL = 'https://staging.example.com'
TEST_ENV = 'ci'
BROWSER = 'chromium'
}
stages {
stage('E2E Tests') {
steps {
sh 'npx playwright test --project=${BROWSER}'
}
}
}
}
Используйте credentials() для чувствительных значений:
environment {
DB_CREDS = credentials('test-database-credentials')
API_KEY = credentials('api-key-staging')
}
Параллельное выполнение тестов
Запуск тестов параллельно — одна из наиболее эффективных оптимизаций для QA-пайплайнов. Jenkins поддерживает параллелизацию на уровне stage:
stage('Tests') {
parallel {
stage('Тесты Chrome') {
agent { label 'chrome' }
steps {
sh 'npx playwright test --project=chromium'
}
}
stage('Тесты Firefox') {
agent { label 'firefox' }
steps {
sh 'npx playwright test --project=firefox'
}
}
stage('API-тесты') {
agent any
steps {
sh 'npm run test:api'
}
}
}
}
Это запускает тесты Chrome, Firefox и API одновременно на разных агентах. Если каждый набор занимает 15 минут, параллельный этап завершается за 15 минут вместо 45 минут последовательно.
Отчёты о тестах
Jenkins предоставляет несколько способов отображения результатов тестов.
Плагин JUnit Report
Большинство тестовых фреймворков могут генерировать формат JUnit XML. Jenkins может парсить эти отчёты и показывать результаты в панели сборки:
post {
always {
junit testResults: '**/junit-results.xml', allowEmptyResults: true
}
}
HTML Publisher
Для богатых тестовых отчётов (Allure, Playwright HTML reporter):
post {
always {
publishHTML([
reportDir: 'playwright-report',
reportFiles: 'index.html',
reportName: 'Отчёт Playwright'
])
}
}
Архивация артефактов
Сохранение скриншотов, видео и логов упавших тестов:
post {
always {
archiveArtifacts artifacts: 'test-results/**', allowEmptyArchive: true
}
failure {
archiveArtifacts artifacts: 'screenshots/**', allowEmptyArchive: true
}
}
Quality Gates в Jenkins
Quality gates определяют критерии, которые должны быть выполнены для продолжения пайплайна. Для QA типичные gates включают:
Процент прохождения тестов
stage('Quality Gate') {
steps {
script {
def testResults = currentBuild.rawBuild.getAction(hudson.tasks.junit.TestResultAction.class)
if (testResults) {
def failCount = testResults.result.failCount
if (failCount > 0) {
error("${failCount} тестов упало. Сборка заблокирована.")
}
}
}
}
}
Упражнение: Создайте Jenkins-пайплайн для веб-приложения
Спроектируйте полный Jenkinsfile для веб-приложения со следующими требованиями:
- Приложение Node.js с React-фронтендом и Express-бэкендом
- Unit-тесты (Jest), API-тесты (Supertest) и E2E-тесты (Playwright)
- Тесты должны выполняться параллельно где возможно
- Деплой в staging после прохождения всех тестов
- Quality gate: ноль падений тестов и минимум 80% покрытия кода
Решение
pipeline {
agent { docker { image 'node:20-slim' } }
environment {
CI = 'true'
BASE_URL = 'https://staging.example.com'
}
stages {
stage('Install') {
steps {
sh 'npm ci'
}
}
stage('Lint & Type Check') {
steps {
sh 'npm run lint'
sh 'npm run type-check'
}
}
stage('Tests') {
parallel {
stage('Unit Tests') {
steps {
sh 'npm run test:unit -- --coverage --ci'
}
post {
always {
junit 'coverage/junit.xml'
publishCoverage adapters: [coberturaAdapter('coverage/cobertura-coverage.xml')]
}
}
}
stage('API Tests') {
steps {
sh 'npm run test:api'
}
post {
always {
junit 'api-test-results/junit.xml'
}
}
}
stage('E2E Tests') {
agent {
docker { image 'mcr.microsoft.com/playwright:v1.40.0-focal' }
}
steps {
sh 'npm ci'
sh 'npx playwright test'
}
post {
always {
junit 'test-results/junit.xml'
publishHTML([
reportDir: 'playwright-report',
reportFiles: 'index.html',
reportName: 'Отчёт Playwright'
])
archiveArtifacts artifacts: 'test-results/**', allowEmptyArchive: true
}
}
}
}
}
stage('Quality Gate') {
steps {
script {
def testResults = currentBuild.rawBuild.getAction(hudson.tasks.junit.TestResultAction.class)
if (testResults && testResults.result.failCount > 0) {
error("${testResults.result.failCount} тестов упало.")
}
}
}
}
stage('Deploy to Staging') {
when { branch 'main' }
steps {
sh './scripts/deploy-staging.sh'
}
}
}
post {
always {
cleanWs()
}
failure {
echo 'Пайплайн упал. Проверьте отчёты тестов выше.'
}
}
}
Популярные плагины Jenkins для QA
| Плагин | Назначение |
|---|---|
| JUnit | Парсинг и отображение результатов тестов |
| HTML Publisher | Публикация HTML-отчётов |
| Allure | Продвинутая агрегация отчётов тестов |
| Coverage | Визуализация покрытия кода |
| Pipeline Utility Steps | Операции с файлами, парсинг JSON |
| Docker Pipeline | Запуск этапов в Docker-контейнерах |
| Slack Notification | Отправка результатов сборки в Slack |
| Git | Управление исходным кодом |
| Credentials Binding | Безопасная инъекция секретов в сборки |
| Blue Ocean | Современный UI Jenkins с визуализацией пайплайна |
Лучшие практики Jenkins для QA
Всегда используйте декларативные Jenkinsfile, хранящиеся в репозитории. Никогда не настраивайте пайплайны через UI Jenkins — это не версионируется.
Держите выполнение пайплайна в пределах 30 минут. Если тесты занимают больше, параллелизуйте их или разделите на отдельные пайплайны (быстрый feedback + ночная полная регрессия).
Используйте Docker-агенты для консистентных тестовых окружений. Фиксируйте конкретные версии образов, чтобы избежать сюрпризов при обновлении.
Архивируйте тестовые артефакты при каждой сборке — не только при падениях. Исторические данные нужны для анализа тенденций.
Реализуйте корректную очистку с
cleanWs()в блокеpost { always }. Оставшиеся файлы от предыдущих сборок могут вызывать нестабильные тесты.Используйте shared libraries для общего кода пайплайнов. Если несколько проектов используют одинаковую настройку отчётности тестов, вынесите её в общую библиотеку.
Устранение типичных проблем
Тесты проходят локально, но падают в Jenkins
- Различие окружений: Используйте Docker-агенты для соответствия локальному окружению
- Отсутствующие зависимости: Убедитесь, что
npm ci(а неnpm install) запускается в CI - Проблемы с таймингом: CI-агенты могут быть медленнее; увеличьте таймауты для E2E-тестов
- Проблемы отображения: Headless-режим браузера может вести себя иначе; проверьте скриншоты
Пайплайн работает медленно
- Нет параллелизации: Разделите независимые тестовые наборы на параллельные этапы
- Нет кэширования: Используйте кэширование workspace Jenkins или кэширование слоёв Docker для node_modules
- Конкуренция за ресурсы: Убедитесь, что агенты имеют достаточно CPU/RAM для браузерных тестов
Нестабильные тесты в CI
- Общее состояние: Тесты, использующие общую БД или файлы, могут мешать друг другу
- Состояния гонки: Сетевые запросы могут падать по таймауту под нагрузкой CI
- Решение: Изолируйте тестовые данные, добавьте retry для сетезависимых операций, используйте
playwright test --retries=1