Тестирование в JavaScript: unit, integration, e2e от А до Я

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Тестирование в JavaScript: от модульных до сквозных тестов

Качественное тестирование — неотъемлемая часть профессиональной разработки на JavaScript. В этой статье мы разберём три основных уровня тестирования: модульные (unit), интеграционные (integration) и сквозные (e2e) тесты. Вы узнаете, какие инструменты использовать, как писать тесты на Node.js и как построить эффективную стратегию тестирования.

1. Unit-тестирование: основа пирамиды тестирования

Unit-тесты проверяют изолированные модули — функции, классы или отдельные методы. Главное правило: тестируемый код не должен зависеть от внешних ресурсов (базы данных, API, файловой системы).

Инструменты для unit-тестирования

  • Jest — самый популярный фреймворк от Facebook. Из коробки включает моки, снапшоты и покрытие кода.
  • Mocha + Chai — гибкая связка для тех, кто любит настраивать всё вручную.
  • Vitest — современный аналог Jest, оптимизированный для Vite-проектов.
// Пример unit-теста на Jest
const { calculateDiscount } = require('./pricing');

describe('calculateDiscount', () => {
  test('возвращает 10% скидку для суммы > 1000', () => {
    const result = calculateDiscount(1500);
    expect(result).toBe(1350);
  });

  test('не применяет скидку для суммы <= 1000', () => {
    const result = calculateDiscount(500);
    expect(result).toBe(500);
  });

  test('обрабатывает граничное значение 1000', () => {
    const result = calculateDiscount(1000);
    expect(result).toBe(1000);
  });
});

Лучшие практики unit-тестирования

  • Тестируйте одно поведение за раз (один assert на тест).
  • Используйте описательные названия тестов (given/when/then).
  • Избегайте тестирования приватных методов — тестируйте публичный интерфейс.
  • Поддерживайте покрытие кода на уровне 70-80%.

2. Integration-тестирование: проверка взаимодействия компонентов

Интеграционные тесты проверяют, как различные модули работают вместе. В контексте Node.js это обычно означает тестирование с реальной базой данных, файловой системой или внешними API.

Типичные сценарии интеграционного тестирования

  • Взаимодействие контроллера с сервисным слоем и базой данных.
  • Проверка middleware и маршрутов Express/Koa.
  • Тестирование репозиториев с тестовой БД (SQLite в памяти или PostgreSQL в Docker).
// Пример интеграционного теста с Supertest и Jest
const request = require('supertest');
const app = require('../app');
const { createTestUser, cleanDatabase } = require('./helpers');

beforeEach(async () => {
  await cleanDatabase();
});

describe('POST /api/users', () => {
  test('создаёт пользователя и возвращает 201', async () => {
    const response = await request(app)
      .post('/api/users')
      .send({ name: 'Иван', email: 'ivan@test.com' });

    expect(response.status).toBe(201);
    expect(response.body).toHaveProperty('id');
    expect(response.body.name).toBe('Иван');
  });

  test('возвращает 400 при дублировании email', async () => {
    await createTestUser({ email: 'ivan@test.com' });

    const response = await request(app)
      .post('/api/users')
      .send({ name: 'Петр', email: 'ivan@test.com' });

    expect(response.status).toBe(400);
    expect(response.body.error).toBe('Email уже используется');
  });
});

Настройка тестовой инфраструктуры

  • Docker Compose — для поднятия тестовых сервисов (БД, Redis).
  • Testcontainers — программное управление контейнерами из тестов.
  • In-memory базы данных (например, mongodb-memory-server) — для быстрых тестов без внешних зависимостей.

3. E2E-тестирование: проверка системы целиком

Сквозные (end-to-end) тесты имитируют действия реального пользователя. Они проверяют всю систему от интерфейса до базы данных. Для веб-приложений это означает запуск браузера и автоматизацию кликов, ввода данных и навигации.

Популярные инструменты для E2E

  • Cypress — современный инструмент с отличным UI, автоматическими ожиданиями и возможностью записи тестов.
  • Playwright — от Microsoft, поддерживает все браузеры (Chrome, Firefox, Safari) и мобильные эмуляторы.
  • Puppeteer — библиотека для управления Chromium, низкоуровневая, но гибкая.
// Пример E2E теста на Cypress
describe('Авторизация пользователя', () => {
  beforeEach(() => {
    cy.visit('http://localhost:3000/login');
  });

  it('успешный вход с корректными данными', () => {
    cy.get('[data-testid="email-input"]').type('user@example.com');
    cy.get('[data-testid="password-input"]').type('correct-password');
    cy.get('[data-testid="login-button"]').click();

    cy.url().should('include', '/dashboard');
    cy.contains('Добро пожаловать, User');
  });

  it('показывает ошибку при неверном пароле', () => {
    cy.get('[data-testid="email-input"]').type('user@example.com');
    cy.get('[data-testid="password-input"]').type('wrong-password');
    cy.get('[data-testid="login-button"]').click();

    cy.contains('Неверный email или пароль');
  });
});

Когда писать E2E тесты

  • Критически важные пользовательские сценарии (регистрация, оплата, поиск).
  • Регрессионное тестирование перед релизом.
  • Проверка интеграции с внешними сервисами (платёжные шлюзы, OAuth).

4. Стратегия тестирования: как всё совместить

Идеальная стратегия основывается на пирамиде тестирования, предложенной Майком Коном:

  • Основание (70%) — быстрые unit-тесты. Их должно быть много.
  • Середина (20%) — интеграционные тесты. Проверяют ключевые сценарии взаимодействия.
  • Вершина (10

Блоги

Рекомендаций по книгам