Поиск по сайту:

Как начать работу с Jest для модульного тестирования JavaScript


Jest — это фреймворк для запуска «модульных тестов», позволяющий вам тестировать отдельные функции и компоненты из вашей кодовой базы, чтобы гарантировать, что будущие коммиты не сломают что-то неожиданное. Мы покажем вам, как его настроить и использовать с интерфейсной средой, такой как React.

Что такое модульное тестирование?

Тестирование очень важно при работе с командой программистов — любые коммиты, переданные в систему управления версиями, должны автоматически создаваться и тестироваться, чтобы убедиться, что вы ничего не сломаете случайно. Чтобы все были в здравом уме, весь конвейер можно автоматизировать с помощью программного обеспечения, такого как Jenkins, но для запуска реальных тестов вам потребуется использовать среду модульного тестирования, такую как Jest.

Jest — это фреймворк для запуска «модульных тестов». «Единицей» может быть что угодно — функция, класс или компонент — она просто представляет собой наименьшую единицу кода, которую вы должны тестировать, чтобы убедиться, что будущие обновления кода ничего не сломают. Если вы напишите функцию, которая извлекает некоторые данные из конечной точки и возвращает некоторый результат, вы напишете соответствующий модульный тест, который будет принимать эту функцию, вызывать ее и регистрировать выходные данные. Затем вы можете делать утверждения на основе того, что он вернул. Он правильно отформатирован? Какие-либо значения не определены? Работает ли он так, как ожидалось? Если какой-либо из этих тестов не проходит, что-то не так в вашем коде.

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

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

Начало работы с Jest

Чтобы настроить простую среду тестирования, создайте новый проект с помощью npm init -y и установите Jest в качестве зависимости разработки от npm:

npm install --save-dev jest

Чтобы запускать тесты из командной строки, вам нужно добавить простой скрипт в package.json, который вызывает Jest:

"scripts": {
  "test": "jest"
}

Вам понадобится функция для тестирования, поэтому создайте новый файл в разделе src/doSomeMath.js и настройте его для экспорта функции:

function doSomeMath(a, b) {
  return a + b;
}

module.exports = doSomeMath;

Сохраните этот файл и откройте tests/doSomeMath.test.js. Jest автоматически просматривает каталог test/, чтобы найти тесты для запуска. Этот файл служит дополнением к doSomeMath.js и определяет набор тестов для проверки правильности работы всех функций. Базовый тест Jest выглядит примерно так:

test('Description', () => {
  expect(functionName(args)).toBe(result);
});

По сути, функция test() оборачивает весь код теста. Каждый блок expect() вызывает функцию (т. е. единицу измерения), а затем передает значение «сопоставителю». В данном случае это функция toBe(), которая проверяет простое равенство.

В Jest есть множество различных сопоставителей, о которых вы можете прочитать в их документации. Назвать несколько:

  • .not.matcher() обрабатывает инверсию любого сопоставителя.
  • toBe() проверяет точное равенство (Object.is), но не обрабатывает объекты.
  • toEqual() проверяет глубокое равенство объектов.
  • toStrictEqual() то же самое, что и toEqual , но также гарантирует, что ни один из объектов не имеет дополнительных неопределенных свойств.
  • toBeTruthy() и toBeFalsy() проверяют все, что оценивается как true или false в if оператор.
  •  toBeNull() , toBeUndefined() и toBeDefined() проверяют различные состояния объектов.
  • toContain() проверяет содержимое массива.
  • toMatch() сопоставляет регулярное выражение со строкой.
  • toThrow() гарантирует, что код выдаст ошибку (обычно для проверки неправильного ввода).

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

const doSomeMath = require('../src/doSomeMath');

test('adds 2 + 2 to equal 4', () => {
  expect(doSomeMath(1, 1)).toBe(2);
  expect(doSomeMath(2, 2)).toBe(4);
});

Сохраните этот файл, затем запустите:

npm run test

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

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

Поскольку код Jest — это всего лишь JavaScript, вы можете легко создавать сценарии для своих тестов. Например, вы можете использовать цикл for и несколько раз вызывать expect с итеративным вводом. Если какое-либо выполнение expect не удается, то и сам тест не будет выполнен.

test('adds 2 + 2 to equal 4', () => {
  for (let a = 1; a < 10; a++) {
   expect(doSomeMath(a, 5)).toBe(a + 5)
  }
});

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

  • Упорядочить, где готовятся данные для объекта
  • Действие, когда модуль вызывается, передается упорядоченные данные, а выходные данные регистрируются
  • Утвердить, где вы запускаете все свои сопоставители, чтобы убедиться, что все работает так, как задумано

Тестирование с помощью React

Убедиться, что математика работает, — это круто и все такое, но вы, вероятно, не собираетесь использовать Jest для чего-то такого простого. Вы, вероятно, заинтересованы в использовании Jest для автоматизации тестирования приложения JavaScript, возможно, созданного с помощью такой среды, как React. Хотя вам по-прежнему следует выполнять полное тестирование пользовательского интерфейса с ручной проверкой, Jest все еще можно использовать для изолированного тестирования компонентов React. В конце концов, компоненты React — это просто функции, которые возвращают вывод JSX — это можно сопоставить и протестировать.

Для начала создайте новый проект React с помощью create-react-app:

npx create-react-app jest-react

Приложение Create React устанавливает Jest по умолчанию, а также библиотеку тестирования React, которая содержит несколько полезных обработчиков для работы с React в Jest.

Измените компонент App.js по умолчанию следующим образом:

import React, {useState} from 'react';
import './App.css';

function App() {
  const [disabled, setDisabled] = useState(false);

  function handleClick() {
    setDisabled(!disabled);
  }

  return (
    <button data-testid="useless-button" disabled={disabled} onClick={handleClick}>
      Click Me
    </button>
  );
}

export default App;

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

Откройте App.test.js, который уже создан Create React App, чтобы содержать тест для логотипа React по умолчанию. Вместо этого измените тест по умолчанию на следующее:

import React from 'react';
import { render, fireEvent } from '@testing-library/react';

import App from './App';

test('disabled button on click', () => {
  const button = render(<App />).getByTestId('useless-button');

  expect(button.disabled).toBeFalsy();

  fireEvent.click(button, {button: 1});

  expect(button.disabled).toBeTruthy();
});

Этот тест отображает компонент с помощью рендеринга библиотеки тестирования React и находит кнопку на основе идентификатора теста, который мы ей предоставили (хотя существует множество различных селекторов, которые не будут загромождать ваш код компонента). Он следит за тем, чтобы кнопка не была отключена сразу, а затем запускает событие щелчка. (Обратите внимание, что {button: 1} – это просто код для щелчка левой кнопкой мыши.) Состояние обновляется, что вызывает повторную визуализацию, и мы снова проверяем, что кнопка теперь отключена.

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