Ответ
Для тестирования компонентов использую Jest + React Testing Library (RTL). Основные подходы:
- Рендеринг – проверяю, что компонент отображается без ошибок:
test('renders button', () => {
render(<Button>Click</Button>);
expect(screen.getByText('Click')).toBeInTheDocument();
});
- Поведение – тестирую обработчики событий и состояние:
test('calls onClick when clicked', () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick} />);
fireEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalled();
});
-
Снимки (Snapshots) – для контроля неожиданных изменений в верстке.
-
Интеграционные тесты – проверяю взаимодействие с другими компонентами/хуками.
Ключевые принципы:
- Тестирую как пользователь (через DOM, а не внутреннее состояние)
- Избегаю тестирования реализации
- Использую
data-testidтолько когда нет других вариантов - Мокирую только внешние зависимости (API и т.д.)
Ответ 18+ 🔞
А, тестирование, говоришь? Ну, слушай, я тебе сейчас так разложу, что ты офигеешь, но по-человечески.
Вот смотри, чтобы мои компоненты не вели себя как последние мудаки в продакшене, я их держу в ежовых рукавицах. Инструмент? Jest да React Testing Library (или RTL, для своих). Это как связка ключа и отмычки — без них нихуя не проверишь.
Как я это делаю? По полочкам, блядь:
- Рендеринг, ёпта. Самый базовый чекап — не разваливается ли эта хрень при первом же взгляде. Как бабушка у подъезда: «А живой ли ты вообще?».
test('renders button', () => {
render(<Button>Click</Button>);
expect(screen.getByText('Click')).toBeInTheDocument();
});
Всё, глянул — кнопка на месте. Уже хорошо. Не на месте? Ну, пидарас шерстяной, иди фикси.
- Поведение, ёбушки-воробушки. А теперь самое интересное — а работает ли оно? Кликнул — что-то произошло? Не кликнул — не произошло? Это ж магия, блядь, её проверять надо.
test('calls onClick when clicked', () => {
const handleClick = jest.fn(); // Подставная крыса, мок, короче
render(<Button onClick={handleClick} />);
fireEvent.click(screen.getByRole('button')); // БАЦ кликнул!
expect(handleClick).toHaveBeenCalled(); // А крыса-то запищала? Значит, работает!
});
Вот это уже тест с характером. Не запищала крыса — значит, хуйня, а не кнопка.
-
Снимки (Snapshots). Это как фотография твоего кода в молодости. Запустил раз, он сфоткал разметку. Потом, через месяц, когда ты там что-то «улучшил», запускаешь снова — а он тебе: «Слушай, а тут у тебя волосы выпали и морщины появились, это ожидаемо?». Удобно, чтобы случайно не сломать то, что не трогал. Но без фанатизма, а то заебешься эти снапшоты апдейтить.
-
Интеграционные тесты. Это когда ты проверяешь не одного отбитого солдата, а целый взвод — как компоненты друг с другом или с хуками общаются. Чтобы не вышло, что кнопка жмётся, а данные в пропердоленную дыру улетают.
А теперь, блядь, главные принципы, чтобы не быть мудаком в тестах:
- Тестируй как пользователь, а не как долбоёб. Не лезь во внутренности компонента, не проверяй стейты и пропсы напрямую. Ты должен кликать по кнопкам, заполнять поля — как это делает живой человек. И смотреть, что в ДОМе поменялось. Всё.
- Не тестируй реализацию, тестируй результат. Наплевать, как внутри функция называется. Важно, что после её вызова на экране появилась надпись «Успех». Иначе с каждым рефакторингом тесты будут сыпаться, и терпения ноль ебать.
data-testid— это как кричать «АУУУ, я здесь!» в лесу. Используй только в самом крайнем случае, когда по-человечески через текст или роль элемент не найти. СначалаgetByRole,getByText,getByLabelText. Это твои лучшие друзья.- Моки — это зло, но иногда необходимое. Мокай только внешний мир, который от тебя не зависит: запросы к АПИ, модули для работы с датами, всякие сторонние либы. Свою логику мокать — это путь в никуда, чистая симуляция работы.
Вот и вся философия. Не усложняй, думай как юзер, и будет тебе счастье. А то некоторые такие тесты пишут, что сам чёрт ногу сломит, а толку — хуй с горы.