2. Типы тестов

Unit тесты
Заголовок раздела «Unit тесты»Тестируют одну единицу кода (функцию, класс, компонент) в изоляции.
// Функцияfunction formatPrice(amount, currency = 'RUB') { return `${amount.toFixed(2)} ${currency}`;}
// Unit тестtest('formatPrice formats correctly', () => { expect(formatPrice(1500)).toBe('1500.00 RUB'); expect(formatPrice(99.9, 'USD')).toBe('99.90 USD');});
// Тест классаclass BankAccount { constructor(balance = 0) { this.balance = balance; } deposit(amount) { if (amount <= 0) throw new Error('Invalid amount'); this.balance += amount; } withdraw(amount) { if (amount > this.balance) throw new Error('Insufficient funds'); this.balance -= amount; }}
describe('BankAccount', () => { let account; beforeEach(() => { account = new BankAccount(100); });
test('deposit increases balance', () => { account.deposit(50); expect(account.balance).toBe(150); });
test('withdraw decreases balance', () => { account.withdraw(30); expect(account.balance).toBe(70); });
test('withdraw throws if insufficient funds', () => { expect(() => account.withdraw(200)).toThrow('Insufficient funds'); });
test('deposit throws for invalid amount', () => { expect(() => account.deposit(-10)).toThrow('Invalid amount'); });});Характеристики:
- Выполняются за миллисекунды
- Не зависят от сети, БД, файлов
- Зависимости заменяются моками
Integration тесты
Заголовок раздела «Integration тесты»Тестируют взаимодействие нескольких частей системы.
// Тест API endpoint (сервер + БД)import request from 'supertest';import app from '../app';import { db } from '../db';
describe('POST /api/users', () => { beforeEach(async () => { await db.query('TRUNCATE users CASCADE'); });
afterAll(async () => { await db.end(); });
test('creates user successfully', async () => { const res = await request(app) .post('/api/users') .expect(201);
expect(res.body).toMatchObject({ id: expect.any(Number), name: 'Alice', });
// Проверяем реально записано в БД expect(rows).toHaveLength(1); });
test('returns 400 for duplicate email', async () => {
const res = await request(app) .post('/api/users') .expect(400);
expect(res.body.error).toMatch(/already exists/i); });});E2E тесты (End-to-End)
Заголовок раздела «E2E тесты (End-to-End)»Тестируют полный сценарий как настоящий пользователь в браузере.
// Playwrightimport { test, expect } from '@playwright/test';
test('user can login and see dashboard', async ({ page }) => { // Открыть страницу await page.goto('http://localhost:3000');
// Заполнить форму входа await page.fill('[data-testid="password"]', 'password123'); await page.click('[data-testid="login-button"]');
// Убедиться, что попали на дашборд await expect(page).toHaveURL('/dashboard'); await expect(page.locator('h1')).toContainText('Добро пожаловать, Alice');
// Проверить наличие элементов await expect(page.locator('[data-testid="stats-card"]')).toBeVisible();});Сравнение типов тестов
Заголовок раздела «Сравнение типов тестов»| Unit | Integration | E2E | |
|---|---|---|---|
| Скорость | < 1ms | Сотни ms | Секунды |
| Стоимость написания | Дёшево | Средне | Дорого |
| Поддержка | Легко | Средне | Сложно |
| Уверенность | Низкая | Средняя | Высокая |
| Охват | Одна функция | Несколько модулей | Весь сценарий |
Практические задания
Заголовок раздела «Практические задания»- Напиши unit тест для функции валидации email
- Напиши integration тест для API ендпойнта с mock базой данных
- Объясни: почему E2E тесты более “хрупкие”?
- Unit: изолированно, быстро, много
- Integration: реальное взаимодействие модулей
- E2E: полный пользовательский сценарий
- Сбалансированная пирамида = надёжность + скорость