Автор оригинала: 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должно быть сделано.
Некоторые из этих ограничений стоит тестирования, а другие нет. Вот три правила, которые я использую, чтобы определить, что что-то является Не стоит тестировать :
- Будет ли тест на Дубликат точно код приложения ? Это сделает это хрупким.
- Сделает утверждения в тесте дубликата любого поведения, которое является уже покрыты (и ответственностью) библиотечного кода ?
- С точки зрения аутсайдера, Эта деталь важна, или это только внутренняя забота ? Может быть описан эффект этой внутренней детали, используя только общедоступные 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 .