PurpleSchool — курсы программирования онлайн
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • AI для кодаНовое
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    Тестирование API: от unit-тестов до e2e с Playwright и Vitest

    Тестирование API: от unit-тестов до e2e с Playwright и Vitest

    Аватар автора Тестирование API: от unit-тестов до e2e с Playwright и Vitest

    Антон Ларичев

    Иконка календаря13 апреля 2026
    testingnodejstypescriptmiddleИконка уровня middle
    Картинка поста Тестирование API: от unit-тестов до e2e с Playwright и Vitest

    Введение

    Тестирование API — обязательная практика для любого проекта, который работает с серверной логикой. Без тестов вы узнаете о сломанном эндпоинте только от пользователей, а не на этапе разработки. Современный стек из Vitest и Playwright позволяет покрыть весь спектр: от быстрых unit-тестов отдельных функций до полноценных e2e-сценариев, проверяющих API от запроса до ответа.

    В этой статье разберём, как выстроить стратегию тестирования API на практике. Начнём с unit-тестов бизнес-логики в Vitest, перейдём к интеграционным тестам с моками через MSW и закончим e2e-тестами реального API с помощью Playwright. Каждый уровень — с примерами кода на TypeScript.

    Unit-тесты для API-логики в Vitest

    Unit-тесты проверяют отдельные функции в изоляции. Для API это валидаторы, трансформеры данных, middleware и бизнес-логика обработчиков.

    Настройка Vitest для проекта

    Установите Vitest и запустите первый тест:

    npm install -D vitest
    

    Добавьте скрипт в package.json:

    {
      "scripts": {
        "test": "vitest",
        "test:run": "vitest run"
      }
    }
    

    Как писать unit-тесты для валидации запросов

    Допустим, у вас есть функция валидации тела запроса:

    // src/validators/user.ts
    export function validateCreateUser(body: unknown): { valid: boolean; errors: string[] } {
      const errors: string[] = [];
      if (!body || typeof body !== 'object') {
        return { valid: false, errors: ['Тело запроса должно быть объектом'] };
      }
      const data = body as Record<string, unknown>;
      if (!data.email || typeof data.email !== 'string') {
        errors.push('Email обязателен');
      }
      if (!data.name || typeof data.name !== 'string' || (data.name as string).length < 2) {
        errors.push('Имя должно содержать минимум 2 символа');
      }
      return { valid: errors.length === 0, errors };
    }
    

    Тест для этой функции:

    // src/validators/user.test.ts
    import { describe, it, expect } from 'vitest';
    import { validateCreateUser } from './user';
    
    describe('validateCreateUser', () => {
      it('принимает корректные данные', () => {
        const result = validateCreateUser({ email: 'test@mail.com', name: 'Иван' });
        expect(result.valid).toBe(true);
        expect(result.errors).toHaveLength(0);
      });
    
      it('отклоняет пустое тело запроса', () => {
        const result = validateCreateUser(null);
        expect(result.valid).toBe(false);
        expect(result.errors).toContain('Тело запроса должно быть объектом');
      });
    
      it('требует email и имя', () => {
        const result = validateCreateUser({ email: '', name: 'A' });
        expect(result.valid).toBe(false);
        expect(result.errors.length).toBeGreaterThanOrEqual(1);
      });
    });
    

    Unit-тесты в Vitest запускаются за миллисекунды. Это ваша первая линия защиты от регрессий.

    Интеграционные тесты API с моками HTTP-запросов

    Интеграционные тесты проверяют взаимодействие нескольких модулей. Для тестирования API без реального сервера используют Mock Service Worker (MSW), который перехватывает HTTP-запросы на сетевом уровне.

    Настройка MSW с Vitest

    npm install -D msw
    

    Создайте обработчики моков:

    // src/mocks/handlers.ts
    import { http, HttpResponse } from 'msw';
    
    export const handlers = [
      http.get('/api/users/:id', ({ params }) => {
        const { id } = params;
        return HttpResponse.json({
          id: Number(id),
          name: 'Тестовый пользователь',
          email: 'test@example.com',
        });
      }),
    
      http.post('/api/users', async ({ request }) => {
        const body = await request.json();
        return HttpResponse.json({ id: 1, ...body }, { status: 201 });
      }),
    ];
    

    Подключите MSW в тестах:

    // src/services/api.test.ts
    import { describe, it, expect, beforeAll, afterAll } from 'vitest';
    import { setupServer } from 'msw/node';
    import { handlers } from '../mocks/handlers';
    
    const server = setupServer(...handlers);
    
    beforeAll(() => server.listen());
    afterAll(() => server.close());
    
    describe('API клиент', () => {
      it('получает пользователя по ID', async () => {
        const response = await fetch('/api/users/1');
        const data = await response.json();
    
        expect(response.status).toBe(200);
        expect(data.name).toBe('Тестовый пользователь');
      });
    
      it('создаёт нового пользователя', async () => {
        const response = await fetch('/api/users', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ name: 'Новый', email: 'new@test.com' }),
        });
        const data = await response.json();
    
        expect(response.status).toBe(201);
        expect(data.name).toBe('Новый');
      });
    });
    

    MSW работает на уровне сетевого стека, поэтому ваш код использует настоящий fetch — моки прозрачны для тестируемого кода.

    E2E-тестирование API с Playwright

    E2E-тесты проверяют реальный API на работающем сервере. Playwright предоставляет встроенный APIRequestContext для отправки HTTP-запросов без браузера.

    Настройка Playwright для тестирования API

    npm install -D @playwright/test
    

    Создайте конфигурацию:

    // playwright.config.ts
    import { defineConfig } from '@playwright/test';
    
    export default defineConfig({
      use: {
        baseURL: 'http://localhost:3000',
      },
      projects: [
        {
          name: 'api-tests',
          testDir: './tests/api',
        },
      ],
    });
    

    Как тестировать REST API эндпоинты в Playwright

    // tests/api/users.spec.ts
    import { test, expect } from '@playwright/test';
    
    test.describe('Users API', () => {
      let createdUserId: number;
    
      test('POST /api/users — создание пользователя', async ({ request }) => {
        const response = await request.post('/api/users', {
          data: {
            name: 'Playwright User',
            email: 'playwright@test.com',
          },
        });
    
        expect(response.status()).toBe(201);
        const body = await response.json();
        expect(body.id).toBeDefined();
        expect(body.name).toBe('Playwright User');
        createdUserId = body.id;
      });
    
      test('GET /api/users/:id — получение пользователя', async ({ request }) => {
        const response = await request.get(`/api/users/${createdUserId}`);
    
        expect(response.status()).toBe(200);
        const body = await response.json();
        expect(body.email).toBe('playwright@test.com');
      });
    
      test('DELETE /api/users/:id — удаление пользователя', async ({ request }) => {
        const response = await request.delete(`/api/users/${createdUserId}`);
        expect(response.status()).toBe(200);
    
        // Проверяем, что пользователь действительно удалён
        const check = await request.get(`/api/users/${createdUserId}`);
        expect(check.status()).toBe(404);
      });
    });
    

    Playwright выполняет реальные HTTP-запросы к серверу, проверяя полный цикл обработки: роутинг, middleware, базу данных и ответ.

    Тестирование авторизации и заголовков

    test('защищённый эндпоинт без токена возвращает 401', async ({ request }) => {
      const response = await request.get('/api/admin/stats');
      expect(response.status()).toBe(401);
    });
    
    test('защищённый эндпоинт с токеном возвращает данные', async ({ request }) => {
      const response = await request.get('/api/admin/stats', {
        headers: {
          Authorization: 'Bearer test-jwt-token',
        },
      });
      expect(response.status()).toBe(200);
    });
    

    Частые ошибки при тестировании API

    Тестирование только happy path. Проверяйте не только успешные сценарии, но и ошибки: невалидные данные, отсутствующие ресурсы, таймауты. E2e-тесты без негативных сценариев дают ложную уверенность.

    Зависимость между тестами. Каждый тест должен работать независимо. Если один тест создаёт данные для другого, используйте beforeEach для подготовки состояния.

    Отсутствие тестов на контракт. Проверяйте структуру ответа, а не только статус-код. Если API возвращает 200, но с неправильным форматом — это баг.

    Игнорирование таймаутов. В e2e-тестах всегда задавайте разумные таймауты. Playwright позволяет настроить их глобально и для отдельных запросов.

    Стратегия: какие тесты писать для API

    Оптимальная пирамида тестирования API:

    • Unit-тесты (70%) — Vitest: валидаторы, трансформеры, утилиты, бизнес-логика. Быстрые, дешёвые, запускаются на каждый коммит.
    • Интеграционные (20%) — Vitest + MSW: взаимодействие модулей, API-клиенты, обработка ответов. Средняя скорость, проверяют контракты.
    • E2E (10%) — Playwright: критические пользовательские сценарии, авторизация, CRUD-операции. Медленные, но проверяют реальную систему.

    Такое распределение обеспечивает быструю обратную связь от unit-тестов и надёжность от e2e, не замедляя CI/CD пайплайн.

    Заключение

    Тестирование API не требует одного инструмента на все случаи. Vitest отлично справляется с unit-тестами и интеграционными проверками благодаря скорости и поддержке ESM. Playwright закрывает e2e-уровень, отправляя реальные запросы к серверу. Вместе они покрывают весь спектр — от проверки одной функции до полного сценария с авторизацией, CRUD и обработкой ошибок. Начните с unit-тестов критичной логики, добавьте интеграционные тесты с MSW и завершите e2e-проверками ключевых эндпоинтов.

    Иконка глаза597

    Комментарии

    0

    Постройте личный план изучения Vue.js 3, Vue Router и Pinia до уровня Middle — бесплатно!

    Vue.js 3, Vue Router и Pinia — часть карты развития Frontend

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Angular

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Гарантия
    Бонусы
    иконка звёздочки рейтинга5.0
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Nuxt

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга5.0
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Feature-Sliced Design

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.5
    3 999 ₽ 6 990 ₽
    Подробнее

    Похожие статьи

    Картинка поста GraphQL vs REST: что выбрать для API в 2026 году
    Иконка аватараАнтон
    Иконка календаря11 июля 2026
    graphqlrestapi+ 3middleИконка уровня middle

    GraphQL vs REST: что выбрать для API в 2026 году

    GraphQL vs REST — разбираем ключевые отличия, сценарии применения и подводные камни каждого подхода, чтобы выбрать правильный инструмент для вашего проекта.

    Иконка чипа0
    Иконка глаза59
    Иконка комментариев0
    Картинка поста Тестирование React-компонентов с React Testing Library
    Иконка аватараАнтон
    Иконка календаря07 июля 2026
    reacttestingreact-testing-library+ 2middleИконка уровня middle

    Тестирование React-компонентов с React Testing Library

    React Testing Library — инструмент для тестирования React-компонентов через поведение пользователя, а не детали реализации. Примеры, паттерны, частые ошибки.

    Иконка чипа0
    Иконка глаза175
    Иконка комментариев0
    Картинка поста Clean Architecture: чистая архитектура для веб-разработки
    Иконка аватараАнтон
    Иконка календаря02 июля 2026
    архитектураclean architecturetypescript+ 3middleИконка уровня middle

    Clean Architecture: чистая архитектура для веб-разработки

    Clean Architecture разделяет код на независимые слои: бизнес-логика не зависит от фреймворков, БД и внешних сервисов. Разбираем на примерах TypeScript.

    Иконка чипа0
    Иконка глаза207
    Иконка комментариев0
    Иконка чипа0