Снимки (snapshots) представляют собой способ зафиксировать состояние UI-компонента в момент тестирования, чтобы впоследствии можно было сравнивать изменения и обнаруживать непреднамеренные изменения в интерфейсе. Jest предоставляет встроенную поддержку для создания и проверки снимков, что позволяет быстро и эффективно тестировать React компоненты.
При первом запуске тестов, когда создаётся снимок компонента, Jest
сохраняет HTML-вывод компонента в файл. Этот файл хранится в каталоге
__snapshots__ рядом с тестируемыми файлами. При последующих
запусках Jest будет сравнивать текущий вывод компонента с сохранённым
снимком. Если вывод совпадает, тест проходит успешно. В противном
случае, тест считается не пройденным, и Jest сообщает о расхождении,
предлагая обновить снимок.
Для создания снимка в Jest используется метод
toMatchSnapshot(). Он применяется в тестах, где необходимо
зафиксировать состояние компонента. Рассмотрим пример тестирования
простого React компонента.
import React from 'react';
import { render } from '@testing-library/react';
import MyComponent from './MyComponent';
test('renders correctly', () => {
const { asFragment } = render(<MyComponent />);
expect(asFragment()).toMatchSnapshot();
});
В данном примере используется метод render из библиотеки
@testing-library/react, который рендерит компонент в
тестовой среде. Функция asFragment() позволяет получить
“срез” DOM-дерева компонента, который затем передаётся в
toMatchSnapshot(). При первом запуске теста Jest создаст
снимок текущего состояния компонента.
Когда разработчик вносит изменения в компонент, которые должны отразиться на его UI, необходимо обновить снимки. Jest предоставляет команду для автоматического обновления снимков:
jest --updateSnapshot
Это позволяет синхронизировать тесты с актуальными изменениями в компонентах, если изменения в UI действительно ожидаемы. В случае, если снимок был изменён случайным образом или ошибка в компоненте привела к нежеланным изменениям, необходимо отклонить обновление снимка и исправить проблему.
Снимки хранятся в отдельных файлах в каталоге
__snapshots__. Каждый файл снимков соответствует тесту и
имеет структуру, подобную следующей:
__snapshots__/
MyComponent.test.js.snap
Внутри файла хранится зафиксированный HTML-код компонента в виде строки, которая используется для сравнения с текущим состоянием компонента.
Пример содержимого файла снимка:
exports[`MyComponent renders correctly`] = `
<div>
<h1>Hello, world!</h1>
<p>Welcome to the React world!</p>
</div>
`;
Тестирование асинхронных компонентов в Jest с использованием снимков
требует дополнительных настроек. Например, если компонент загружает
данные с сервера, необходимо дождаться их загрузки перед созданием
снимка. Для этого можно использовать waitFor из библиотеки
@testing-library/react или act() из React.
Пример теста для асинхронного компонента:
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import MyAsyncComponent from './MyAsyncComponent';
test('renders correctly after data is fetched', async () => {
render(<MyAsyncComponent />);
await waitFor(() => screen.getByText(/Data loaded/));
expect(screen.getByText(/Data loaded/)).toMatchSnapshot();
});
В этом примере тестируется компонент, который асинхронно загружает данные. Сначала рендерится компонент, затем тест ждёт появления элемента с текстом “Data loaded”, после чего создаётся снимок.
В некоторых случаях может понадобиться параметризация снимков. Например, компонент может отображаться по-разному в зависимости от переданных пропсов. Для таких случаев можно создавать несколько снимков для различных конфигураций компонента.
Пример:
import React from 'react';
import { render } from '@testing-library/react';
import MyComponent from './MyComponent';
test('renders correctly with different props', () => {
const { asFragment } = render(<MyComponent title="Title 1" />);
expect(asFragment()).toMatchSnapshot();
const { asFragment: asFragment2 } = render(<MyComponent title="Title 2" />);
expect(asFragment2()).toMatchSnapshot();
});
В этом случае для разных значений пропсов будет создано два различных снимка, и каждый будет проверяться отдельно.
Снимки могут быть полезны не только для проверки UI-компонентов, но и
для тестирования производительности. Например, можно фиксировать
рендеринг компонента в различных условиях и сравнивать скорость
рендеринга с предыдущими версиями. Для этого можно использовать методы
времени из стандартной библиотеки JavaScript, такие как
performance.now().
Пример:
import React from 'react';
import { render } from '@testing-library/react';
import MyComponent from './MyComponent';
test('measures render time', () => {
const startTime = performance.now();
render(<MyComponent />);
const endTime = performance.now();
const renderTime = endTime - startTime;
expect(renderTime).toBeLessThan(100); // Ожидаем, что рендеринг займет менее 100 мс
});
Частые ложные срабатывания: Ложные срабатывания
могут происходить, если в компоненте изменяются мелкие детали, не
влияющие на функциональность. В таких случаях можно использовать
toMatchInlineSnapshot(), чтобы вручную фиксировать снимки
прямо в тестах.
Большие снимки: Снимки, содержащие огромные объёмы данных, могут быть неудобными для поддержки. Один из способов решения этой проблемы — использование более мелких, изолированных компонентов, которые тестируются отдельно.
Снимки в Jest — это мощный инструмент для тестирования React компонентов, который позволяет фиксировать их визуальное состояние и проверять, не произошли ли непреднамеренные изменения. Этот метод особенно полезен для UI-компонентов, но также требует внимательности при обновлении снимков и при работе с асинхронными или параметризованными компонентами.