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

Задумывались о разработке приложения React с использованием разработки через тестирование (TDD) или ваш клиент хочет, чтобы в проекте были тесты? Если вы не знаете, с чего начать, это хорошее место для начала!

Перво-наперво я создам проект с помощью create-react-app и добавлю следующие пакеты:

  • фермент (для поверхностной визуализации компонентов)
  • react-test-renderer (для проверки снимков)
  • redux, react-redux и redux-thunk (потому что мы будем тестировать действия и редукторы)
  • redux-actions (упростите создание действий и их обработку в редукторе)
  • redux-mock-store (очевидно, чтобы издеваться над нашим магазином redux)
  • jest-fetch-mock (для имитации различных выборок)

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

Для этого мы будем использовать этот API http://api.adviceslip.com/, чтобы помочь сгенерировать эти полезные советы.

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

Итак, теперь у нас есть скелет, и мы хотим начать работу над этими тестами. Перво-наперво, мы начнем с действий redux.

Эти тесты можно разделить на две категории: действия и асинхронные действия. Первый набор тестов, даже если они не очень полезны, - это проверка сгенерированного объекта, переданного в отправку. Поскольку мы используем redux-actions, это предотвратит некоторые ошибки, если вы сделаете это явно.

Действия

Итак, вот наш создатель действий, расположенный в файле Action.js:

Теперь для тестирования этого кода сначала нужно создать файл с тем же именем, что и Action, но с расширением «.test», так что в данном случае это будет Action.test.js. Создав файл, мы импортируем в него все наши действия. Затем вызовите функцию описать, чтобы узнать, какой раздел тестов мы создаем. После этого мы вызываем функцию it ( описание, функция для проверки кода), где первый аргумент - это строка для идентификации теста, а второй - функция, в которой мы будем проверять код. . Посмотрите следующий пример, чтобы понять, как это сделать:

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

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

Асинхронные действия:

Эти тесты действий не самые полезные и полезные, за исключением очень специфических случаев. Существуют более полезные тесты действий, которые помогут вам убедиться, что ваше приложение не сломается из-за разных ответов от API. Это называется асинхронными действиями. Эти действия будут иметь обещание разрешить и могут иметь более одного действия. Например, если вы делаете запрос, вы можете использовать три разных типа действий: запрос, неудачный ответ и действие успешного ответа. Это может быть полезно, когда вашему приложению необходимо изменить свое состояние при получении данных.

Итак, давайте снова начнем работать над этим.

Первое, что нужно сделать, это импортировать jest-fetch-mock, чтобы имитировать наши вызовы API, и redux-mock-store, чтобы имитировать наш магазин для каждого теста. Как только это будет сделано, мы инициализируем каждую переменную нужными нам фиктивными данными, а затем запустим тест.

Как вы можете видеть в приведенном выше примере, чтобы протестировать наши асинхронные действия, мы начали с вызова «mockResponse» с ответом. Это отменит каждую выборку, вызванную вашим тестом. Как только это будет сделано, мы создали ожидаемые действия, вызвав getRandomAdvice. После этого мы отправим эту функцию в наше фиктивное хранилище, а затем проверим, совпадают ли сгенерированные действия с ожидаемыми.

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

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

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

Редукторы:

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

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

Например, если мы применим действие «REQUEST_ADVICE» к состоянию, в этом случае это состояние будет иметь «fetching» на false и «randomAdvice» до нуля. Мы надеемся, что новый объект будет возвращен с переменной выборки как истина и «randomAdvice» с тем же результатом, что и в предыдущем состоянии. Это должно происходить всегда, и таким образом мы можем проверить, правильно ли мутирует действие в новое состояние.

Следует отметить, что вам не нужно создавать все переменные в своем состоянии. Если действие влияет только на какую-то переменную, вы можете просто использовать его, как показано в тесте «RESPONSE_ADVICE_FAILURE».

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

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

Компонентные тесты:

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

Итак, как вы можете видеть ниже или в проекте GitHub, у нас есть основной компонент приложения. В нем есть одно поле ввода и две кнопки, одна для поиска совета на основе введенного значения, а вторая для выдачи случайного совета. Итак, здесь мы видим три метода, один из которых - defineLabelAdvice, который возвращает метку в зависимости от того, есть у вас значение или нет.

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

Итак, как вы можете видеть здесь, у нас есть тест, чтобы проверить, вернет ли метод «defineLabelAdvice правильную строку. Когда мы вызываем его, мы ожидаем, что возвращаемое значение будет «Это случайный совет», потому что он не имеет значения во входных данных. Но это было бы недостаточно хорошим тестом, если бы вы не тестировали функцию для каждого случая. Вот почему я вызвал функцию setState для обновления состояния и снова вызвал функцию, и, как вы можете видеть, ожидаемая метка должна быть другой.

После того, как вы закончите проверку этих тестов, вы также заметите, что у нас есть снимки, чтобы проверить, используется ли этот совет в HTML. Если некоторые условия изменяются, снимки могут не работать, и в некоторых случаях вам следует проверить их перед обновлением. С помощью снимков вы тестируете HTML, созданный этим компонентом. Я делал это в каждом тесте, потому что таким образом мы также проверяем, отображается ли правильная метка. И это покрывает часть компонентного теста. Вы также можете использовать такие функции, как дети в мелком результате, чтобы проверить, сколько у вас элементов. Это полезно для списков или если вы генерируете код из карт. Вы можете проверить другие примеры в документации по ферментам https://airbnb.io/enzyme/docs/api/.

Чтобы завершить наши тесты, нам нужно знать покрытие нашего кода. У вас есть два способа сделать это. Либо вы устанавливаете пакет, либо, если вы используете response-create-app, вы можете использовать встроенные скрипты. Чтобы получить к ним доступ, вам нужно извлечь свой проект (проверьте эту ссылку, чтобы понять, что он делает) и добавить следующую строку в свой package.json:

“coverage”: “node scripts/test.js — env=jsdom — coverage”,

После того, как вы его получили, вы можете запустить покрытие, используя «npm run cover». В результате будет создана папка под названием «Покрытие» с отчетом внутри нее.

В Runtime Revolution мы серьезно относимся к своему делу и всегда делаем все возможное, чтобы предоставить надежный, обслуживаемый и тестируемый продукт. У вас есть проект, который нужно развивать, или продукт, который вы хотите выпустить? Мы будем рады вам помочь!