В Springload мы влюблены в использование React для создания богатого опыта. Одна из задач, которую решает React, — сделать модульные тесты подходящими для пользовательских интерфейсов. Недавно мы решили перенести наши тесты на Jest (среда тестирования, также созданная Facebook), чтобы еще больше использовать это. Jest был создан для особенно хорошей работы с React и поставляется с захватывающими функциями, которые заставили нас отказаться от нашей существующей комбинации Mocha и Chai. Читайте дальше, чтобы узнать, как мы перешли на React, и узнать больше о функции моментальных тестов Jest, которая заставила нас почувствовать: 😎

Меньше движущихся частей, больше удовольствия

Переход между Mocha и Jest совсем не сложен. На самом деле, в зависимости от того, насколько сложны ваши тесты, вы даже можете запустить тест напрямую с помощью Jest. Без шуток.

Но сначала давайте поговорим о том, почему мы вообще решили перейти на Jest. Комбинация Mocha и Chai очень хорошо работает для ванильного кода JavaScript, используемого в качестве модели данных, бизнес-логики и утилит. Но мы также используем JavaScript для компонентов пользовательского интерфейса, и мы также хотим быть уверенными в этом коде. Но сделать все это с мокко и чаем становится сложно (синон, энзим и другие вызывают у нас такие же головные боли!).

В зависимости от его сложности вам может понадобиться много разных пакетов, которые работают вместе, чтобы правильно протестировать компонент React. Jest более интегрирован, поэтому вы можете работать очень далеко без каких-либо дополнительных пакетов, и именно эта бесшовная интеграция делает процесс таким безболезненным. С Mocha и Chai даже после установки и настройки всех пакетов довольно сложно поддерживать набор тестов. Посмотрите на этот пример кода теста компонента React, чтобы понять, что я имею в виду:

it('it should have an animal class', () => {
  expect(shallow(<Animal sound={testSound} />).find('div').first().props().className)
    .to.equal('animal');
});

А вот и аналогичный код с Jest:

it('it should have an animal class', () => {
  expect(shallow(<Animal sound={testSound} />)).toMatchSnapshot(); });

Я точно знаю?! Это почти шокирующе легко! Это магия шутки.

Более быстрые и надежные тесты

Одним из преимуществ Jest является скорость. Jest запускает тесты параллельно, что значительно ускоряет выполнение всего набора тестов. Кроме того, у вас есть возможность использовать «— watch» и запускать только те тесты, на которые повлияли ваши изменения в редакторе. Функция покрытия также впечатляет. Это дает вам приятный и простой рендеринг прямо в вашей консоли после запуска команды покрытия и стандартных отчетов LCOV.

Узнайте больше о различных опциях Jest CLI.

Суть миграции

Все примеры кода в следующем разделе доступны в виде репозитория GitHub: springload/mocha-chai-to-jest

Импорт

Jest решил сделать все служебные функции тестирования (describe и it для структурирования тестовых случаев, а также утилиты для создания шпионов и макетов) доступными в глобальной среде. Так что импорта не надо!

Утверждения

Если вы изначально использовали синтаксис ожидания Chai, вы будете чувствовать себя как дома с этими утверждениями. Однако есть небольшие отличия в синтаксисе — сопоставители Jest основаны на Jasmine.

Например: .to.be.true в Mocha/Chai становится .toBeTruthy() в Jest.

То же самое касается: .to.be.false -> .toBeFalsy()

Другая сложная задача — .to.be.equal(var). Используя Jest, у вас есть два варианта:

  1. .toBe(var), который сравнивает по ссылке (например, «===»).
  2. .toEqual(var), который сравнивает объекты по значению. Это идеально, если вы хотите убедиться, что все свойства объекта совпадают.

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

Таймеры и макеты

С Mocha самый популярный способ заглушить или издеваться над окружающей средой — это Sinon. В Jest уже все включено! Бум. Нет необходимости импортировать еще один инструмент, и писать тесты становится проще. В качестве примера возьмем служебную функцию debounce: Посмотрите на это. Мы хотим убедиться, что он вызывает свой обратный вызов. И это код, который вы получите.

Вуаля.

Фальшивые таймеры уже встроены в Jest, поэтому Синон не нужен. Скажите тесту, что вы собираетесь использовать поддельные таймеры с помощью jest.useFakeTimers(), затем используйте jest.runOnlyPendingTimers(); чтобы «перемотать вперед» таймеры до их конца.

Шпионы также реализованы непосредственно в Jest — sinon.spy() становится jest.fn() и работает точно так же. Эта интеграция позволяет вносить полезные дополнения в сопоставители — свойства . Called и . CallOnce в шпионском объекте Sinon управляются напрямую с помощью .toBeCalled() и .toHaveBeenCalledTimes().

Компоненты тестирования

Это может показаться самой сложной частью, но ваши тесты будут выглядеть намного проще с помощью средства сопоставления снимков. Вот идея того, как это могло бы выглядеть, по сравнению с версией Jest. Как видите, поддерживать тесты Jest намного проще благодаря снимкам, потому что мы не полагаемся на какие-либо метки/текст или структуру для тестирования. Хотя есть несколько отличий в синтаксисе, это делает тестирование компонентов действительно простым и устойчивым.

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

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

Jest создаст новый снимок компонента при первом запуске теста моментального снимка. Это читаемый файл, который выглядит так:

exports[`StatelessAnimal component renders 1`] = `
<div
  className="animal">
  <p>
    Meow!
  </p>
</div>
`;

Заметили, как все разбито на несколько строк? Это связано с тем, что при следующем запуске тестов Jest сравнит рендеринг StatelessAnimal с существующим снимком. Чем больше строк, тем четче будет разница между двумя снимками и тем проще будет понять, почему тесты провалились. При намеренном изменении вашего компонента тесты тоже сломаются, как и в случае с Chai. Но с Jest вы просто перезаписываете свой снимок, используя `jest -u`, и все! Больше не нужно тратить время на исправление набора тестов!

Jest неожиданно изменил наш рабочий процесс. Мы гораздо больше уверены в наших основных компонентах и ​​функциях, а также в нашей способности создавать и поддерживать обширные наборы тестов для наших самых насущных проектов. Благодаря автоматическому тестовому запуску при каждой отправке кода и каждом развертывании мы гарантируем, что ничего не сломается в процессе производства.

Хотите узнать больше о том, как использовать Jest и React, чтобы сделать пользовательские интерфейсы пригодными для тестирования? Мы собираемся перестроить пользовательский интерфейс нашей любимой трясогузки с помощью React и только начали тестировать его с помощью снимков Jest. Следите за нашим прогрессом и свяжитесь, если вам нужны фронтенд-инженеры, которые помогут вам создать выдающийся продукт (с помощью Jest, конечно).

Первоначально опубликовано на www.springload.co.nz.