Тестирование в CI: стратегия и оптимизация
Тесты в CI — это страховка перед merge. Но медленный пайплайн замедляет всю команду. Параллелизация, кэширование, правильная пирамида тестов — ключ к быстрому и надёжному CI.
Почему это важно: Пайплайн длиной 30 минут означает, что разработчик ждёт полчаса, прежде чем может мержить. За день это несколько часов простоя на команду. Быстрый CI (< 5 минут) — прямое ускорение разработки.
Главная идея
Пирамида тестов: много быстрых unit-тестов, умеренное количество integration, минимум E2E. Параллелизация и кэширование сокращают время. Flaky-тесты — главный враг доверия к CI.
Как это выглядит на практике
- Пайплайн запускается: 500 тестов, текущее время — 20 минут
- Анализ: 80% времени занимают 50 E2E-тестов с реальной БД
- Оптимизация 1: кэширование зависимостей — сохраняем 2 минуты
- Оптимизация 2: параллельный запуск тестов на 4 runner'ах — 20 мин → 6 мин
- Оптимизация 3: разделение на fast (unit) и slow (E2E) jobs — unit за 1 мин, блокирует PR
- Результат: фидбек за 2 минуты (unit + lint), полный прогон за 6 минут
Примеры кода
Параллельные тесты в GitHub Actions
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
# Разбиваем тесты на 4 параллельных группы
ci_node_total: [4]
ci_node_index: [0, 1, 2, 3]
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Run tests (shard ${{ matrix.ci_node_index }})
env:
CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
CI_NODE_INDEX: ${{ matrix.ci_node_index }}
run: |
# Разбиваем файлы тестов по группам
TESTS=$(find spec -name '*_spec.rb' | sort | \
awk "NR % $CI_NODE_TOTAL == $CI_NODE_INDEX")
bundle exec rspec $TESTS
Fast и slow pipelines
# Быстрая проверка: 1-2 минуты, блокирует PR
jobs:
fast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with: { bundler-cache: true }
- run: bundle exec rubocop --parallel
- run: bundle exec rspec spec/models spec/services
# Только unit-тесты — быстро
# Полный прогон: 5-10 минут, не блокирует merge
full:
runs-on: ubuntu-latest
services:
postgres: { image: 'postgres:16', env: { POSTGRES_PASSWORD: pw } }
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with: { bundler-cache: true }
- run: bin/rails db:setup
- run: bundle exec rspec # Все тесты
Что происходит под капотом
- Параллелизация через matrix: каждый shard запускает свою часть тестов на отдельном runner'е
- bundler-cache/npm cache сохраняет зависимости между запусками — экономия 1–5 минут
- Flaky test: тест, который случайно падает (race condition, порядок запуска) — подрывает доверие к CI
- Test splitting по времени: продвинутые инструменты (knapsack, split-tests) распределяют тесты по времени, а не по количеству
- Required checks в GitHub: можно сделать fast обязательным для merge, full — информативным
Типичные ошибки и заблуждения
- «Больше E2E-тестов = надёжнее» — E2E медленные и flaky, unit-тесты быстрые и стабильные
- «Flaky-тесты можно просто перезапустить» — это маскирует проблему, нужно фиксить причину
- «CI должен запускать ВСЕ тесты» — для быстрого фидбека достаточно unit + lint, полный прогон можно делать фоново
Ключевые выводы
- Пирамида тестов: много unit → средне integration → мало E2E
- Параллелизация через matrix — линейное ускорение пайплайна
- Fast pipeline (< 2 мин) для быстрого фидбека, full pipeline для полной проверки
Термины урока
Связь с работой backend-разработчика
Инвестируйте в скорость CI: каждая минута ожидания умножается на количество разработчиков и PR в день. Быстрый фидбек (< 2 минут) меняет workflow: разработчики охотнее создают маленькие PR и чаще мержат.
Мини-разбор реальной ситуации
Команда из 8 человек: 600 тестов, CI занимал 25 минут. Разработчики начинали другие задачи во время ожидания и теряли контекст. После оптимизации: lint + unit (required, 90 секунд) + full suite (параллельно на 4 runner'ах, 4 минуты). Среднее время до merge сократилось с 2 часов до 20 минут.
Что запомнить
- Пирамида тестов: 70% unit, 20% integration, 10% E2E
- Параллелизация через matrix — самый простой способ ускорить CI
- Fast pipeline (обязательный, < 2 мин) + full pipeline (информативный, 5-10 мин)
Итог
Скорость CI — критическая метрика продуктивности команды. Пирамида тестов, параллелизация и разделение на fast/full pipelines позволяют получать фидбек за минуты, а не за десятки минут.
Комментарии к уроку
Войдите, чтобы оставить комментарий.
Пока нет комментариев — будьте первым.