Когда тестов и файлов с тестами становится много, возникают новые вопросы. Как группировать тесты? Как запустить на выполнение все тесты из одной директории? Если их очень много и они долгие, можно ли запустить их параллельно?
Для решения этих вопросов используют специальные тестовые фреймворки. Они помогают организовать структуру тестов и дают много полезного, например, удобный вывод. С большинством из этих возможностей мы познакомимся далее по курсу. В JavaScript-мире наиболее популярен фреймворк Jest, разрабатываемый компанией Facebook. К слову, с помощью него мы тестируем все практики на Хекслете.
Ниже находится инструкция, в которой мы создадим с нуля npm-проект и добавим в него тесты.
Создайте где-нибудь на вашем компьютере директорию с названием hexlet-jest. Зайдите в неё и выполните команду:
npm init
Ответьте на все вопросы запущенного скрипта инициализации проекта. Убедитесь, что в корне проекта появился файл package.json.
Теперь добавим немного исходного кода. Создайте файл src/index.js с таким содержимым:
// Эта функция переворачивает переданную строку
export default str => str.split('').reverse().join('');
Jest — обычный npm-пакет, который локально подключается в разрабатываемый проект. Jest нужен только во время разработки, поэтому лучше установить его в секцию devDependencies:
# В директории с проектом
npm i --save-dev jest
Чтобы Jest корректно работал с системой модулей, добавьте в package.json следующую опцию:
"type": "module"
Jest ожидает, что тесты находятся в директории __tests__, которую обычно располагают в корне проекта. Внутри этого каталога можно создавать любую структуру, Jest найдёт все тесты, которые там лежат. Именование файлов с тестами должно быть таким: <name>.test.js
. Где <name>
, как правило, соответствует имени модуля, который тестируется.
Напишем наш первый тест. Создайте файл __tests__/index.test.js со следующим содержимым:
import reverse from '../src/index.js';
test('reverse', () => {
expect(reverse('hello')).toEqual('olleh');
expect(reverse('')).toEqual('');
});
Далее мы разберём структуру этого файла, а пока попробуем запустить тест на выполнение:
# Jest поддерживает ECMAScript модули в экспериментальном режиме
# Чтобы активировать поддержку модулей в тестах,
# нужно запускать тесты с переменной окружения NODE_OPTIONS
NODE_OPTIONS=--experimental-vm-modules npx jest
PASS __tests__/index.test.js
✓ reverse (11ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.166s
Ran all test suites.
https://replit.com/@hexlet/js-testing-jest-1#__test__/index.test.js
Ура! Тесты прошли успешно.
Давайте ещё раз посмотрим на файл с тестом:
import reverse from '../src/index.js';
test('reverse', () => {
expect(reverse('hello')).toEqual('olleh');
expect(reverse('')).toEqual('');
});
Для тестов Jest предоставляет две глобальные функции: test
и expect
. Они доступны без какого-либо импорта, так как Jest делает их глобальными функциями.
Функция test
нужна для описания конкретного теста и его проверок. Самих тестовых функций может быть любое количество. Первым параметром эта функция принимает произвольную строчку, которая должна описывать сам тест. Эта строчка потом отображается на экране во время запуска тестов для упрощения отладки.
NODE_OPTIONS=--experimental-vm-modules npx jest
PASS __tests__/index.test.js
✓ reverse (11ms) # название теста
Второй параметр — функция, внутри которой описан проверочный код. Обратите внимание на то, что этот код не выполняется сразу. Функция test
добавляет его внутрь Jest, который уже решает, как и когда запускать тесты. Это позволяет проводить различные оптимизации, например, выполнять тесты параллельно.
Самое необычное в этом коде — проверки. Jest использует «матчеры» (matchers). Это утверждения, имеющие особую структуру, напоминающую обращение к объекту. Общий принцип работы матчеров такой:
expect()
, куда передаётся актуальное (фактическое) значение.expect()
, вызывается подходящий матчер, например, toEqual
.Код с матчерами похож на обычные предложения на английском языке. Это сделано специально, чтобы их могли читать даже не программисты:
// Ожидается, что результат выражения reverse('hello') равен 'olleh'
expect(reverse('hello')).toEqual('olleh');
Подробнее о матчерах в следующем уроке.
Одна из приятнейших особенностей Jest — то, как он выводит сообщения о проваленных проверках. Попробуйте внести ошибку в исходную функцию и запустите тесты заново:
NODE_OPTIONS=--experimental-vm-modules npx jest
FAIL __tests__/index.test.js
✕ reverse (9ms)
● reverse
expect(received).toEqual(expected) // Object.is equality
Expected: "olleh"
Received: "o|l|l|e|h"
3 | test('reverse', () => {
4 | const str = 'hello';
> 5 | expect(reverse(str)).toEqual('olleh');
| ^
6 | })
7 |
at Object.toEqual (__tests__/index.test.js:5:24)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 1.683s
Ran all test suites.
В этом выводе показаны не только ожидаемое и фактическое значение, но и исходный код файла с тестами с указанием на конкретную проверку. Это невероятно полезная фишка, которая значительно ускоряет анализ результатов тестирования и помогает в отладке.
Пример полностью настроенного пакета: https://github.com/hexlet-boilerplates/nodejs-package
Вам ответят команда поддержки Хекслета или другие студенты
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
Наши выпускники работают в компаниях:
Зарегистрируйтесь или войдите в свой аккаунт