Рубрики
Без рубрики

Правильный способ проверить компоненты реагирования

Lily Scott правильный путь к тестированию ACT ComponentSthere много путаницы прямо сейчас о «правильном» способе проверить ваши элементы реагирования. Если вы пишете все свои тесты вручную или использовать только снимки или некоторые из них? Должны ли вы проверить реквизиты? Состояние? Стили / макет? я

Автор оригинала: FreeCodeCamp Community Member.

Лили Скотт

Сейчас есть много путаницы в отношении «правильного» способа проверить ваши элементы реагирования. Если вы пишете все свои тесты вручную или использовать только снимки или некоторые из них? Должны ли вы проверить реквизиты? Состояние? Стили/макет?

Я не думаю, что есть один «правильный» способ, но я нашел несколько шаблонов и советов, которые очень хорошо работают для меня, которые я хотел бы поделиться.

Обновите Feb 2019 : Этот пост описывает способ тестирования единиц реагирования. Со временем я обнаружил, что получаю больше ценности от тестов интеграции, чем тесты единиц, так что Я лично больше не применяю этот метод Отказ

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

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

Фон: приложение мы проверим

Предположим, вы хотите проверить LockScreen Компонент, который ведет себя как экран блокировки телефона. Это:

  • Показывает текущее время
  • Может показать пользовательское сообщение
  • Может показать пользовательское фоновое изображение
  • Имеет виджет слайда до разблокировки внизу

Это выглядит что-то подобное:

Вы можете попробовать это здесь и просмотреть код на Github Отказ

Вот код для верхнего уровня Приложение составная часть:

Как вы можете видеть, LockScreen Получает три реквизита: Wallpasathate , UserInFomessage и окутел Отказ

Вот код для LockScreen :

LockScreen тянет в несколько других компонентов, но так как мы тестируем только LockScreen Давайте направимся на это прямо сейчас.

Компонентные контракты

Для того, чтобы проверить LockScreen , вы должны сначала понять, что это Контракт является. Понимание контракта компонента является наиболее важной частью тестирования компонента реагирования. Договор определяет ожидаемое поведение вашего компонента, и какие предположения разумно иметь о своем использовании. Без четкого договора ваш компонент может быть трудно понять. Письменные тесты – отличный способ официально определить контракт вашего компонента.

Каждый реактивный компонент имеет по крайней мере одно, что способствует определению его договора:

  • Что это делает (что ничто не может быть)

Кроме того, эти вещи также влияют на большинство компонентных контрактов:

  • реквизит компонент получает
  • Составьте компонент удерживает (если есть)
  • Какой компонент делает, когда Пользователь взаимодействует с этим (через щелчок, перетаскивание, ввод клавиатуры и т. Д.)

Некоторые менее распространенные вещи, которые влияют на контракты компонентов:

  • Контекст компонент отображается в
  • Что делает компонент, когда вы звоните Методы на его экземпляре (Открытый интерфейс REF)
  • Побочные эффекты которые происходят как часть жизненного цикла компонента (ComponentDIDMount, ComponentWillunmount и т. Д.)

Чтобы найти контракт вашего компонента, задайте себе вопросы, такие как:

  • Что делает мой компонент?
  • Мой компонент представляет разные вещи в разных обстоятельствах?
  • Когда я передаю функцию в качестве опоры, в чем он использует мой компонент? Это называет это, или просто дайте его другому компоненту? Если он это называет, что это так называет?
  • Когда пользователь взаимодействует с моим компонентом, что происходит?

Найти контракт блокировки

Давайте пройдемся через LockScreen ‘s оказывать Способ и добавить комментарии в местах, где его поведение может отличаться. Вы будете искать тройки, если утверждения и высказывания высказывания как наши подсказки. Это поможет нам найти вариации в его договоре.

Мы выучили три ограничения, которые описывают LockScreen контракт:

  • Если Wallpasathate Проп пропущен, внешняя упаковка Div что компонент рендеры должен иметь Фоновое изображение Свойство CSS в его встроенных стилях, установленных на любой ценность Wallpasathate был, завернутый в URL (...) Отказ
  • Если UserInFomessage Проп пропущен, оно должно быть принято как дети до Topoverlay , который должен быть представлен с определенным набором встроенных стилей.
  • Если UserInFomessage опора не Прошло, нет Topoverlay должно быть сделано.

Вы также можете найти некоторые ограничения договора, которые всегда являются верными:

  • А Div всегда визуализируется, что содержит все остальное. Он имеет определенный набор встроенных стилей.
  • А ClockDisplay всегда оказывается. Это не получает никаких реквизитов.
  • А СЛУШАЙТЕУНЬЛОКС всегда оказывается. Получает значение прошлого окутел опоры как его Порыв опоры, независимо от того, если это было определено или нет.

Компонент Пропорты Также хорошее место для поиска подсказков к его договору. Вот еще несколько ограничений, которые я замечаю:

  • Wallpasathate Ожидается, что будет строка и не является обязательной.
  • UserInFomessage Ожидается, что будет строка и не является обязательной.
  • окутел Ожидается, что будет функция и не является обязательной.

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

Что стоит тестировать?

Давайте посмотрим на контракт, который мы нашли:

  • Wallpasathate Ожидается, что будет строка и не является обязательной.
  • UserInFomessage Ожидается, что будет строка и не является обязательной.
  • окутел Ожидается, что будет функция и не является обязательной.
  • А Div всегда визуализируется, что содержит все остальное. Он имеет определенный набор встроенных стилей.
  • А ClockDisplay всегда оказывается. Это не получает никаких реквизитов.
  • А СЛУШАЙТЕУНЬЛОКС всегда оказывается. Получает значение прошлого окутел опоры как его Порыв опоры, независимо от того, если это было определено или нет.
  • Если Wallpasathate ПРОГРАЖДЕНИЕ ПРОИЗВОДСТВА, ВНЕШНЯЯ УПРАВЛЕНИЕ ДИД, КОТОРЫЕ ОРУЖИВАЮТНОЕ ОРУЖИЕ Фоновое изображение Свойство CSS в его встроенных стилях, установленных на любой ценность Wallpasathate был, завернутый в URL (…) Отказ Если
  • UserInFomessage Проп пропущен, оно должно быть принято как дети до Topoverlay , который должен быть представлен с определенным набором встроенных стилей. Если
  • UserInFomessage опора не Прошло, нет Topoverlay должно быть сделано.

Некоторые из этих ограничений стоит тестирования, а другие нет. Вот три правила, которые я использую, чтобы определить, что что-то является Не стоит тестировать :

  1. Будет ли тест на Дубликат точно код приложения ? Это сделает это хрупким.
  2. Сделает утверждения в тесте дубликата любого поведения, которое является уже покрыты (и ответственностью) библиотечного кода ?
  3. С точки зрения аутсайдера, Эта деталь важна, или это только внутренняя забота ? Может быть описан эффект этой внутренней детали, используя только общедоступные API компонента?

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

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

  • Wallpasathate Ожидается, что будет строка и не является обязательной.
  • UserInFomessage Ожидается, что будет строка и не является обязательной.
  • окутел Ожидается, что будет функция и не является обязательной.

Эти ограничения являются обеспокоенностью Rection Пропорты Механизм, и поэтому писать тесты вокруг типов SPOP не удаются правило № 2 (уже охватывается библиотечным кодом). Как таковой, Я не проверяю типы опоры Отказ Поскольку тесты часто удваряются в качестве документации, я могу решить проверить то, что не удалось правило № 2, если код приложения не задокументировал ожидаемые типы очень хорошо, но Пропорты уже хорошие и читаемые человеком.

Вот следующее ограничение:

  • А Div всегда визуализируется, что содержит все остальное. Он имеет определенный набор встроенных стилей.

Это может быть разбито на три ограничения:

  • А Div всегда оказывается.
  • Оказанные Div содержит все остальное, что делает оказанные.
  • Оказанные Div имеет определенный набор встроенных стилей.

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

Игнорирование свойства фона-изображения, которое покрывается другим ограничением, обертыванием Div У этих стилей:

height: "100%",display: "flex",justifyContent: "space-between",flexDirection: "column",backgroundColor: "black",backgroundPosition: "center",backgroundSize: "cover",

Если мы написали тест, что эти стили были в Div, нам придется проверить ценность каждого стиля точно Для того, чтобы сделать полезные утверждения. Так что наши утверждения могут быть чем-то вроде:

  • Упаковочная дива должна иметь свойство стиля высоты 100%
  • Упаковочная Div должна иметь свойство стиля отображения Flex
  • … и так далее для каждого стиля свойства

Даже если мы использовали что-то вроде Tomatchobjec T Чтобы сохранить этот тест, это дублирует одни и те же стили в коде приложения и быть хрупким. Если мы добавили другой стиль, нам придется поставить точно такой же код в нашем тесте. Если мы настроим стиль, нам придется настроить его в наше тест, хотя поведение компонента не может измениться. Следовательно, это ограничение не удается правило № 1 (дублирует код приложения; хрупкий). По этой причине Я не проверю встроенные стили, если только они не могут измениться во время выполнения.

Зачастую, если вы пишете тест, который составляет «оно делает то, что он делает», или «это делает именно это, что происходит дублировать в код приложения», то тест либо не нужен, либо слишком широкий.

Вот следующие два ограничения:

  • А ClockDisplay всегда оказывается. Это не получает никаких реквизитов.
  • А СЛУШАЙТЕУНЬЛОКС всегда оказывается. Получает значение прошлого окутел опоры как его Порыв опоры, независимо от того, если это было определено или нет.

Это можно разбить в:

  • А ClockDisplay всегда оказывается.
  • Оказанные ClockDisplay не получает никаких реквизитов.
  • А СЛУШАЙТЕУНЬЛОКС всегда оказывается.
  • Когда прошло окутел опора определяется, отображаемый СЛУШАЙТЕУНЬЛОКС получает это ценность от того, что его Порыв пропры
  • Когда прошло окутел опора undefined , оказанные СЛУШАЙТЕУНЬЛОКС ‘s Порыв PROP также должен быть установлен на undefined Отказ

Эти ограничения попадают на две категории: «Оказывается какой-то компонент компонента», а «Изведомый компонент получает эти реквизиты». Оба очень важны для тестирования Как они описывают, как ваш компонент взаимодействует с другими компонентами. Мы проверим все эти ограничения.

Следующее ограничение:

  • Если Wallpasathate ПРОГРАЖДЕНИЕ ПРОИЗВОДСТВА, ВНЕШНЯЯ УПРАВЛЕНИЕ ДИД, КОТОРЫЕ ОРУЖИВАЮТНОЕ ОРУЖИЕ Фоновое изображение Свойство CSS в его встроенных стилях, установленных на любой ценность Wallpasathate был, завернутый в URL (…) Отказ

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

Последние два ограничения:

  • Если UserInFomessage Проп пропущен, оно должно быть принято как дети до Topoverlay , который должен быть представлен с определенным набором встроенных стилей.
  • Если UserInFomessage опора не Прошло, нет Topoverlay должно быть сделано.

Это можно разбить в:

  • Если UserInFomessage Проп пропущен, а Topoverlay должно быть сделано.
  • Если UserInFomessage Пропс проходит, его стоимость должна быть передана как дети для оказанных Tooloverlay.
  • Если UserInFomessage Проп пропущен, оказанные Topoverlay должны быть оказаны с определенным набором встроенных стилей.
  • Если UserInFomessage опора не Прошло, нет Topoverlay должно быть сделано.

Первое и четвертое ограничения (A Tooverlay должны/не должны быть оказаны) Опишите, что мы визуализируем, поэтому мы проверим их.

Второе ограничение проверяет, что Topoverlay получает определенный проп, основанный на значении UserInFomessage Отказ Важно писать тесты вокруг реквизитов, которые получают компоненты, поэтому мы проверим его.

Третье ограничение проверяет, что Topoverlay Получает определенный опоры, так что вы можете подумать, что мы должны проверить это. Тем не менее, этот опор – это только некоторые встроенные стили. Утверждает, что прошедшие реквизиты важно, но утверждения о встроенных стилях являются хрупкие и дублирует код приложения (не удается правило № 1). Потому что важно проверить прошедшие реквизиты, неясно, следует ли тестировать это, просто посмотрев на правило № 1; К счастью, вот почему у меня есть правление № 3. Как напоминание, это:

Когда я пишу тесты компонентов, я Только тестируйте публичное API компонента (в том числе побочные эффекты, которые API имеет на приложение), где это возможно. Точная планировка этого компонента не влияет на публичное API этого компонента; Это забота двигателя CSS. Из-за этого это ограничение не удается правило № 3. Потому что это не удается правило № 1 и правило № 3, Мы не будем проверить это ограничение , хотя он проверяет, что Topoverlay получает опоры, который обычно важен.

Трудно было определить, следует ли проверить это окончательное ограничение или нет. В конечном итоге, решать, какие части важны для тестирования; Эти правила Thumb I используем только рекомендации.

Теперь мы прошли все наши ограничения и знают, какие из них мы собираемся писать тесты для. Вот они:

  • А Div всегда оказывается.
  • Оказанные Div содержит все остальное, что делает оказанные.
  • А ClockDisplay всегда оказывается.
  • Оказанные ClockDisplay не получает никаких реквизитов.
  • А СЛУШАЙТЕУНЬЛОКС всегда оказывается.
  • Когда прошло окутел опора определяется, отображаемый СЛУШАЙТЕУНЬЛОКС получает это ценность от того, что его Порыв пропры
  • Когда прошло окутел опора undefined , оказанные СЛУШАЙТЕУНЬЛОКС ‘s Порыв PROP также должен быть установлен на undefined Отказ
  • Если Wallpasathate ПРОГРАЖДЕНИЕ ПРОИЗВОДСТВА, ВНЕШНЯЯ УПРАВЛЕНИЕ ДИД, КОТОРЫЕ ОРУЖИВАЮТНОЕ ОРУЖИЕ Фоновое изображение Свойство CSS в его встроенных стилях, установленных на любой ценность Wallpasathate был, завернутый в URL (…) Отказ Если
  • UserInFomessage Проп пропущен, а Topoverlay должно быть сделано. Если
  • UserInFomessage Пропс проходит, его стоимость должна быть передана как дети для оказанных Tooloverlay. Если
  • UserInFomessage опора не Прошло, нет Topoverlay должно быть сделано.

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

Настройка некоторой тестируемой котельной

Давайте начнем стипендировать тест для этого компонента. Я буду пользоваться Jest с фермент в моих тестах. Jest Работает отлично с реагированием И также является тестовым бегуном, включенным в приложения, созданные с помощью Create-React-App Так что вы уже можете быть установлены, чтобы использовать его. Enzyme – это зрелая библиотека тестирования на реагирование, которая работает в узле, так и в браузере.

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

Это много котельной. Позвольте мне объяснить, что я здесь настроил:

  • Я создаю Пусть Привязки для реквизит и MountedLockscreen так что эти переменные будут доступны для всего в Опишите функция.
  • Я создаю LockScreen Функция это доступно в любом месте в Опишите Функция, что использует MountedLockscreen Переменная для либо Гора А LockScreen С текущим реквизит или верните тот, который уже установлен. Эта функция возвращает фермент Regwrapper Отказ Мы будем использовать его в каждом тесте.
  • Я настроил Rebedeach что сбрасывает реквизит и MountedLockscreen Переменные перед каждым тестом. В противном случае состояние из одного теста будет утечке в другое. Установка MountedLockscreen к undefined Здесь, когда следующий тест работает, если он звонит LockScreen новый LockScreen будет установлен с текущим реквизит Отказ

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

Написание тестов!

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

  • А Div всегда оказывается.
  • Оказанные Div содержит все остальное, что делает оказанные.
  • А ClockDisplay всегда оказывается.
  • Оказанные ClockDisplay не получает никаких реквизитов.
  • А СЛУШАЙТЕУНЬЛОКС всегда оказывается.

Все ограничения до сих пор были вещи, которые являются всегда Правда, поэтому их тесты были относительно простыми для записи. Однако оставшиеся ограничения начинаются со слов, таких как «если» и «когда». Это подсказки, которые они являются условно правда, и поэтому мы соберем Опишите с Rebedeach проверить их. Именно здесь все, что тестируют котельной мы написали ранее, пригодится.

  • Когда прошло окутел опора определяется, отображаемый СЛУШАЙТЕУНЬЛОКС получает это ценность от того, что его Порыв пропры
  • Когда прошло окутел опора undefined , оказанные СЛУШАЙТЕУНЬЛОКС ‘s Порыв PROP также должен быть установлен на undefined Отказ

Когда нам нужно описать поведение, которое происходит только в определенном состоянии, мы можем Опишите это состояние, а затем использовать Rebedeach внутри этого Опишите установить это условие вверх.

  • Если Wallpasathate ПРОГРАЖДЕНИЕ ПРОИЗВОДСТВА, ВНЕШНЯЯ УПРАВЛЕНИЕ ДИД, КОТОРЫЕ ОРУЖИВАЮТНОЕ ОРУЖИЕ Фоновое изображение Свойство CSS в его встроенных стилях, установленных на любой ценность Wallpasathate был, завернутый в URL (…) Отказ
  • Если UserInFomessage Проп пропущен, а Topoverlay должно быть сделано.
  • Если UserInFomessage Пропс проходит, его стоимость должна быть передана как дети для оказанных Tooloverlay.
  • Если UserInFomessage опора не Прошло, нет Topoverlay должно быть сделано.

Это все наши ограничения! Вы можете просмотреть окончательный тестовый файл здесь Отказ

«Не моя работа»

При взгляде на анимированные GIF в начале статьи вы, возможно, ожидали, что наши тестовые случаи в конечном итоге как нечто вроде:

  • Когда пользователь перетаскивает разблокировку спиртной разблокировки, весь путь вправо, вызывается обратный вызов разблокировки
  • Если пользователь перетаскивает разблокировку с разблокировкой вправо, а затем выпускает его, ручка анимируется обратно в исходное положение
  • Часы в верхней части экрана всегда должны показывать текущее время

Эта интуиция естественная. С точки зрения приложения, это некоторые из самых заметных функций.

Тем не менее, мы не закончили письменные тесты для любой из этой функциональности. Почему? Они были Не забота LockScreen Отказ

Поскольку компоненты React представляют собой многоразовые единицы, агрегаты являются естественными для них. И когда тестирование подразделения, Вы должны проверить только то, что ваша настоящая единица заботится о Отказ Лучше видеть деревья, чем лес при написании тестов в реактивный компонент.

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

  • Что мне делать с реквизитами, я получаю?
  • Какие компоненты я визуализации? Что я передаю к этим компонентам?
  • Я когда-нибудь держу что-нибудь в штате? Если это так, я неинфицитую его при получении новых реквизитов? Когда мне обновлять состояние?
  • Если пользователь взаимодействует со мной или дочерним компонентом, вызывает обратный вызов, который я передал ему, что мне делать?
  • Что-нибудь случится, когда я смонтирован? Когда я отключается?

Особенности, описанные выше, являются опасениями СЛУШАЙТЕУНЬЛОКС и ClockDisplay Таким образом, тесты вокруг этих функций будут пойти в тесты для тех компонентов, а не здесь.

Резюме

Я надеюсь, что эти методы помогут вам написать свои собственные тесты на реактивный компонент. Обобщить:

  • Найти свой компонентный контракт первым
  • Решить, какие ограничения стоит тестирования, и которые не
  • Типы опоры не стоит тестирования
  • Встроенные стили обычно не стоит тестирования
  • Компоненты, которые вы представляете и какие реквизиты вы их даете, важно проверить
  • Не тестируйте вещи, которые не являются заботой вашего компонента

Если вы не согласны или нашли этот пост полезным, я хотел бы услышать от вас в твиттере Отказ Давайте все научимся проверять компоненты реагирования вместе!

Хотя эта статья лицензирована, все права защищены, все образцы кода в этой статье доступны в соответствии с лицензией MIT, как найдено в их репозитории источника на Github .