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

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

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

1. Тестирование более чем одного объекта за раз.

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

Позвольте мне спросить вас: кто это напутал? Это был ваш разработчик тестов? Или кто-то, кто работал над функцией с сотнями строк внутри?

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

Возьмем, к примеру, следующую функцию-образец:

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

И с этим рефакторингом теперь вы можете индивидуально тестировать различные части предыдущего поведения.

2. Опора на внешние службы

В большинстве случаев код, который мы пишем, не предназначен для работы изолированно, на самом деле он предназначен для работы с внешними службами. И слово «услуги» здесь используется неаккуратно, потому что оно подразумевает что угодно, от запроса к API Google Map до сохранения файла на локальном жестком диске.

По сути, ваш код будет взаимодействовать с чем-то за пределами своей среды выполнения, и ваш модульный тест не должен полагаться на это. Почему? Просто потому, что во время выполнения теста вы не несете (или не должны нести) ответственность за состояние этих сторонних сервисов. Другими словами, почему ваши модульные тесты должны терпеть неудачу, если Google внезапно решил отключить свой API Карт на несколько часов?

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

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

Итак, я пытаюсь сказать вот что: сосредоточьтесь на своем коде, если вы взаимодействуете с базой данных, сделайте макет, если вы отправляете запрос в API, беспокойтесь о имитации ответов, вы поняли суть .

3. Стремление к охвату

Наконец, еще одна классическая ошибка, которую делают люди при написании модульных тестов, - стремление к охвату. Сколько раз вам говорили: «Пишите тесты, пока не пройдете с их помощью 90% своего кода».

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

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

Если вы ищете метрику для измерения вашего успеха, постарайтесь придерживаться точности ваших тестов. Другими словами, вместо того, чтобы убедиться, что вы охватываете все пути кода, убедитесь, что вы проходите каждый соответствующий путь со всеми возможными вариантами. Что я имею в виду?

Представьте, что у вас есть полностью реальная и полезная функция, показанная ниже:

Вы можете легко достичь 100% покрытия, проверив, что div(1,1) возвращает 1 и что console.log вызывается. Это нормально, однако я уверен, что вы понимаете, насколько нерелевантными будут эти тесты, как только вы передадите 0 в качестве второго аргумента функции.

Если вместо этого вы добавите несколько тестов, чтобы убедиться, что все работает с разными значениями для обоих, a и b, но не включите какие-либо тесты для содержимого вашего if блока, это будет нормально.

Помните, сосредоточьтесь на функциональности!

Заключение

Итак, вот три основные ошибки, которые я видел и, конечно же, сам сделал во время модульного тестирования. Можете ли вы вспомнить какие-либо другие классические ошибки, на которые допускаются разработчики при написании тестов? Делитесь ими в комментариях!

Спасибо за чтение, увидимся на следующем!

Учить больше