Найти в Дзене
Библиотека программиста

🧪 Успешное тестирование: основы и передовые приемы Jest. Часть 1

Знаком с ситуацией, когда после деплоя все падает, а ты не знаешь почему? В этой статье я показываю, как из обычного разработчика стать профи в тестировании с Jest. Разобрал все от и до: настройка проекта, базовые тесты, моки и даже асинхронщина. Плюс весь код доступен на GitHub – бери и используй! Если тестирование вызывает у тебя дрожь – этот гайд изменит твою жизнь. Привет, друзья! Я Кирилл Мыльников, frontend-разработчик в ГК Юзтех. Сегодня хочу поделиться своей экспертизой в тестировании с использованием фреймворка Jest. Полностью настроенный проект будет доступен на GitHub, где вы сможете ознакомиться с ним и клонировать его. Мы рассмотрим широкий спектр тем – от базовых до продвинутых приёмов тестирования. Статья будет полезна как для тех, кто хочет освежить свои знания, так и для новичков, только начинающих погружаться в мир тестирования. Также отмечу, что статья состоит из нескольких частей. В серии статей разберем следующие темы: Jest основы: Особенности Jest: Прежде чем прис
Оглавление

Знаком с ситуацией, когда после деплоя все падает, а ты не знаешь почему? В этой статье я показываю, как из обычного разработчика стать профи в тестировании с Jest. Разобрал все от и до: настройка проекта, базовые тесты, моки и даже асинхронщина. Плюс весь код доступен на GitHub – бери и используй! Если тестирование вызывает у тебя дрожь – этот гайд изменит твою жизнь.

Привет, друзья! Я Кирилл Мыльников, frontend-разработчик в ГК Юзтех. Сегодня хочу поделиться своей экспертизой в тестировании с использованием фреймворка Jest. Полностью настроенный проект будет доступен на GitHub, где вы сможете ознакомиться с ним и клонировать его. Мы рассмотрим широкий спектр тем – от базовых до продвинутых приёмов тестирования. Статья будет полезна как для тех, кто хочет освежить свои знания, так и для новичков, только начинающих погружаться в мир тестирования. Также отмечу, что статья состоит из нескольких частей.

В серии статей разберем следующие темы:

Jest основы:

  • структура тестов;
  • виды проверок;
  • настройка и запуск.

Особенности Jest:

  • моки и для чего они нужны;
  • тестирование ошибок и покрытие кода.

Прежде чем приступим к практике, давайте вспомним, какие виды тестирования существуют.

👨‍💻🎨 Библиотека фронтендера

Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека фронтендера»

Виды тестирования

Unit-тесты

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

Интеграционное тестирование

Интеграционное тестирование — это тестирование на работоспособность двух или более модулей системы. Они решают проблему после покрытия кода unit-тестов, проверяют, как ведут себя связные модули.

End to End

End to End — это метод тестирования, который проверяет полностью функциональности ПО от начала до конца, включает в себя проверку всех уровней системы, начиная от пользовательского интерфейса и заканчивая базой данных и серверной логикой. В основном, это робот, имитирующий пользователя.

UI тестирование

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

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

   Стратегия тестирования
Стратегия тестирования

Когда проект уже существует, стратегия тестирования может быть адаптирована. В таких случаях часто начинают с проведения end-to-end тестов для проверки работы приложения в целом. Затем переходят к интеграционным тестам, чтобы убедиться в правильном взаимодействии компонентов. И только после этого фокусируются на unit-тестах, чтобы покрыть отдельные части логики приложения. Такой подход помогает обеспечить надёжное тестирование всего приложения в целом перед более детальной проверкой отдельных компонентов.

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

Jest

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

Основные возможности:

  • Детальное описание причин падения тестов;
  • Наличие полноценного набора инструментов из коробки;
  • Быстрый и надёжный запуск тестов в параллельных потоках;
  • Работа с проектами, использующими Babel, Rect, Vue, Angular, TypeScript, Node;
  • Можно писать как и unit-тесты, так и интеграционные;
  • Инструменты для имитации.

Вообще, у нас будет два отдельных проекта-примера, один естественно с React (реализация будет в другой статье), а другой просто настроим с нуля.

Создаём папку, где у вас будет проект, и инициализируем проект, в моём случае с помощью команды:

Должна появиться такая структура:

-2

После чего нужно будет установить сам пакет Jest с помощью команды:

Как говорится в документации Jest, для расширенных настроек понадобится установить ещё ряд пакетов:

После установки всех необходимых пакетов создаём файл babel.config.js в корневой директории проекта и указываем необходимые конфигурационные параметры. Если мы хотим использовать TypeScript, мы должны установить соответствующий пакет и добавить соответствующую зависимость в наш файл конфигурации:

Не забывайте про важную деталь: чтобы Jest проверял типы по мере их выполнения, нужно установить ещё один пакет ts-jest и для предоставления глобальных типов @types/jest

Давайте пока переключимся на конфигурацию Jest. В корне проекта создаём jest.config.ts и указываем следующую настройку:

Опция verbose: true обеспечивает более подробный вывод информации при запуске тестов в случае возникновения проблем.

Используем preset: “ts-jest” для преобразования TypeScript в JavaScript перед запуском тестов.

Также импортируем тип Config для получения подсказок о других доступных настройках в целом.

Можно теперь проверить, запускаются ли тесты вообще. В package-json указываем команду:

Создаём файл utils, в котором содержится функция, выполняющая деление двух чисел. Нам необходимо протестировать эту функцию, поэтому создаём файл utils.test.ts и пишем первый тест.

И запускаем с помощью команды yarn start. Если всё настроили правильно, то должно быть так:

-3

В одном файле можно создавать произвольное количество тестов, используя директивы test или it. Хорошей практикой является начинать названия тестов с ключевого слова "should", чтобы чётко определить ожидаемое поведение. Это способствует пониманию того, что тестируется, и повышает читаемость кода. Кроме того, использование describe() для группировки тестов помогает упорядочить и структурировать код, делая его более ясным и лёгким для поддержки. Важно быть особенно внимательным к именованию тестов, чтобы обеспечить их эффективную организацию и понимание.

Пример:

Результат:

-4

Давайте разберём, что такое expect. Это глобальная функция, в которую мы передаём определённый результат и которая возвращает нам объект с разными вариантами проверок. Основные проверки, которые используются:

toBe() — работает как тройное сравнение, идёт проверка на true/false, хорошо подходит для примитивов:

toEqual() — работает с объектами, сравнивает и возвращает true, если равны объекты, в противном случае false.

toHaveLength() — проверяет длину массива.

toContain() — проверяет, есть ли конкретный элемент в массиве.

toBeUndefined() и toBeNull() — проверяют результат на null/undefined.

Думаю, суть вы поняли, проверок достаточно много. О них можно почитать в официальной документации Jest.

Статья по теме

🛠 Тестирование JavaScript: все, что нужно знать

Параметризованные тесты

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

Возможности test и it включают методы, такие как skip, который позволяет игнорировать определенный тест, и only, который позволяет выполнять только выбранные тесты, оставляя остальные в игноре. Эти функции облегчают управление тестами.

only:

-5

skip:

-6

Этих методов у нас достаточно много. Подробнее можете посмотреть в официальной документации Jest.

Особенности Jest

Mocks — это фейковые данные, которые нужны для тестового кейса.

Spies — отслеживание работы методов.

Функции-фейки нужны для тестирования количества вызовов колбэков.

Что такое моки (mocks)?

Давайте рассмотрим пример тестирования с мок-данными. У нас есть функция, которая фильтрует массив:

Пример:

  • В первом случае мы проверяем, что функция не была вызвана;
  • Во втором случае мы проверяем, что функция была вызвана, получила массив и вернула количество вызовов;
  • В третьем случае мы используем предоставленные мок-данные для возвращения отфильтрованного массива.

Те самые мок-данные можно посмотреть тут, где result_mocks_data — результат после фильтрации, mocks_data — просто мок-данные, которые получает функция.

Результат:

-7

Следующее, что мы с вами разберём, это Spies

Spies

Spies используют для отслеживания вызовов конкретных функций с целью убедиться, что они были вызваны или вызваны с определенными параметрами. Рассмотрим следующий случай: мы хотим отследить console.log, который используется в нашем цикле. Для этого мы можем использовать метод spyOn, который принимает два аргумента. Первый аргумент — это объект, за которым мы хотим следить (в данном случае это console), а второй аргумент — это метод объекта, за которым мы хотим следить (например, log).

Пример:

Результат:

-8

Мы видим конкретные элементы массива.

Тестирование асинхронного кода

Давайте создадим асинхронную функцию, которая будет создавать нам что-то:

И сразу напишем тесты к данной функции:

Пример:

Далее в тесте используем метод mockReturnValueOnce, чтобы задать поведение моковой функции fetch. Мы возвращаем объект с флагом ok: true и методом json, который возвращает объект задачи из тестовых данных.

Мок-данные, которые мы ожидаем, в ответе.

Пример:

Тестирование ошибок

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

В функции createTodoAsync ожидаем, что если ошибка, то выводим текст «Ошибка создания задачи».

Пример:

В данном примере изменили мок-данные на значение ok: false и ожидаем появления ошибки с конкретным текстом, который определён в функции.

Покрытие кода тестами

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

Чтобы начать собирать статистику тестов по проекту, нам нужно прописать дополнительные настройки в файле jest.config.ts

Прописываем такое свойство:

Этим свойством мы разрешаем сбор информации, по умолчанию — false.

Дальше прописываем:

Указываем в виде массива пути, которые мы хотим протестировать или не хотим. К примеру, всё, что начинается со знака "!", мы отмечаем как папки или файлы, которые будут проигнорированы.

Если всё сделали правильно, запускаем тесты и проверяем статистику.

Результат:

-9

Теперь мы видим, что протестировано, а что нет. Написано, где именно, например, в файле createTodo забыли протестировать функцию.

Давайте напишем для неё тесты и опять запустим.

Тесты к функции.

Запускаем снова тесты.

Результат:

-10

Также обратите внимание, что в корне проекта у нас создалась папка coverage, там находится вся информация о тестах.

-11

Больше всего нас интересует index.html который нам нужно открыть.

-12

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

Пример:

-13

Также в конфиге можем указать пороговые значения тестов для нашего проекта:

Запускаем и видим, что мы не прошли порог по тестам.

Результат:

-14

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

Материалы

Jest https://jestjs.io/

GitHub https://github.com/kirill0202/Jest