DevGang
Авторизоваться

Стоит ли использовать jest в качестве тестовой библиотеки?

Узнайте, почему это нарушает работу оператора instanceof

jest, популярный фреймворк для тестирования, созданный Facebook с более чем 50 миллионами загрузок в месяц, вызывает много проблем у бэкэнд-разработчиков.

В этой статье я попытаюсь кратко описать раздражение и восторг от jest, а также то, как с этим бороться и что является ее причиной.

Как работает jest?

jest — это платформа для тестирования JavaScript с множеством функций, в том числе isolated, написанных на ее веб-сайте. Целевая производительность функции изоляции:

Тесты распараллеливаются путем запуска их в их собственных процессах для максимизации производительности.

Изоляция jest обусловлена его архитектурой, в которой под капотом используется основной модуль node:vm.

Модуль vm позволяет jest запускать каждый тестовый файл в песочнице с собственным временным контекстом. Контекст включает в себя все классы global, такие как Array, Error, Date и многие другие — например, функцию describe и функцию тестирования it для примера. (Здесь исходный код Jest, который делает свое дело)

Так как jest перезаписывает некоторые из этих компонентов, чтобы предоставить вам модные функции, такие как макеты, фальшивые часы и быстрое выполнение теста, он должен установить все vm данные global, чтобы настроить контекст, в котором будет выполняться исходный код теста.

К сожалению, когда основные модули Node.js создают новый экземпляр класса global, они не будут использовать контекст vm, а возвращаются к собственной реализации.

Это означает, что оператор instanceof не будет работать должным образом и будет генерировать ложные отрицательные значения!

Вы можете получить быстрый пример этой проблемы в следующем фрагменте файла test.js:

const { parseArgs } = require('util')

test('Array is not an Array', async () => {
  const { values } = parseArgs({
    args: ['--bar', 'a', '--bar', 'b'],
    options: {
      bar: {
        type: 'string',
        multiple: true
      }
    }
  })
  expect(values.bar).toEqual(['a', 'b'])
  expect(values.bar).toBeInstanceOf(Array) // ❌ it will fail
})

Запустив приведенный выше тест с помощью команды jest test.js (с конфигурацией jest по умолчанию), он завершится с ошибкой:

  ● Array is not an Array

    expect(received).toBeInstanceOf(expected)

    Expected constructor: Array
    Received constructor: Array

      27 |   })
      28 |   expect(values.bar).toEqual(['a', 'b'])
    > 29 |   expect(values.bar).toBeInstanceOf(Array)

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

Например, Fastify удалил оператор instanceof из своей кодовой базы, потому что он вызывал проблемы у тех разработчиков, которые полагаются на jest в качестве основы для тестирования.

Как это исправить?

Вы не можете выйти из коробки. Существует открытый вопрос по Node.js репозиторий позволяет модулю node:vm использовать контекст vm, но он все еще открыт. Похоже, что Node.js основная команда заинтересована в устранении этой проблемы путем внедрения новой спецификации Shadow Realm, и я думаю, что мы добьемся некоторого прогресса в течение 2023 года.

Если вы не можете ждать, есть очень быстрое решение, используя пользовательскую среду тестирования jest-environment-node-single-context.

Если вы установите этот модуль и запустите предыдущий код с помощью команды:

jest --testEnvironment jest-environment-node-single-context test.js

Теперь все будет работать как положено:

 PASS  ./test.js
  ✓ Array is not an Array (5 ms)
⚠️ Обратите внимание, что теперь тест работает, потому что функция изоляции jest полностью отключена при запуске всех тестов в одном контексте.

Другим рабочим решением является использование нового jest runner: jest-light-runner. Это раскручивает Node.js рабочий поток для каждого тестового файла предоставляет вам ту же функцию изоляции, что и jest, но без контекста vm. Обратите внимание, что не все функции jest поддерживаются этим раннером, но все наиболее часто используемые функции работают!

Итак, после его установки вы можете убедиться, что тесты являются зелеными, выполнив команду:

jest --runner jest-light-runner test.js

Краткое содержание

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

Мы обсуждали, как решить эту проблему различными способами:

  1. Примите пользовательскую тестовую среду jest-environment-node-single-context и ее ограничения.
  2. Используйте раннер jest-light-runner, чтобы получить ту же функцию изоляции jest, но с подмножеством ее функций.
  3. Откройте проблему в репозитории модуля, который вы используете, и попросите удалить оператор instanceof, что по-прежнему является хорошей практикой.
  4. Выберите другую тестовую среду. Я лично предпочитаю node-tap

Архитектура jest имеет смысл для интерфейсных приложений, которые запускаются в браузере и имеют другой глобальный контекст, но она не подходит для Node.js приложения.

Мне не нравится концепция использования другого глобального контекста в моей тестовой и производственной среде.

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

Источник:

#JavaScript #NodeJS #Testing
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу