Matrix testing — одна из самых мощных техник для обеспечения работы вашего приложения в различных окружениях, конфигурациях и платформах. В современных CI/CD pipelines matrix testing позволяет автоматически запускать один и тот же набор тестов в разных комбинациях переменных. Это комплексное руководство проведет вас через внедрение стратегий matrix testing, которые масштабируются вместе с вашим рабочим процессом разработки.
Что такое Matrix Testing?
Matrix testing, также известное как комбинаторное тестирование, — это техника, при которой вы запускаете тесты по нескольким измерениям конфигурационных переменных одновременно. Вместо того чтобы тестировать каждую конфигурацию отдельно, вы создаете матрицу всех возможных комбинаций и выполняете тесты для каждой перестановки.
Например, если вам нужно протестировать ваше приложение на:
- 3 операционных системах (Linux, macOS, Windows)
- 3 версиях языка программирования (Node.js 16, 18, 20)
- 2 версиях базы данных (PostgreSQL 13, 14)
Традиционное тестирование потребовало бы 18 отдельных ручных конфигураций. Matrix testing автоматизирует весь этот процесс, запуская все комбинации параллельно.
Предварительные требования
Перед внедрением matrix testing убедитесь, что у вас есть:
Необходимые инструменты:
- CI/CD платформа (GitHub Actions, GitLab CI, Jenkins или CircleCI)
- Система контроля версий (Git)
- Docker (опционально, но рекомендуется для воспроизводимых окружений)
- Базовые знания YAML для конфигурации CI
Технические знания:
- Понимание концепций CI/CD pipeline
- Знакомство с выбранной CI платформой
- Базовые навыки скриптинга (Bash, Python или JavaScript)
Настройка окружения:
- Доступ к вашему репозиторию с включенным CI/CD
- Соответствующие разрешения для изменения конфигураций pipeline
- Уже реализованный набор тестов
Шаг 1: Определите измерения вашей тестовой матрицы
Начните с выявления переменных, которые нужно тестировать с различными значениями. Общие измерения включают:
Инфраструктурные переменные:
- Операционные системы (ubuntu-latest, macos-latest, windows-latest)
- Архитектура (x86, ARM64)
- Облачные провайдеры (AWS, Azure, GCP)
Переменные приложения:
- Версии языка программирования
- Версии фреймворков
- Версии зависимостей
- Системы баз данных и версии
Конфигурационные переменные:
- Типы окружений (development, staging, production)
- Feature flags
- Endpoints интеграции
Создайте документ с перечислением критических измерений:
# matrix-config.yaml
dimensions:
os: [ubuntu-22.04, ubuntu-20.04, macos-13, windows-2022]
node_version: [16, 18, 20]
database: [postgres:13, postgres:14, postgres:15]
Контрольная точка: Проверьте ваши измерения с командой. Приоритизируйте комбинации, которые представляют реальные пользовательские окружения. Избегайте тестирования комбинаций, которые не существуют в production.
Шаг 2: Внедрите Matrix Testing в GitHub Actions
GitHub Actions предоставляет встроенную поддержку стратегии матрицы. Вот как это реализовать:
# .github/workflows/matrix-tests.yml
name: Matrix Testing
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
name: Test on ${{ matrix.os }} with Node ${{ matrix.node }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node: [16, 18, 20]
include:
# Добавьте специфичные комбинации с дополнительной конфигурацией
- os: ubuntu-latest
node: 20
experimental: true
exclude:
# Пропустите проблемные комбинации
- os: macos-latest
node: 16
fail-fast: false # Продолжайте тестирование других комбинаций, даже если одна упала
max-parallel: 5 # Ограничьте одновременные задачи
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
flags: ${{ matrix.os }}-node-${{ matrix.node }}
Ожидаемый результат: Эта конфигурация создает 8 задач (3 OS × 3 версии Node - 1 исключенная комбинация). Каждая задача выполняется независимо, и вы увидите результаты для каждой комбинации в UI GitHub Actions.
Шаг 3: Реализуйте продвинутую матрицу с сервисами баз данных
Приложения реального мира часто требуют тестирования с различными базами данных. Вот как добавить сервисные контейнеры в вашу матрицу:
name: Matrix with Database Testing
jobs:
integration-test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [18, 20]
database:
- type: postgres
version: '13'
port: 5432
- type: postgres
version: '14'
port: 5432
- type: mysql
version: '8.0'
port: 3306
services:
database:
image: ${{ matrix.database.type }}:${{ matrix.database.version }}
env:
POSTGRES_PASSWORD: testpass
MYSQL_ROOT_PASSWORD: testpass
ports:
- ${{ matrix.database.port }}:${{ matrix.database.port }}
options: >-
--health-cmd="pg_isready"
--health-interval=10s
--health-timeout=5s
--health-retries=5
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- name: Configure database connection
run: |
echo "DATABASE_TYPE=${{ matrix.database.type }}" >> $GITHUB_ENV
echo "DATABASE_PORT=${{ matrix.database.port }}" >> $GITHUB_ENV
- name: Run integration tests
run: npm run test:integration
env:
DATABASE_URL: ${{ matrix.database.type }}://user:testpass@localhost:${{ matrix.database.port }}/testdb
Контрольная точка: Запустите этот workflow и проверьте, что каждый сервис базы данных стартует корректно. Проверьте логи, чтобы убедиться, что соединения с базой данных установлены до запуска тестов.
Шаг 4: Оптимизируйте выполнение матрицы с динамическими матрицами
Для больших матриц вы можете генерировать комбинации динамически для снижения избыточности:
jobs:
prepare-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- name: Generate dynamic matrix
id: set-matrix
run: |
# Генерируйте матрицу на основе измененных файлов или условий
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
# Ограниченная матрица для PR
echo 'matrix={"os":["ubuntu-latest"],"node":[20]}' >> $GITHUB_OUTPUT
else
# Полная матрица для ветки main
echo 'matrix={"os":["ubuntu-latest","macos-latest","windows-latest"],"node":[16,18,20]}' >> $GITHUB_OUTPUT
fi
test:
needs: prepare-matrix
runs-on: ${{ matrix.os }}
strategy:
matrix: ${{ fromJson(needs.prepare-matrix.outputs.matrix) }}
steps:
- uses: actions/checkout@v4
- name: Run tests
run: echo "Testing on ${{ matrix.os }} with Node ${{ matrix.node }}"
Ожидаемый результат: Pull requests будут запускать только 1 задачу, в то время как pushes в main будут запускать полную матрицу из 9 задач. Это значительно снижает затраты и время CI для рутинной разработки.
Шаг 5: Внедрите Matrix Testing в GitLab CI
GitLab CI использует параллельные задачи для matrix testing:
# .gitlab-ci.yml
.test_template:
stage: test
script:
- npm ci
- npm test
test:
extends: .test_template
image: node:${NODE_VERSION}
parallel:
matrix:
- NODE_VERSION: ['16', '18', '20']
OS: ['ubuntu', 'alpine']
DATABASE:
- TYPE: 'postgres'
VERSION: '13'
- TYPE: 'postgres'
VERSION: '14'
services:
- name: ${DATABASE_TYPE}:${DATABASE_VERSION}
alias: database
variables:
DATABASE_URL: "${DATABASE_TYPE}://user:pass@database:5432/testdb"
before_script:
- echo "Testing Node ${NODE_VERSION} on ${OS} with ${DATABASE_TYPE} ${DATABASE_VERSION}"
Контрольная точка: GitLab создаст 12 задач (3 версии Node × 2 OS × 2 версии базы данных). Проверьте граф pipeline для визуализации всех комбинаций.
Шаг 6: Добавьте Matrix Testing для Jenkins
Jenkins требует более программного подхода с использованием Groovy:
// Jenkinsfile
pipeline {
agent none
stages {
stage('Matrix Build') {
matrix {
axes {
axis {
name 'OS'
values 'linux', 'windows', 'mac'
}
axis {
name 'NODE_VERSION'
values '16', '18', '20'
}
axis {
name 'DATABASE'
values 'postgres:13', 'postgres:14', 'mysql:8.0'
}
}
excludes {
exclude {
axis {
name 'OS'
values 'mac'
}
axis {
name 'NODE_VERSION'
values '16'
}
}
}
stages {
stage('Test') {
agent {
docker {
image "node:${NODE_VERSION}"
label "${OS}"
}
}
steps {
sh 'npm ci'
sh 'npm test'
}
}
}
}
}
}
post {
always {
publishHTML([
reportDir: 'coverage',
reportFiles: 'index.html',
reportName: "Coverage Report - ${OS}-${NODE_VERSION}-${DATABASE}"
])
}
}
}
Ожидаемый результат: Jenkins создает визуальную матрицу со всеми комбинациями, позволяя вам углубиться в конкретные результаты тестов для каждой конфигурации.
Шаг 7: Внедрите умное Matrix Testing с кэшированием
Оптимизируйте время выполнения матрицы, используя эффективные стратегии кэширования:
name: Optimized Matrix Testing
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
node: [18, 20]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: 'npm'
- name: Cache node modules
uses: actions/cache@v3
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ matrix.node }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ matrix.node }}-
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci
- name: Cache build artifacts
uses: actions/cache@v3
with:
path: dist
key: ${{ runner.os }}-build-${{ matrix.node }}-${{ github.sha }}
- name: Run tests
run: npm test
Контрольная точка: Мониторьте время выполнения вашего workflow. Правильно настроенное кэширование должно сократить время выполнения на 30-50% при последующих запусках.
Лучшие практики для Matrix Testing
1. Приоритизируйте критические комбинации
Не все комбинации одинаково важны. Используйте приоритизацию на основе данных:
strategy:
matrix:
include:
# Критичные production конфигурации (высший приоритет)
- os: ubuntu-latest
node: 20
priority: critical
# Общие пользовательские конфигурации
- os: ubuntu-latest
node: 18
priority: high
# Граничные случаи и будущая совместимость
- os: macos-latest
node: 20
priority: medium
2. Используйте Fail-Fast стратегически
Контролируйте, как сбои матрицы влияют на ваш pipeline:
strategy:
fail-fast: false # Тестируйте все комбинации, даже если некоторые упали
matrix:
# ... конфигурация матрицы
Установите fail-fast: true когда:
- Работаете с ограниченными CI ресурсами
- Тестируете критические функции, где один сбой указывает на системные проблемы
- Отлаживаете конкретные комбинации
Установите fail-fast: false когда:
- Исследуете платформо-специфичные проблемы
- Генерируете комплексные отчеты о совместимости
- Некоторые комбинации известны как нестабильные
3. Реализуйте сбор артефактов матрицы
Собирайте и организуйте результаты тестов из всех комбинаций матрицы:
steps:
- name: Run tests
run: npm test -- --coverage
- name: Upload test results
uses: actions/upload-artifact@v3
if: always()
with:
name: test-results-${{ matrix.os }}-node-${{ matrix.node }}
path: |
coverage/
test-results/
retention-days: 30
- name: Generate matrix report
if: always()
run: |
echo "## Test Results: ${{ matrix.os }} - Node ${{ matrix.node }}" >> $GITHUB_STEP_SUMMARY
echo "Status: ${{ job.status }}" >> $GITHUB_STEP_SUMMARY
echo "$(cat test-results/summary.txt)" >> $GITHUB_STEP_SUMMARY
4. Мониторьте производительность матрицы
Отслеживайте метрики выполнения матрицы для оптимизации затрат и времени:
- name: Report matrix metrics
run: |
echo "Matrix combination: ${{ matrix.os }}-${{ matrix.node }}"
echo "Start time: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
npm test
echo "End time: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "Status: ${{ job.status }}"
Используйте эти метрики для выявления:
- Самых медленных комбинаций, нуждающихся в оптимизации
- Часто падающих конфигураций
- Избыточных или ненужных измерений матрицы
Распространенные ошибки и решения
Ошибка 1: Взрыв матрицы
Проблема: Слишком много измерений создают сотни комбинаций, перегружая CI ресурсы.
Решение: Используйте стратегические исключения и условные матрицы:
strategy:
matrix:
os: [ubuntu, macos, windows]
node: [16, 18, 20]
database: [postgres, mysql, mongodb]
# Это создает 27 комбинаций!
exclude:
# Удалите маловероятные production комбинации
- os: windows
database: mongodb
- os: macos
node: 16
# Теперь сокращено до 23 комбинаций
Ошибка 2: Конкуренция за ресурсы
Проблема: Все задачи матрицы стартуют одновременно, вызывая истощение ресурсов или достижение лимитов.
Решение: Внедрите контролируемый параллелизм:
strategy:
max-parallel: 4 # Ограничьте одновременные задачи
matrix:
# ... конфигурация
Ошибка 3: Несогласованные тестовые окружения
Проблема: Тесты проходят в некоторых комбинациях матрицы, но падают в других из-за различий окружения.
Решение: Используйте Docker для согласованных окружений:
jobs:
test:
runs-on: ${{ matrix.os }}
container:
image: node:${{ matrix.node }}
options: --user root
strategy:
matrix:
os: [ubuntu-latest]
node: [16, 18, 20]
Инструменты и ресурсы
Рекомендуемые инструменты
| Инструмент | Случай использования | Плюсы | Минусы |
|---|---|---|---|
| GitHub Actions | Matrix testing общего назначения | Встроенная поддержка матрицы, хороший UI, бесплатно для публичных репозиториев | Ограничено GitHub |
| GitLab CI | Корпоративные окружения | Self-hosted опция, интегрировано с GitLab | Кривая обучения для синтаксиса матрицы |
| Jenkins | Legacy системы | Высоко кастомизируемый, экосистема плагинов | Сложная настройка, многословный синтаксис |
| CircleCI | Docker-тяжелые workflows | Отличная Docker поддержка, параллелизм | Стоимость может быть высокой для больших матриц |
Важные ресурсы
- GitHub Actions Matrix Strategy Documentation
- GitLab CI Parallel Matrix Jobs
- Jenkins Matrix Project Plugin
Заключение
Matrix testing трансформирует ваш CI/CD pipeline из тестирования отдельных конфигураций в комплексную кросс-платформенную валидацию. Внедряя стратегии из этого руководства, вы можете:
- Автоматически тестировать все критические комбинации платформ
- Обнаруживать окружение-специфичные баги рано
- Сокращать нагрузку ручного тестирования на 70-80%
- Строить уверенность в кросс-платформенной совместимости
Ключевые выводы:
- Начинайте с минимальной матрицы и расширяйте на основе реальных сбоев
- Используйте динамические матрицы для оптимизации затрат и времени выполнения
- Приоритизируйте критические комбинации над исчерпывающим покрытием
- Мониторьте и постоянно улучшайте производительность матрицы
Следующие шаги:
- Внедрите базовую матрицу для вашего наиболее критичного набора тестов
- Мониторьте выполнение матрицы в течение 2-3 недель и собирайте метрики
- Расширяйте измерения матрицы на основе production проблем
- Рассмотрите внедрение параллельного выполнения тестов для еще более быстрых результатов
Matrix testing — это не просто о запуске большего количества тестов, это о запуске правильных тестов в правильное время на конфигурациях, которые наиболее важны для ваших пользователей.