Перейти к основному содержимому

Тестирование JavaScript — Vitest и Testing Library

Разработчику Архитектору

Тестирование JavaScript

В современном фронтенде стандарт — Vitest (быстрый runner, совместим с Vite) и Testing Library (тесты через DOM, как пользователь). Jest по-прежнему встречается в legacy и Create React App.

Связь: React, Vue, Node.js, раздел тестирования.


Vitest vs Jest

VitestJest
Скорость devОчень высокая (ESM, Vite)Медленнее на больших проектах
Конфигvite.config.ts + testjest.config.js
APIdescribe, it, expect — как в JestОригинал
CRA / старые проектыМиграция возможнаИз коробки

Новые проекты на Vite / Next / Vue CLI 5+ чаще выбирают Vitest.


Чистые функции (unit)

npm init -y
npm install -D vitest

package.json:

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

src/sum.js:

export function sum(a, b) {
return a + b;
}

src/sum.test.js:

import { describe, it, expect } from 'vitest';
import { sum } from './sum.js';

describe('sum', () => {
it('adds numbers', () => {
expect(sum(2, 3)).toBe(5);
});
});
npm test

React + Testing Library

npm create vite@latest my-app -- --template react
cd my-app
npm install -D vitest jsdom @testing-library/react @testing-library/jest-dom @testing-library/user-event

vite.config.js:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
plugins: [react()],
test: {
environment: 'jsdom',
setupFiles: './src/test/setup.js',
},
});

src/test/setup.js:

import '@testing-library/jest-dom/vitest';

src/Counter.jsx:

import { useState } from 'react';

export function Counter() {
const [n, setN] = useState(0);
return (
<div>
<span data-testid="count">{n}</span>
<button type="button" onClick={() => setN((x) => x + 1)}>+1</button>
</div>
);
}

src/Counter.test.jsx:

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect } from 'vitest';
import { Counter } from './Counter';

describe('Counter', () => {
it('increments on click', async () => {
const user = userEvent.setup();
render(<Counter />);
expect(screen.getByTestId('count')).toHaveTextContent('0');
await user.click(screen.getByRole('button', { name: '+1' }));
expect(screen.getByTestId('count')).toHaveTextContent('1');
});
});

Принцип Testing Library: искать по роли/тексту, а не по классам CSS.


Тест API на Node (Supertest)

npm install express
npm install -D vitest supertest

app.js:

import express from 'express';
export const app = express();
app.get('/health', (_req, res) => res.json({ ok: true }));

app.test.js:

import request from 'supertest';
import { describe, it, expect } from 'vitest';
import { app } from './app.js';

describe('GET /health', () => {
it('returns ok', async () => {
const res = await request(app).get('/health');
expect(res.status).toBe(200);
expect(res.body).toEqual({ ok: true });
});
});

См. Первая программа на Node.js.


E2E (граница раздела)

Браузерные сценарии — Playwright или Cypress (упоминаются в Vue и React), не Vitest. Пирамида тестов: много unit → меньше integration → мало e2e.


CI

- run: npm ci
- run: npm run test:run

Связанные материалы


См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).