Практическое руководство по тестированию React-приложений с помощью Jest

Создание корректно работающего приложения требует хорошего тестирования; в противном случае понимание того, работает ли ваше приложение должным образом или нет, будет вопросом догадок и удачи. Jest — один из лучших инструментов для тестирования React- приложений. В этой статье вы узнаете все, что нужно для создания надежного теста для компонентов и приложений React.

В этой статье я собираюсь познакомить вас с инструментом тестирования React под названием Jest, а также с популярной библиотекой Enzyme, которая предназначена для тестирования компонентов React. Я познакомлю вас с методами тестирования Jest, включая: выполнение тестов, тестирование компонентов React, тестирование снэпшотов и имитацию. Если вы новичок в тестировании и хотите знать, с чего начать, вы найдете это руководство полезным, потому что мы начнем с введения в тестирование. К концу изучения этого руководства вы сможете тестировать React- приложения с использованием Jest и Enzyme. Вы должны быть знакомы с React, чтобы следовать этому руководству.

Краткое введение в тестирование

Тестирование — это построчный обзор того, как будет выполняться код. Набор тестов для приложения включает в себя различный код, позволяющий проверить, выполняется ли приложение успешно и без ошибок или нет. Тестирование также пригодится при обновлении кода. После обновления фрагмента кода можно запустить тест, чтобы убедиться, что обновление не нарушает текущий функционал приложения.

Для чего выполнять тестирование?

Хорошо понять, почему мы что-то делаем, прежде чем делать это. Итак, для чего необходимо выполнять тестирование, и какова его цель?

  1. Первой целью тестирования является предотвращение регрессии. Регрессия— это повторное появление ошибки, которая ранее уже была исправлена. Это заставляет функцию перестать работать, как задумано после возникновения определенного события.
  2. Тестирование обеспечивает функционал сложных компонентов и модульных приложений.
  3. Тестирование необходимо для эффективной работы программного приложения или продукта.

Тестирование делает приложение более надежным и менее подверженным ошибкам. Это отличный способ проверить, что ваш код выполняет то, что вы от него хотите, и что ваше приложение работает так, как было задумано.

Давайте рассмотрим различные типы тестирования.

Модульные тесты

При этом типе тестирования тестируются отдельные модули или компоненты программного обеспечения. Единицей тестирования может быть отдельная функция, метод, процедура, модуль или объект. Модульный тест изолирует часть кода и проверяет его правильность, чтобы проверить, что каждая единица кода программного обеспечения работает так, как ожидалось.

При модульном тестировании проверяются отдельные процедуры или функции, чтобы гарантировать их правильную работу, а все компоненты тестируются индивидуально. Например, тестирование функции или определение правильности работы оператора или цикла в программе подпадают под определение модульного тестирования.

Тестирование компонентов

Тестирование компонентов проверяет функционал отдельной части приложения. Тестирование проводится для каждого компонента отдельно от других. Как правило, React- приложения состоят из нескольких компонентов, поэтому тестирование компонентов связано с индивидуальным тестированием этих компонентов.

В качестве примера, рассмотрим сайт, на котором есть различные веб-страницы с множеством компонентов. Каждый компонент будет иметь свои собственные подкомпоненты. Тестирование каждого модуля без учета интеграции с другими компонентами называется тестированием компонентов.

Подобное тестирование в React требует более сложных инструментов. Итак, нам понадобятся Jest, а иногда и более сложные инструменты, такие как Enzyme, которые мы кратко рассмотрим чуть позже.

Тестирование снэпшотов

Тест снэпшотов гарантирует, что пользовательский интерфейс веб-приложения не изменился неожиданно. Он фиксирует код компонента в определенный момент времени, так что мы можем сравнить компонент в одном состоянии с любым другим возможным состоянием, которое он может принять.

Мы поговорим о тестировании снэпшотов в следующем разделе.

Преимущества и недостатки тестирования

Тестирование — это прекрасно, и оно должно выполняться, но оно имеет как свои преимущества, так и недостатки.

Преимущества тестирования

  1. Предотвращает неожиданную регрессию.
  2. Позволяет разработчику сосредоточиться на текущей задаче, и не беспокоиться о прошлых.
  3. Позволяет создавать модульное приложение, которое в противном случае было бы слишком сложным для построения.
  4. Уменьшает необходимость ручной проверки.

Недостатки тестирования

  1. Вам придется написать больше кода, а также отладить и поддерживать его.
  2. Некритические сбои тестов могут привести к отклонению приложения с точки зрения непрерывной интеграции.

Введение в Jest

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, необходимо создать в папке src проекта файл setupTest.js. Его содержимое должно выглядеть следующим образом:

import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
configure({ adapter: new Adapter() });

Приведенный выше код импортирует Enzyme и настраивает адаптер для запуска тестов.

Прежде чем продолжить, давайте изучим некоторые основы. Некоторые ключевые вещи часто используются в этой статье, и вам необходимо их понимать.

  • it или test- вы передаете функцию этому методу, и исполнитель теста выполнит эту функцию как блок тестов.
  • 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 отображает только один компонент без дочерних компонентов.

Второй тест с помощью сопоставителя Jest toEqual проверяет, указан ли в компоненте приложения вывод тега h1 «Display Active User Account».

Теперь запустите тест:

npm run test 
/* ИЛИ */
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.

Как видите, тест пройден успешно. Это показывает, что при запуске Jest у нас есть один набор тестов App.test.js с двумя успешными тестами. Мы поговорим о тестировании снэпшотов позже, и вы также увидите пример неудачного теста.

Пропуск или изоляция теста

Пропуск или изоляция теста означает, что при запуске 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: "david@gmail.com",
  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("david@gmail.com");
  });
});

У нас есть два теста, и мы используем уровень describe, который принимает тестируемый компонент. Указав свойства и значения, которые мы хотим проверить тестом, мы можем продолжать.

В первом тесте мы проверяем, соответствуют ли свойства, которые мы передали подключенному компоненту, макетам, которые мы создали выше.

Для второго теста мы передаем свойства пользователя подключенному компоненту Account. Затем мы проверяем, можем ли мы найти элемент <p>, который соответствует тому, что мы имеем в компоненте Account. Когда мы запустим набор тестов, то увидим, что тест выполняется успешно.

Мы также можем проверить состояние компонента. Давайте проверим, равно ли состояние сообщения об ошибке нулю:

it("renders correctly with no error message", () => {
  const wrapper = mount();
  expect(wrapper.state("error")).toEqual(null);
});

В этом тесте мы проверяем, равно ли состояние ошибки нашего компонента нулю, используя средство сравнения toEqual(). Если в приложении появится сообщение об ошибке, тест не пройдёт при запуске.

В следующем разделе мы поговорим о том, как тестировать компоненты React с помощью тестирования снэпшотов, еще одной удивительной техники.

Тестирование снэпшотов

Тестирование снэпшотов фиксирует код компонента в определенный момент времени, чтобы сравнить его с эталонным файлом снэпшота, хранящимся вместе с тестом. Он используется для отслеживания изменений в пользовательском интерфейсе приложения.

Фактическое представление кода снэпшота — это файл 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

      
        
          Display Active Users Account Details
        
        
    -     Loading...
    +     Fetching Users...
        
      

       7 | it("renders correctly", ()
=> {
       8 |   const wrapper = shallow();
    >  9 |   expect(toJson(wrapper)).toMatchSnapshot();
         |                           ^      10 | });
      11 |
      12 | /* it("renders without crashing", () => {

      at Object. (src/App.test.js:9:27)

 › 1 snapshot failed.
Snapshot Summary
 › 1 snapshot failed from 1 test suite. Inspect your code changes or press `u` to update them.

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   1 failed, 1 total
Time:        92.274s
Ran all test suites related to changed files.

Watch Usage: Press w to show more.

Если мы хотим, чтобы тест прошел успешно, нам необходимо либо изменить тест на его предыдущее состояние, либо обновить файл снэпшота. В командной строке Jest предоставляет инструкции по обновлению снэпшота. Сначала нажмите w в командной строке, а затем нажмите u, чтобы обновить снэпшот.

› Press u to update failing snapshots.

После того как мы нажмем u, чтобы обновить снэпшот, тест будет пройден успешно.

Заключение

Я надеюсь, вам понравилось работать с этим руководством. Мы изучили некоторые методы тестирования Jest с использованием библиотеки тестирования Enzyme. Я также познакомил вас с процессом запуска теста, тестирования компонентов React, имитаций и тестирования снэпшотов. Если у вас есть какие-либо вопросы, вы можете задать их в комментариях.

Дополнительные материалы

  • Документация Jest
  • Документация Enzyme

Данная публикация представляет собой перевод статьи «A Practical Guide To Testing React Applications With Jest» , подготовленной дружной командой проекта Интернет-технологии.ру

Меню