Тестируем React в 2019

VLADYSLAV KOPONKIN
4 min readApr 26, 2019

Сегодня кажется, что все используют разные библиотеки для тестирования React приложений. Даже одну и ту же библиотеку используют по разному…

Полный пример кода из статьи можно посмотреть здесь.

Библиотеки

Это руководство поможет разобраться, как тестировать код react-apollo приложения. В приведённых ниже примерах используется фреймворк для тестирования - Jest, но большинство концепций можно использовать и с другими библиотеками.

Enzyme: JavaScript утилита для тестирования React компонентов. Она отлично справляется с манипулированием, обходом и симуляцией рантайма.

ReactTestUtil: набор утилит от React, помогающий тестировать компоненты в любой из возможных библиотек.

react-testing-library: легковесное решение тестирования React DOM которое способствующее использованию лучших практик.

Test Render: Этот пакет предоставляет возможность рендера React компонентов в чистые JavaScript объекты.

Две библиотеки (ReactTestUtils and Test Render) поддерживаются командой React, а остальные две рекомендуются ей.

Философия (главные принципы)

Пишите тесты. Не слишком много. В основном - интеграционные.

Kent Dodds

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

Kent Dodds

Пример

  • Для примера будем использовать TypeScript; Статичная типизация TypeScript предоставляет крепкую базу для нашей стратегии тестирования

Пример будет состоять из тестирования компонента-родителя (и его потомков) который рендерит кнопку Toggle(переключения) и текст “Hello World”. Компонент будет принимать булевую property - “initialShow”:

  • Если initialShow == true, текст Hello World текст будет виден по умолчанию; клик по кнопке Toggle заставит текст исчезнуть
  • Если initialShow == false, текст Hello World будет скрыт по умолчанию; клик по кнопке Toggle заставит текст появится

Начнем с построения каркаса нашего TypeScript React проекта по примеру из статьи Hello Create React App (CRA) — TypeScript.

Далее создадим два компонента и сопутствующие файлы стилей:

  • src/components/HiddenText/index.tsx: Классовый компонент контейнер; Главным образом состоящий из булевого состояния - show и метода toggle для его переключения.
  • src/components/HiddenText/HiddenText.css: Стилизует два css-селектора; hidden-message-enter (стили для Hello Text когда он виден по умолчанию) и hidden-message-exit (стили для Hello Text когда скрыт по умолчанию)
  • src/components/HiddenText/Fade.tsx: Функциональный, презентационный компонент отвечающий за анимацию скрытия текста
  • src/components/HiddenText/Fade.css: Определяет вспомогательные стили для анимации

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

Из описания функционала становится понятно, что нам нужно проверить следующее:

  • Текст отображается при загрузке, если initialShow == true
  • Текст скрыт при загрузке, если initialShow == false
  • Текст скрыт после клика по кнопке, если initialShow == true
  • Текст отображается после клика по кнопке, если initialShow == false

Для тестирования поведения при загрузке мы не хотим проверять результат внутри кода компонентов. Нам стоит смотреть в сторону отрисовки DOM элементов. В данном случае наблюдать за использованием CSS-классов hidden-message-enter и hidden-message-exit.

Есть как минимум два аргумента за тестирование используя наличие CSS-классов:

  • TODO!!!!
  • While an implementation detail, using class names shields us from having to test against the more implementation intensive styling they define
  • Test Render works from a React-centric perspective; class names are used in the React className property; the styling they define, however, are completely opaque to React

Обратите внимание: Использование CSS модулей, как в примере, предполагает что Вы подключите “имитирование”.

Чтобы убедиться в том, что анимация прошла успешно когда компонент загрузился, мы проинспектируем свойство “in” стороннего компонента CSSTransition. Так как проверка компонента CSSTransition скрыта за деталями реализации, это оберегает нас от тестирования более сложных классов которые он использует.

С учетом вышеизложенного, напишем два теста в src/components/HiddenText/HiddenText.test.tsx:

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

Наблюдения:

  • Так как метод setState является асинхронным, мы добавляем задержку, чтобы убедиться, что изменения вступают в силу после клика по кнопке и перед продолжением теста. В то же время тест отработал без задержки (мы назначили значение задержки - 0, чтобы обезопасить себя)
  • Оказывается, компонент CSSTransition из библиотеки react-transition-group манипулирует DOM напрямую. Так как Test Render не использует DOM, нам нужно “имитировать” компонент CSSTransition.

Оригинал статьи - ссылка

--

--