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

Что тестировать при тестировании

Один из вопросов, который я часто получаю от разработчиков из моей команды на работе, звучит так: «Ну, что мне тестировать?» или «Должен ли я проверить это, или это не важно?», и я все еще борюсь с этим вопросом. Потому что, как и все, что связано с инженерией.

По-разному.

Мои обычные эмпирические правила, которые работают лучше всего для меня, следующие:

  1. Если это модуль: проверьте все экспорты
  2. Если это простой реагирующий компонент: протестируйте все статические состояния пользовательского интерфейса (ошибка рендеринга/ожидаемый рендеринг/ожидающий рендеринг) и все взаимодействия компонента.
  3. Если компонент наследует свойства от родителя, имитируйте эти инъекции, потому что вы должны тестировать только явную функциональность исследуемой единицы кода, вы не должны подразумевать функциональность, которую наследует компонент. Родитель должен проверять, может ли он правильно передать функциональность и что при передаче он работает должным образом, а не дочерний элемент.

Правила в дикой природе

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

  • Строки 1–4 являются импортом, а строка 4 — это что-то вроде функции mockComponent. Конечно.
  • Строка 6 издевается над приложением, которое представляет собой каррированную функцию, которая теперь что-то возвращает… Я предполагаю, что это элемент JSX, который возвращает компонент с отображаемым именем в качестве аргумента.
  • Строка 7 имитирует модуль узла, чтобы он был какой-то функцией, которая выполняет эту странную деструктуризацию и каррирование, а затем возвращает ту же самую фиктивную функцию, но теперь с именем из этой функции, называемой chunkName
  • Строка 11 — это пользовательская функция многократного использования, которая возвращает неглубоко отрисованный маршрутизатор, в котором свойства по умолчанию объединены с параметрами, переданными в саму функцию.
  • Строка 22 описывает файл (я полагаю, в некотором роде)
  • Строка 23 описывает состояние чего-то под названием Validity.
  • Строки 24, 30, 37 и 43 описывают условия тестирования.
  • Строки 25–27, 31, 32, 40 и 49 содержат эти тестовые утверждения.

На бумаге этот тест выглядит нормально. Это очень многословно, но есть идея того, что он пытается проверить. Файл, с которым это тестируется, также имеет около 81% общего покрытия этим тестом, поэтому можно подумать, что это достаточно хорошее место, чтобы остановиться.

Но я Тайлер, и я думаю, что мы можем добиться большего.

Правило первое: тестируйте все экспорты

Проблема первая: тест не описывал компонент

Это реальный компонент.

Как вы заметите, есть 4 основных экспорта этого файла default, matchPathToRoute, isSearchPage и isValidRoute, но если вы посмотрите на приведенный выше тест, вы увидите, что нет ни одного теста, описывающего какую-либо из этих функций и тесты, которыми они являются. очень многословны и явно говорят о логике уровня приложения.

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

Правило второе: тестируйте все статические состояния пользовательского интерфейса

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

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

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

Вон со старым

Так я испортил тест

И с новым

И переписал это, чтобы быть супер явным

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

Благодаря этому тестовое покрытие увеличилось до 87,29% (не удивительно, но это тема для другого дня). Это увеличение произошло исключительно из-за того, что в исходном коде отсутствовал тест ветвления, поскольку исходный код делал много предположений о состоянии приложения.

Этот тест оставляет довольно большое TODO, но идея состоит в том, чтобы представить будущую поломку при добавлении/удалении маршрута в приложении.

Вывод

Написание тестов может быть пугающим, но если вы подойдете к ним как можно более объективно, помня о цели функциональности, все может иметь больше смысла.

Вы можете найти меня здесь ниже: