Почему GitHub Actions для QA
GitHub Actions — встроенная CI/CD-платформа GitHub. Если ваш проект живёт на GitHub, Actions устраняет необходимость во внешних CI/CD-сервисах. Воркфлоу запускаются непосредственно внутри GitHub с тесной интеграцией в pull requests, issues и экосистему GitHub.
Для QA-инженеров эта тесная интеграция — большое преимущество. Результаты тестов отображаются прямо в pull requests. Упавшие проверки блокируют мержи. Тестовые артефакты доступны из того же интерфейса, где вы ревьюите код.
Основы воркфлоу
Воркфлоу GitHub Actions — это YAML-файл в .github/workflows/. Вот минимальный воркфлоу, запускающий тесты при каждом push:
name: Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm test
Триггеры
GitHub Actions поддерживает множество событий-триггеров:
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * *' # Ежедневно в 6:00 UTC
workflow_dispatch: # Ручной запуск из UI
Для QA наиболее важные триггеры:
- pull_request: Запуск тестов на каждом PR для обнаружения проблем до мержа
- push в main: Полная регрессия после мержа для проверки основной ветки
- schedule: Ночные полные тестовые наборы, тесты производительности или сканирования безопасности
Jobs и Steps
Воркфлоу содержит один или несколько jobs. Каждый job запускается на чистой виртуальной машине (runner). Jobs запускаются параллельно по умолчанию, но могут зависеть друг от друга:
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run test:unit
e2e-tests:
needs: unit-tests # Запускается после завершения unit-tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
Matrix-стратегия для кросс-браузерного тестирования
Matrix-стратегии — одна из самых мощных функций GitHub Actions для QA. Они позволяют запускать один набор тестов на множестве конфигураций автоматически:
jobs:
e2e-tests:
strategy:
matrix:
browser: [chromium, firefox, webkit]
os: [ubuntu-latest, windows-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx playwright install --with-deps ${{ matrix.browser }}
- run: npx playwright test --project=${{ matrix.browser }}
Это создаёт 6 параллельных jobs (3 браузера x 2 ОС). Настройка fail-fast: false гарантирует, что все комбинации выполнятся, даже если одна упадёт — вы хотите знать обо всех падениях, а не только о первом.
Шардинг больших тестовых наборов
Для больших тестовых наборов можно разделить тесты между несколькими runners:
jobs:
e2e-tests:
strategy:
matrix:
shard: [1, 2, 3, 4]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test --shard=${{ matrix.shard }}/4
Это разделяет тестовый набор на 4 равные части, выполняемые параллельно. 40-минутный набор становится 10-минутным.
Артефакты и тестовые отчёты
Загрузка тестовых артефактов
Сохраняйте тестовые отчёты, скриншоты и видео из тестовых запусков:
- name: Запуск E2E-тестов
run: npx playwright test
continue-on-error: true
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: |
playwright-report/
test-results/
retention-days: 14
Условие if: always() гарантирует загрузку артефактов даже при падении тестов — именно тогда они нужны больше всего.
Публикация результатов тестов в PR
Используйте сторонние actions для публикации результатов как комментариев к PR:
- name: Публикация результатов
uses: dorny/test-reporter@v1
if: always()
with:
name: Тесты Playwright
path: test-results/junit.xml
reporter: java-junit
Это создаёт check run с подробными результатами тестов, видимыми непосредственно в pull request.
Кэширование для ускорения сборок
Кэширование зависимостей радикально сокращает время пайплайна:
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
# Для браузеров Playwright
- name: Кэширование браузеров Playwright
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- name: Установка Playwright
run: npx playwright install --with-deps
Без кэширования npm ci и установка браузеров могут занять 2-3 минуты. С кэшем — секунды.
Секреты и переменные окружения
jobs:
test:
runs-on: ubuntu-latest
env:
BASE_URL: https://staging.example.com
NODE_ENV: test
steps:
- run: npm run test:e2e
env:
API_KEY: ${{ secrets.STAGING_API_KEY }}
DB_URL: ${{ secrets.TEST_DATABASE_URL }}
Секреты настраиваются в параметрах репозитория (Settings > Secrets and variables > Actions). Они маскируются в логах и никогда не раскрываются в файлах воркфлоу.
Упражнение: Создайте полный QA-воркфлоу
Создайте воркфлоу GitHub Actions, который:
- Запускает unit-тесты при каждом push
- Запускает E2E-тесты в 3 браузерах на pull requests
- Загружает тестовые отчёты как артефакты
- Публикует результаты тестов как check в PR
- Запускает ночную полную регрессию
Решение
name: QA Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 2 * * *'
workflow_dispatch:
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm run test:unit -- --coverage --ci
- uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-report
path: coverage/
retention-days: 7
e2e-tests:
if: github.event_name == 'pull_request' || github.event_name == 'schedule'
needs: unit-tests
strategy:
matrix:
browser: [chromium, firefox, webkit]
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- name: Кэш Playwright
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: pw-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- run: npx playwright install --with-deps ${{ matrix.browser }}
- run: npx playwright test --project=${{ matrix.browser }}
env:
BASE_URL: ${{ secrets.STAGING_URL }}
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-${{ matrix.browser }}
path: |
playwright-report/
test-results/
retention-days: 14
- name: Отчёт о тестах
uses: dorny/test-reporter@v1
if: always()
with:
name: E2E ${{ matrix.browser }}
path: test-results/junit.xml
reporter: java-junit
nightly-regression:
if: github.event_name == 'schedule'
needs: e2e-tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm run test:regression
- run: npm run test:performance
Переиспользуемые воркфлоу
Если нескольким репозиториям нужен одинаковый тестовый пайплайн, создайте переиспользуемые воркфлоу:
# .github/workflows/reusable-e2e.yml
name: Переиспользуемые E2E-тесты
on:
workflow_call:
inputs:
base-url:
required: true
type: string
browsers:
required: false
type: string
default: '["chromium"]'
secrets:
api-key:
required: true
jobs:
e2e:
strategy:
matrix:
browser: ${{ fromJson(inputs.browsers) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx playwright test --project=${{ matrix.browser }}
env:
BASE_URL: ${{ inputs.base-url }}
API_KEY: ${{ secrets.api-key }}
GitHub Actions vs Jenkins: перспектива QA
| Аспект | GitHub Actions | Jenkins |
|---|---|---|
| Настройка | Нулевая настройка для GitHub-репозиториев | Требует установки и обслуживания сервера |
| Стоимость | Бесплатно для публичных репо; платные минуты для приватных | Бесплатно, но платите за серверы |
| Гибкость | Хорошая с actions из marketplace | Максимальная с 1800+ плагинами |
| Поддержка контейнеров | Нативные Docker и service containers | Через плагин Docker Pipeline |
| Интеграция с PR | Нативная — checks, статусы, комментарии | Требует плагинов и webhook-ов |
| Self-hosted runners | Поддерживается | Основная функциональность |
| Matrix builds | Первоклассная через strategy.matrix | Требует scripted pipeline |
| Управление секретами | Встроенные секреты репозитория/организации | Плагин Credentials |
Лучшие практики
Используйте
actions/checkout@v4сfetch-depth: 0, если тесты зависят от git-истории (для обнаружения изменений или blame).Устанавливайте
fail-fast: falseв matrix-стратегиях для тестовых jobs. Вы хотите видеть все падения, а не только первое.Кэшируйте агрессивно — npm-зависимости, браузеры Playwright и любые другие загружаемые ресурсы.
Используйте
continue-on-error: trueна тестовых шагах в сочетании сif: always()при загрузке артефактов. Это гарантирует доступность тестовых отчётов.Фиксируйте версии actions по конкретным SHA-хешам в продакшене, а не только по мажорным версиям. Это предотвращает атаки на цепочку поставок.
Используйте группы concurrency для отмены устаревших запусков при новом push:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true