Нейминг файлов тестов — это важная часть работы с любой системой тестирования, в том числе с React Testing Library. Подход к ней должен быть последовательным и логичным, чтобы код оставался читаемым и поддерживаемым в течение длительного времени. Нейминговые соглашения помогают не только улучшить понимание структуры проекта, но и ускорить навигацию по файлам, особенно в крупных приложениях с множеством компонентов.
Тесты должны отражать структуру исходных файлов компонентов и быть легко ассоциируемыми с ними. Обычно тесты размещаются рядом с тестируемым компонентом, что позволяет быстро найти все тесты, относящиеся к конкретному коду. Для этого можно использовать следующие рекомендации:
Расположение тестовых файлов рядом с компонентами В большинстве проектов принято хранить тесты рядом с компонентами, которые они проверяют. Например:
src/
components/
Button/
Button.js
Button.test.js
Header/
Header.js
Header.test.jsИспользование одинаковых имен для тестовых и исходных
файлов Тесты должны иметь те же имена, что и компоненты, но с
добавлением расширения .test.js или .spec.js
для отличия от исходных файлов. Например, если компонент называется
Button.js, тестовый файл для него будет называться
Button.test.js. Это помогает избежать путаницы и упростить
поиск тестов.
Использование .test.js и
.spec.js Важно понимать разницу между двумя
расширениями:
.test.js — это наиболее распространённый вариант для
именования тестовых файлов..spec.js — в некоторых проектах используется как
альтернатива. Основное отличие заключается в стиле, однако для
большинства проектов оба варианта являются приемлемыми.Тесты для различных частей компонента Когда компонент включает несколько подкомпонентов или различных частей логики, тесты могут быть разбиты на несколько файлов. Например:
src/
components/
Button/
Button.js
Button.test.js
ButtonText.test.js
ButtonClickHandler.test.jsДля крупных проектов, где тесты занимают значительную часть структуры
проекта, может быть полезно создать отдельную папку для тестов. Она
может располагаться в корне проекта или в папке src. Важно,
чтобы структура оставалась логичной и понятной.
Пример структуры:
src/
components/
Button/
Button.js
tests/
Button.test.js
Header.test.js
В этом случае тесты не обязательно будут находиться рядом с тестируемыми компонентами, но при этом они будут организованы в отдельную папку, что сохраняет структуру проекта аккуратной.
Хотя нейминг файлов тестов важен для навигации по проекту, организация тестов внутри самого тестового файла играет не менее важную роль. В React Testing Library принято разделять тесты на несколько категорий:
Тесты рендеринга Тестирование рендеринга компонентов является одной из самых базовых задач. Тесты рендеринга проверяют, что компонент правильно отображается в UI при заданных входных данных.
it('должен рендерить кнопку с текстом "Click me"', () => {
render(<Button label="Click me" />);
expect(screen.getByText('Click me')).toBeInTheDocument();
});Тесты взаимодействия Проверка взаимодействий пользователя с компонентом. Это могут быть клики, изменения состояний и другие действия.
it('должен обновлять текст кнопки при клике', () => {
render(<Button label="Click me" />);
fireEvent.click(screen.getByText('Click me'));
expect(screen.getByText('Clicked!')).toBeInTheDocument();
});Тесты асинхронных действий Важно тестировать асинхронные действия, такие как запросы к серверу или задержки в анимации. React Testing Library предоставляет методы для работы с асинхронными операциями.
it('должен загружать данные и отображать их', async () => {
render(<DataFetcher />);
await waitFor(() => expect(screen.getByText('Data Loaded')).toBeInTheDocument());
});В некоторых случаях для удобства можно разделить тесты на группы с помощью описательных заголовков внутри одного тестового файла, что позволяет структурировать их по функциональным блокам:
describe('Button компонент', () => {
describe('Рендеринг', () => {
it('должен рендерить кнопку с текстом "Click me"', () => {
render(<Button label="Click me" />);
expect(screen.getByText('Click me')).toBeInTheDocument();
});
});
describe('Взаимодействие', () => {
it('должен изменять текст кнопки при клике', () => {
render(<Button label="Click me" />);
fireEvent.click(screen.getByText('Click me'));
expect(screen.getByText('Clicked!')).toBeInTheDocument();
});
});
});
Тесты для утилитарных функций Если в проекте
присутствуют утилитарные функции, которые не связаны напрямую с
компонентами, для их тестирования можно использовать тот же подход с
именами файлов, добавив суффикс .utils.test.js.
Например:
src/
utils/
formatDate.js
formatDate.test.jsТесты для хуков Для тестирования кастомных
React-хуков рекомендуется использовать имена с добавлением суффикса
.hook.test.js:
src/
hooks/
useFetch.js
useFetch.hook.test.jsТесты для маршрутизации и других зависимостей В случае, когда тестируется сложная логика с использованием роутинга или других внешних зависимостей, для тестов можно использовать более общее имя с указанием контекста. Например:
src/
components/
App/
App.js
AppWithRouter.test.jsЧёткое и логичное нейминг соглашение способствует улучшению понимания структуры проекта и облегчает процесс отладки. Когда тесты и компоненты именуются последовательно, становится проще находить тесты, связывать их с кодом и модифицировать их по мере изменений в компоненте. Это помогает поддерживать чистоту и порядок в проекте, а также упрощает работу других разработчиков, которые могут подключаться к проекту на разных этапах его развития.
Таким образом, соблюдение хороших практик нейминга тестов в React помогает в достижении лучшего понимания структуры проекта, повышает читаемость и поддерживаемость кода, а также делает процесс тестирования более удобным и гибким.