Как было устроено тестирование на последнем проекте со стороны CI/CD?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как было устроено тестирование на последнем проекте со стороны CI/CD
На последнем проекте (PrepBro - платформа подготовки к IT-собеседованиям) мы использовали полностью автоматизированный pipeline с Jest, Playwright и GitHub Actions.
1. Архитектура CI/CD Pipeline
Инструменты:
- GitHub Actions - оркестрация пайплайна
- Vitest - unit тесты (быстрее Jest)
- Testing Library - тесты компонентов
- Playwright MCP - E2E тесты
- ESLint + Prettier - code quality
- Next.js - фреймворк с встроенной оптимизацией
2. Этапы Pipeline
Этап 1: Lint & Format
# Проверяем код на соответствие стандартам
npm run lint
npm run type-check
# Проверяем форматирование (Prettier)
npm run format:check
Литинг запускается первым - самое быстрое, выявляет синтаксические ошибки.
Этап 2: Unit Tests
# Тесты компонентов через Vitest + Testing Library
npm run test:run -- --coverage
# Требование: coverage >= 90%
# Если ниже - PR не может быть merged
Если coverage меньше порога, pipeline падает.
Этап 3: Build Проверка
# Проверяем, что код компилируется
npm run build
# Проверяем bundle size
Это выявляет проблемы на этапе сборки (несовместимые зависимости, неправильные импорты).
Этап 4: E2E Tests (на staging)
# Запускаем Playwright тесты
npm run test:e2e
# Проверяем:
# - Авторизация пользователей
# - Основные user flows
# - Навигация между страницами
# - Формы и инпуты
# - Интеграция с API
3. GitHub Actions Workflow
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Lint code
run: npm run lint
- name: Type check
run: npm run type-check
- name: Unit tests
run: npm run test:run -- --coverage
- name: Build
run: npm run build
- name: Archive build
uses: actions/upload-artifact@v3
with:
name: build
path: .next
e2e:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install Playwright
run: npx playwright install
- name: E2E tests
run: npm run test:e2e
env:
BASE_URL: https://staging.prepbro.ru
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v3
with:
name: playwright-report
path: test-results/
4. Требования для PR
PR не может быть merged, если:
- Не прошёл lint (ошибки в коде)
- Не прошли unit тесты (падающие тесты)
- Coverage < 90% (недостаточное тестовое покрытие)
- Не собирается проект (npm run build ошибка)
- E2E тесты падают
Все проверки должны быть зелёными перед merge.
5. Unit Testing - Best Practices
// Тест компонента
describe('Button Component', () => {
it('should render with correct text', () => {
const { getByRole } = render(<Button>Click me</Button>);
const button = getByRole('button');
expect(button).toHaveTextContent('Click me');
});
it('should call onClick when clicked', () => {
const mockClick = jest.fn();
const { getByRole } = render(
<Button onClick={mockClick}>Click</Button>
);
fireEvent.click(getByRole('button'));
expect(mockClick).toHaveBeenCalledTimes(1);
});
});
// Запуск тестов
npm run test:run -- --coverage --reporter=verbose
6. E2E Testing с Playwright
// Тест юзер-флоу
import { test, expect } from '@playwright/test';
test.describe('User Authentication', () => {
test('should login successfully', async ({ page }) => {
// 1. Navigare to login page
await page.goto('/auth/login');
// 2. Fill form
await page.fill('input[name="email"]', 'test@example.com');
await page.fill('input[name="password"]', 'password123');
// 3. Submit
await page.click('button[type="submit"]');
// 4. Check redirection
await page.waitForURL('/dashboard');
expect(page.url()).toContain('/dashboard');
});
});
7. Coverage Report
После каждого прогона тестов:
Stmts : 92.5% (185/200)
Branch : 88.3% (52/59)
Funcs : 94.1% (97/103)
Lines : 92.1% (184/200)
Если падает ниже 90% - PR блокируется.
8. Кеширование зависимостей
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
Это ускоряет установку зависимостей в 10+ раз.
9. Времена выполнения
- Lint: 30-45 сек
- Type check: 15-20 сек
- Unit tests: 2-3 минуты
- Build: 1-2 минуты
- E2E tests: 5-7 минут
- Итого: ~12-15 минут
10. Бранчинг стратегия
main (production ready):
- Выполняются все checks
- E2E тесты на production staging
- Требуется 2 approvals перед merge
develop (development):
- Все checks выполняются
- E2E на development staging
- Требуется 1 approval
feature/ (feature branches):
- Lint + Unit тесты (быстро)
- E2E пропускаются до merge в develop
11. Fail-fast стратегия
Если тест падает на ранних этапах:
jobs:
test:
if: success() # Запускается только если предыдущие успешны
e2e:
needs: test
if: success() # Зависит от теста
Это экономит время - не запускаем дорогие E2E, если unit тесты падают.
12. Интеграция с GitHub
- Статус чеков видна в PR
- Блокировка merge-кнопки при ошибках
- Slack нотификации о падении пайплайна
- Auto-dismiss review если был push новых коммитов
Выводы
Автоматизированный CI/CD pipeline обеспечивает:
- Качество кода - линтинг, типизация
- Корректность - unit + E2E тесты
- Скорость - параллельное выполнение, кеширование
- Надёжность - проверка на staging перед production
- Стабильность - требование >= 90% coverage
Это позволяет командиме безопасно деплоить несколько раз в день с уверенностью, что код работает корректно.