Практическое руководство по тестированию приложений React с помощью Jest
Опубликовано: 2022-03-10В этой статье я познакомлю вас с инструментом тестирования React под названием Jest, а также с популярной библиотекой Enzyme, предназначенной для тестирования компонентов React. Я познакомлю вас с методами тестирования Jest, в том числе: запуск тестов, тестирование компонентов React, тестирование моментальных снимков и имитация. Если вы новичок в тестировании и вам интересно, с чего начать, это руководство будет вам полезно, потому что мы начнем с введения в тестирование. К концу вы будете работать и тестировать приложения React с помощью Jest и Enzyme. Вы должны быть знакомы с React, чтобы следовать этому руководству.
Краткое введение в тестирование
Тестирование — это построчная проверка того, как будет выполняться ваш код. Набор тестов для приложения включает в себя различные фрагменты кода для проверки того, выполняется ли приложение успешно и без ошибок. Тестирование также пригодится, когда в код вносятся обновления. После обновления фрагмента кода вы можете запустить тест, чтобы убедиться, что обновление не нарушило уже существующие функции приложения.
Почему тест?
Хорошо понимать, почему мы что-то делаем, прежде чем делать это. Итак, зачем тестировать и какова его цель?
- Первая цель тестирования — предотвратить регрессию. Регрессия — это повторное появление ошибки, которая ранее была исправлена. Это заставляет функцию перестать функционировать должным образом после того, как произойдет определенное событие.
- Тестирование обеспечивает функциональность сложных компонентов и модульных приложений.
- Тестирование необходимо для эффективной работы программного приложения или продукта.
Тестирование делает приложение более надежным и менее подверженным ошибкам. Это способ убедиться, что ваш код делает то, что вы хотите, и что ваше приложение работает так, как задумано для ваших пользователей.
Давайте рассмотрим типы тестирования и то, что они делают.
Модульный тест
В этом типе тестирования тестируются отдельные блоки или компоненты программного обеспечения. Единицей может быть отдельная функция, метод, процедура, модуль или объект. Модульный тест изолирует раздел кода и проверяет его правильность, чтобы убедиться, что каждый модуль программного кода работает так, как ожидалось.
При модульном тестировании проверяются отдельные процедуры или функции, чтобы гарантировать их правильную работу, и все компоненты проверяются по отдельности. Например, проверка функции или правильности функционирования оператора или цикла в программе подпадает под область модульного тестирования.
Тест компонентов
Компонентное тестирование проверяет функциональность отдельной части приложения. Тесты выполняются для каждого компонента отдельно от других компонентов. Как правило, приложения React состоят из нескольких компонентов, поэтому тестирование компонентов касается тестирования этих компонентов по отдельности.
Например, рассмотрим веб-сайт, на котором есть разные веб-страницы со многими компонентами. Каждый компонент будет иметь свои собственные подкомпоненты. Тестирование каждого модуля без учета интеграции с другими компонентами называется тестированием компонентов.
Для подобного тестирования в React требуются более сложные инструменты. Итак, нам понадобится Jest, а иногда и более сложные инструменты, такие как Enzyme, которые мы кратко обсудим позже.
Снимок теста
Снимок-тест гарантирует, что пользовательский интерфейс (UI) веб-приложения не изменится неожиданно. Он фиксирует код компонента в определенный момент времени, чтобы мы могли сравнить компонент в одном состоянии с любым другим возможным состоянием, которое он может принять.
Мы узнаем о тестировании моментальных снимков в следующем разделе.
Преимущества и недостатки тестирования
Тестирование — это здорово, и его нужно проводить, но у него есть свои преимущества и недостатки.
Преимущества
- Это предотвращает неожиданный регресс.
- Это позволяет разработчику сосредоточиться на текущей задаче, а не беспокоиться о прошлом.
- Это позволяет создавать модульные конструкции приложений, которые в противном случае были бы слишком сложными для создания.
- Это снижает потребность в ручной проверке.
Недостатки
- Вам нужно написать больше кода, а также отлаживать и поддерживать.
- Некритические сбои теста могут привести к тому, что приложение будет отклонено с точки зрения непрерывной интеграции.
Введение в шутку
Jest — это восхитительный фреймворк для тестирования JavaScript с упором на простоту. Его можно установить с помощью npm или Yarn. Jest относится к более широкой категории утилит, известных как средства запуска тестов. Он отлично работает для приложений React, но также отлично работает вне приложений React.
Enzyme — это библиотека, которая используется для тестирования приложений React. Он предназначен для тестирования компонентов и позволяет писать утверждения, имитирующие действия, подтверждающие правильность работы пользовательского интерфейса.
Jest и Enzyme так хорошо дополняют друг друга, что в этой статье мы будем использовать оба.
Процесс запуска теста с Jest
В этом разделе мы будем устанавливать Jest и писать тесты. Если вы новичок в React, я рекомендую использовать приложение Create React, потому что оно готово к использованию и поставляется с Jest.
npm init react-app my-app
Нам нужно установить Enzyme **** и enzyme-adapter-react-16
с помощью react-test-renderer
(число должно основываться на версии React, которую вы используете).
npm install --save-dev enzyme enzyme-adapter-react-16 react-test-renderer
Теперь, когда мы создали наш проект как с Jest, так и с Enzyme, нам нужно создать файл setupTest.js
в папке src
проекта. Файл должен выглядеть так:
import { configure } from "enzyme"; import Adapter from "enzyme-adapter-react-16"; configure({ adapter: new Adapter() });
Это импортирует Enzyme и настраивает адаптер для запуска наших тестов.
Прежде чем продолжить, давайте изучим некоторые основы. Некоторые ключевые вещи часто используются в этой статье, и вам необходимо их понять.
-
it
ortest
Вы должны передать функцию этому методу, и программа запуска тестов выполнит эту функцию как блок тестов. -
describe
Этот необязательный метод предназначен для группировки любого количества операторовit
илиtest
. -
expect
Это условие, которое тест должен пройти. Он сравнивает полученный параметр с сопоставителем. Это также дает вам доступ к ряду сопоставителей, которые позволяют вам проверять разные вещи. Подробнее об этом можно прочитать в документации. -
mount
Этот метод отображает полный DOM, включая дочерние компоненты родительского компонента, в котором мы запускаем тесты. -
shallow
Это визуализирует только отдельные компоненты, которые мы тестируем. Он не отображает дочерние компоненты. Это позволяет нам тестировать компоненты изолированно.
Создание тестового файла
Как Jest узнает, что является тестовым файлом, а что нет? Первое правило заключается в том, что любые файлы, найденные в любом каталоге с именем __test__
, считаются тестом. Если вы поместите файл JavaScript в одну из этих папок, Jest попытается запустить его, когда вы вызовете Jest, к лучшему или к худшему. Второе правило заключается в том, что Jest распознает любой файл с суффиксом .spec.js
или .test.js
. Он будет искать имена всех папок и всех файлов во всем вашем хранилище.
Давайте создадим наш первый тест для мини-приложения React, созданного для этого руководства. Вы можете клонировать его на GitHub. Запустите npm install
, чтобы установить все пакеты, а затем npm start
, чтобы запустить приложение. Проверьте файл README.md
для получения дополнительной информации.
Давайте откроем App.test.js
, чтобы написать наш первый тест. Во-первых, проверьте, правильно ли отображается наш компонент приложения и указали ли мы вывод:
it("renders without crashing", () => { shallow(<App />); }); it("renders Account header", () => { const wrapper = shallow(<App />); const welcome = <h1>Display Active Users Account Details</h1>; expect(wrapper.contains(welcome)).toEqual(true); });
В вышеприведенном тесте первый тест с shallow
проверяет, правильно ли отображается наш компонент приложения без сбоев. Помните, что shallow
метод отображает только один компонент без дочерних компонентов.
Второй тест проверяет, указали ли мы вывод тега h1
«Отображать активную учетную запись пользователя» в нашем компоненте приложения с помощью Jest toEqual
.
Теперь запустите тест:
npm run test /* OR */ npm test
Вывод в вашем терминале должен выглядеть так:
PASS src/App.test.js √ renders without crashing (34ms) √ renders Account header (13ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 11.239s, estimated 16s Ran all test suites related to changed files. Watch Usage: Press w to show more.
Как видите, наш тест прошел. Это показывает, что у нас есть один набор тестов с именем App.test.js
с двумя успешными тестами при запуске Jest. Мы поговорим о тестировании моментальных снимков позже, и вы также увидите пример неудачного теста.
Пропуск или изоляция теста
Пропуск или изоляция теста означает, что при запуске Jest определенный помеченный тест не запускается.
it.skip("renders without crashing", () => { shallow(<App />); }); it("renders Account header", () => { const wrapper = shallow(<App />); const header = <h1>Display Active Users Account Details</h1>; expect(wrapper.contains(header)).toEqual(true); });
Наш первый тест будет пропущен, потому что мы использовали метод skip
, чтобы изолировать тест. Таким образом, он не будет запускаться или вносить какие-либо изменения в наш тест при запуске Jest. Запустится только второй. Вы также можете использовать it.only()
.
Немного неприятно вносить изменения в тестовый файл, а затем снова запускать npm test
вручную. Jest имеет удобную функцию, называемую режимом наблюдения, которая следит за изменениями файлов и соответствующим образом запускает тесты. Чтобы запустить Jest в режиме просмотра, вы можете запустить npm test -- --watch
или jest --watch
. Я бы также рекомендовал оставить Jest запущенным в окне терминала до конца этого руководства.
Насмешливая функция
Макет — это убедительная копия объекта или модуля без какой-либо реальной внутренней работы. У него может быть небольшая функциональность, но по сравнению с реальной вещью это макет. Он может быть создан Jest автоматически или вручную.
Почему мы должны издеваться? Мокирование уменьшает количество зависимостей, то есть количество связанных файлов, которые необходимо загрузить и проанализировать при запуске теста. Таким образом, использование большого количества моков ускоряет выполнение тестов.
Мок-функции также известны как «шпионы», потому что они позволяют вам следить за поведением функции, которая вызывается непосредственно каким-то другим кодом, а не только проверять вывод.
Есть два способа имитировать функцию: либо создать фиктивную функцию для использования ее в тестовом коде, либо написать фиктивную функцию вручную, чтобы переопределить зависимость модуля.
Ручные макеты ****используются для заглушения функциональности фиктивными данными. Например, вместо доступа к удаленному ресурсу, такому как веб-сайт или база данных, вы можете создать макет вручную, который позволит вам использовать поддельные данные.
Мы будем использовать фиктивную функцию в следующем разделе.
Тестирование компонентов React
В этом разделе будут объединены все знания, которые мы получили на данный момент, чтобы понять, как тестировать компоненты React. Тестирование включает в себя проверку того, что выходные данные компонента не изменились неожиданно на что-то другое. Правильное конструирование компонентов — безусловно, самый эффективный способ обеспечить успешное тестирование.
Одна вещь, которую мы можем сделать, — это протестировать реквизиты компонентов — в частности, проверить, передаются ли реквизиты из одного компонента другому. Jest и Enzyme API позволяют нам создать фиктивную функцию для имитации того, передаются ли реквизиты между компонентами.
Мы должны передать реквизиты учетной записи пользователя из основного компонента App
в компонент Account
. Нам нужно предоставить данные учетной записи пользователя в Account
, чтобы отобразить активную учетную запись пользователей. Именно здесь нам пригодится насмешка, позволяющая нам тестировать наши компоненты с поддельными данными.
Давайте создадим макет для user
реквизита:
const user = { name: "Adeneye David", email: "[email protected]", username: "Dave", };
Мы создали ручную фиктивную функцию в нашем тестовом файле и обернули ее вокруг компонентов. Допустим, мы тестируем большую базу данных пользователей. Доступ к базе данных напрямую из нашего тестового файла не рекомендуется. Вместо этого мы создаем фиктивную функцию, которая позволяет нам использовать поддельные данные для тестирования нашего компонента.
describe(" ", () => { it("accepts user account props", () => { const wrapper = mount(<Account user={user} />); expect(wrapper.props().user).toEqual(user); }); it("contains users account email", () => { const wrapper = mount(<Account user={user} />); const value = wrapper.find("p").text(); expect(value).toEqual("[email protected]"); }); });
describe(" ", () => { it("accepts user account props", () => { const wrapper = mount(<Account user={user} />); expect(wrapper.props().user).toEqual(user); }); it("contains users account email", () => { const wrapper = mount(<Account user={user} />); const value = wrapper.find("p").text(); expect(value).toEqual("[email protected]"); }); });
У нас есть два теста выше, и мы используем слой describe
, который принимает тестируемый компонент. Указав реквизиты и значения, которые, как мы ожидаем, будут переданы тестом, мы можем продолжить.
В первом тесте мы проверяем, совпадают ли реквизиты, которые мы передали смонтированному компоненту, с фиктивными реквизитами, которые мы создали выше.
Для второго теста мы передаем реквизиты пользователя смонтированному компоненту Account
. Затем мы проверяем, можем ли мы найти элемент <p>
, соответствующий тому, что у нас есть в компоненте Account
. Когда мы запустим набор тестов, вы увидите, что тест проходит успешно.
Мы также можем проверить состояние нашего компонента. Проверим, равно ли состояние сообщения об ошибке null:
it("renders correctly with no error message", () => { const wrapper = mount( ); expect(wrapper.state("error")).toEqual(null); });
it("renders correctly with no error message", () => { const wrapper = mount( ); expect(wrapper.state("error")).toEqual(null); });
В этом тесте мы проверяем, равно ли состояние ошибки нашего компонента нулю, используя toEqual()
. Если в нашем приложении есть сообщение об ошибке, тест не будет выполнен.
В следующем разделе мы рассмотрим, как тестировать компоненты React с помощью моментального тестирования — еще одного замечательного метода.
Тестирование моментальных снимков
Тестирование моментальных снимков фиксирует код компонента в определенный момент времени, чтобы сравнить его с эталонным файлом моментального снимка, хранящимся вместе с тестом. Он используется для отслеживания изменений в пользовательском интерфейсе приложения.
Фактическое кодовое представление моментального снимка — это файл JSON, и этот JSON содержит запись о том, как выглядел компонент при создании моментального снимка. Во время теста Jest сравнивает содержимое этого файла JSON с выводом компонента во время теста. Если они совпадают, тест пройден; если они этого не делают, тест не пройден.
Чтобы преобразовать оболочку Enzyme в формат, совместимый с тестированием моментальных снимков Jest, мы должны установить enzyme-to-json
:
npm install --save-dev enzyme-to-json
Давайте создадим наш тестовый снимок. Когда мы запустим его в первый раз, снимок кода этого компонента будет составлен и сохранен в новой папке __snapshots__
в каталоге src
.
it("renders correctly", () => { const tree = shallow(<App />); expect(toJson(tree)).toMatchSnapshot(); });
Когда приведенный выше тест выполняется успешно, текущий компонент пользовательского интерфейса будет сравниваться с существующим.
Теперь запустим тест:
npm run test
При запуске набора тестов будет создан новый снимок, который будет сохранен в папке __snapshots__
. Когда мы впоследствии запустим тест, Jest проверит, соответствуют ли компоненты снимку.
Как объяснялось в предыдущем разделе, этот shallow
метод из пакета Enzyme используется для рендеринга одного компонента и больше ничего. Он не отображает дочерние компоненты. Скорее, это дает нам хороший способ изолировать код и получать более точную информацию при отладке. Другой метод с именем mount
используется для рендеринга всего DOM, включая дочерние компоненты родительского компонента, в котором мы запускаем тесты.
Мы также можем обновить наш снимок. Давайте внесем некоторые изменения в наш компонент, чтобы наш тест не прошел, что произойдет, потому что компонент больше не соответствует тому, что у нас есть в файле снимка. Для этого изменим <h3>
в нашем компоненте с <h3> Loading...</h3>
на <h3>Fetching Users...</h3>
. Когда тест запустится, вот что мы получим в терминале:
FAIL src/App.test.js (30.696s) × renders correctly (44ms) ● renders correctly expect(received).toMatchSnapshot() Snapshot name: `renders correctly 1 - Snapshot + Received
7 | it("отображает правильно", () => { 8 | константная оболочка = мелкая ( FAIL src/App.test.js (30.696s) × renders correctly (44ms) ● renders correctly expect(received).toMatchSnapshot() Snapshot name: `renders correctly 1 - Snapshot + Received
Отображение сведений об учетной записи активных пользователей
- Загрузка... + Получение пользователей...
); > 9 | ожидать(toJson(обертка)).toMatchSnapshot(); | ^ 10 | }); 11 | 12 | /* it("работает без сбоев", () => { на Объект. (источник/App.test.js:9:27) › Ошибка 1 снимка. Сводка по снимку › Ошибка 1 моментального снимка из 1 набора тестов. Проверьте изменения кода или нажмите `u`, чтобы обновить их. Наборы тестов: 1 неудачно, всего 1 Тесты: 1 неудачный, 1 всего Снимки: 1 неудачный, всего 1 Время: 92,274 с Запустил все наборы тестов, связанные с измененными файлами. Использование просмотра: нажмите w, чтобы показать больше.
Если мы хотим, чтобы наш тест прошел, мы либо вернем его в предыдущее состояние, либо обновим файл моментального снимка. В командной строке Jest предоставляет инструкции по обновлению моментального снимка. Сначала нажмите w
в командной строке, чтобы показать больше, а затем нажмите u
, чтобы обновить снимок.
› Press u to update failing snapshots.
Когда мы нажмем u
для обновления снимка, тест будет пройден.
Заключение
Надеюсь, вам понравилось работать с этим уроком. Мы изучили некоторые методы тестирования Jest, используя библиотеку тестирования Enzyme. Я также познакомил вас с процессом запуска теста, тестирования компонентов React, имитации и тестирования моментальных снимков. Если у вас есть какие-либо вопросы, вы можете оставить их в разделе комментариев ниже, и я буду рад ответить на каждый из них и решить любые проблемы с вами.
Ресурсы и дополнительная литература
- Шуточная документация
- Документация по ферментам
- «Как тестировать компоненты React: полное руководство», Мохаммад Икбал, freeCodeCamp
- «Тестирование React с помощью Jest и Enzyme», Доминик Фрейзер, CodeClan