Вступление

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

В этом посте я хочу поделиться своими отзывами о недавнем использовании Jest, когда я участвовал в проекте next-static после того, как наткнулся на него в репозитории Next.js.

Короче говоря, мне недавно потребовалось перейти от динамического веб-приложения к статическому сайту с помощью проекта next-static. До сих пор это решение работало отлично, поэтому в конечном итоге я внес свой вклад в проект. Первым делом было написать несколько тестов для этого проекта. В течение 2017 года я уделял особое внимание тестированию. Я получил большой опыт написания модульных тестов для приложений ReactJS и был готов к ним приступить.

Шаг первый - создайте нежелательный тест и отправьте его в репозиторий.

Мой первый выбор для написания модульных тестов - это лента. Он очень легкий и предоставляет инструменты, необходимые для написания эффективных модульных тестов. Через несколько минут после настройки среды у меня был готов шаблон для моего первого test.js файла.

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

// imports….
// set up for test scope
test('<Post />', nest => {
  nest.test('given no props', assert => {
    const msg = `should render a post`;
    const props = makeProps();
    const re = RegExp(props);
    const el = <Post {...props} />;
    const $ = dom.load(render(el));
    const output = $('.post').html();
    const actual = re.test(output);
    const expected = true;
    assert.same(actual, expected, msg);
    assert.end();
  });
});

После запуска этот журнал для этого теста будет выглядеть, как показано на рисунке ниже.

Разве это не красиво? Я любитель хороших TAP, которые мало что дают на кассете, я знал, что принимаю это как должное, но об этом чуть позже. На этом этапе у меня наконец-то было то, что я мог с уверенностью перенести в следующее статическое репо.

Примерно через день я получил это замечание от владельца проекта.

Но конечно! Зачем я использовал эту технологию каменного века, когда я мог просто подключить Jest! Если отбросить сарказм, меня это не удивило. Я знаю, насколько важным инструментом стал Jest для многих разработчиков, и не собирался с этим бороться. Мне просто не терпелось погрузиться в фреймворк.

Стать единым целым с Jest

Я знал, что перенести этот супербазовый тест не составит труда. Мне просто нужно было знать, как должен быть настроен мой тест, чтобы Jest работал.

В качестве . Одно из основных свойств Jest - это способность волшебным образом запускать тесты, если они:

  • в * .test.js или * .spec.js
  • они находятся в папке с тестами.

На момент написания моего теста я даже не знал об этих критериях, однако мой код был внутри test.js файла, так что все работало отлично. Кроме того, я мог полностью исключить этот главный index.test.js файл, поскольку jest команда самостоятельно переходила к тестам. Когда jest запущен, он будет искать в тестах проекта определенные глобальные переменные, которые он предоставляет пользователям. В моем случае мне пришлось заменить test на describe функцию Jest w

Глобальные объекты В ваших тестовых файлах Jest помещает каждый из этих методов и объектов в глобальную среду. Для их использования не нужно ничего запрашивать или импортировать.

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

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

describe('<Post /> with no args', () => {

});`

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

expect(actual).toEqual(expected);

В частности, мы видим, что expect проверяет, чтобы значение внутри actual было равно expected, используя toEqual. (Узнайте больше об ожиданиях Jest-теста здесь.) Благодаря ленте перенос этого теста действительно не занял много времени, и было приятно знать, что я, безусловно, мог бы перенести любой написанный мной тест на использование Jest без каких-либо конфликтов. . Те же концепции, но разные библиотеки. Мне нравится вникать в известные технологии (особенно если я могу понять их с первого взгляда), так что для меня это был беспроигрышный вариант.

У тебя была одна работа

На следующий день после того, как я отправил свой новый тест в PR, мне сообщили, что я не полностью понимаю, о чем меня просят. Я произвел модульный тест, но мне действительно нужно было создать тест-снимок. Большой! Теперь, когда я правильно определил цель, мне просто нужно было выяснить, что именно представляет собой тест снимка.

Войти в тестирование снимков

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

Для этого мы используем метод .toMatchSnapshot() библиотеки react-test-renderer. Как только это будет настроено, Jest сравнит снимок нашего компонента с любым предыдущим снимком и проверит, что их содержимое одинаково.

describe('Snapshot::<Post />s', () => {
    it('should render the contents of the component.', () => {
        const props = makeProps();
        const el = <Component {...props} />;
        const tree = renderer.create(el).toJSON();
        expect(tree).toMatchSnapshot();
    });
});

Ниже приведен точный снимок Jest, созданный для компонента <Post/>. Я не буду объяснять каждую строку, но вы должны легко понять, что должен отображать пользовательский интерфейс.

// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Snapshot::<Post />s should render the contents of the component. 1`] = `
<article
  className="post Post__Article-s1eculme-0 fQItYZ"
  itemScope={true}
  itemType="http://schema.org/BlogPosting";
>
  <header>
    <a
      href="/post/test-post"
      onClick={[Function]}
    >
      <h1
        className="post--title"
        itemProp="headline"
      >
        Hello
      </h1>
    </a>
    <footer
      className="post--info"
    >
      <span>
        <time
          dateTime="7/22/2017"
          itemProp="datePublished"
        >
          about 1 month ago
        </time>
      </span>
      <span
        itemProp="author"
      >
        User
      </span>
    </footer>
  </header>
  <div
    className="post--body"
    dangerouslySetInnerHTML={
      Object {
        "__html": "<p>lorem ipsum is the name making tests is this game</p>
      ",
      }
    }
  />
  <footer>
    <small
      className="post--tags"
    >
      <span>
        Filed under: 
      </span>
      <span
        className="post--tag"
        itemProp="keywords"
      >
        <a
          href="/tag/javascript"
          onClick={[Function]}
        >
          javascript
        </a>
        , 
      </span>
      <span
        className="post--tag"
        itemProp="keywords"
      >
        <a
          href="/tag/angular"
          onClick={[Function]}
        >
          angular
        </a>
        
      </span>
    </small>
  </footer>
</article>
`;

Как видите, Jest создал удобочитаемое представление нашего пользовательского интерфейса. С этого момента все будущие реализации <Post/> будут проверяться на основе этого снимка. Чтобы лучше понять, что это означает, давайте посмотрим, что произойдет, когда мы удалим <footer> из нашего Post компонента и запустим наш тест снимка.

Взглянув на это изображение, мы видим, что Jest ожидает <footer> div и не может найти его внутри нашего компонента. В результате мы видим знак-, означающий, что блок кода был удален из файла. Если бы меня попросили удалить этот нижний колонтитул, я бы подтвердил это изменение и запустил jest -u, чтобы обновить свой снимок, но я этого не сделал. Вместо этого я создавал начальный снимок для этого компонента, и поэтому мне не нужно было беспокоиться о предыдущих снимках. Тот факт, что я создал отправную точку для тестов фьючерсов, был достаточно хорош.

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

Кроме того, лента позволяет мне использовать TAP. Называйте меня старомодным, но TAP существует с 1980-х годов. Он старше меня, и технологии, просуществовавшие так долго, обычно не зря высекаются в камне. Я лично не пробовал интегрировать пользовательский репортер TAP с Jest, но, как я понял, это довольно сложная задача. Это конец света? Нет. Вовсе нет, но стоит отметить. С другой стороны, когда используется флаг —watch, Jest предлагает довольно крутой интерфейс, который упрощает выполнение определенных тестов. —watch сохраняет работу Jest после создания тестов моментальных снимков и предлагает нам возможность обновлять наши предыдущие снимки, просто нажав u.

Заключительные слова

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