Почему 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, который:

  1. Запускает unit-тесты при каждом push
  2. Запускает E2E-тесты в 3 браузерах на pull requests
  3. Загружает тестовые отчёты как артефакты
  4. Публикует результаты тестов как check в PR
  5. Запускает ночную полную регрессию
Решение
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 ActionsJenkins
НастройкаНулевая настройка для GitHub-репозиториевТребует установки и обслуживания сервера
СтоимостьБесплатно для публичных репо; платные минуты для приватныхБесплатно, но платите за серверы
ГибкостьХорошая с actions из marketplaceМаксимальная с 1800+ плагинами
Поддержка контейнеровНативные Docker и service containersЧерез плагин Docker Pipeline
Интеграция с PRНативная — checks, статусы, комментарииТребует плагинов и webhook-ов
Self-hosted runnersПоддерживаетсяОсновная функциональность
Matrix buildsПервоклассная через strategy.matrixТребует scripted pipeline
Управление секретамиВстроенные секреты репозитория/организацииПлагин Credentials

Лучшие практики

  1. Используйте actions/checkout@v4 с fetch-depth: 0, если тесты зависят от git-истории (для обнаружения изменений или blame).

  2. Устанавливайте fail-fast: false в matrix-стратегиях для тестовых jobs. Вы хотите видеть все падения, а не только первое.

  3. Кэшируйте агрессивно — npm-зависимости, браузеры Playwright и любые другие загружаемые ресурсы.

  4. Используйте continue-on-error: true на тестовых шагах в сочетании с if: always() при загрузке артефактов. Это гарантирует доступность тестовых отчётов.

  5. Фиксируйте версии actions по конкретным SHA-хешам в продакшене, а не только по мажорным версиям. Это предотвращает атаки на цепочку поставок.

  6. Используйте группы concurrency для отмены устаревших запусков при новом push:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true