Знакомство с фронтенд-тестированием. Часть первая. Введение

Рассказывает Гил Тайяр, автор блога на Hackernoon


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

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

В итоге я решил написать его сам.

Что такое тестирование?

На мой взгляд, тестирование — это код, который проверяет, работает ли код твоего приложения, так называемый «промышленный код», согласно ожиданиям. Некоторые люди подразумевают под этим TDD (разработку через тестирование), специфическую методологию тестирования, где тесты пишутся в самом начале и направляют дальнейшую разработку продукта.

Прим. перев. О том, зачем нужна TDD, читайте в нашей статье.

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

К сожалению, индустрия объединила идею тестирования и TDD, и из-за этого у кода, написанного разработчиком параллельно с промышленным кодом, нет стандартного определения. Я решил назвать его просто тестированием.

Зачем нужно тестирование?

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

Нет, я не собираюсь обсуждать, зачем нужно тестирование.

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

Другая область, сбивающая с толку людей, начавших изучать тестирование — это различные типы тестов. Если вы изучали эту тему, вы наверняка слышали о юнит-тестировании, интеграционном тестировании, end-to-end (E2E) тестировании и компонентном тестировании.

И что еще хуже, каждый человек описывает эти понятия по-своему.

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

Многообразие типов тестирования

Давайте начнем с самого простого — юнит-теста. Юнит-тест — это по определению то, что тестирует «юнит» (англ. элемент). А что же такое «юнит»? Это зависит от языка программирования. Юнитом может быть функция, модуль, пакет, класс, даже объект (в языках вроде JavaScript и Scala). В JavaScript юнит — это обычно класс или модуль.

Прим. перев. Советуем также прочитать наш перевод статьи «Зачем нужны юнит-тесты».

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

Легко тестировать элемент кода отдельно, когда он не зависит от других элементов вообще. Но что, если я хочу протестировать юнит, который зависит от другого элемента кода? Мы можем сделать две вещи: протестировать два юнита вместе или замо́кать один из них.

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

Что же такое «мок»? Давайте посмотрим на примере:

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

Но заметим, что мы не пишем в файл сами, это пишет другая функция, fileSumWriter.

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

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

Итак, с одной стороны мы имеем юнит-тесты, с другой — E2E-тесты, тесты целого приложения. Все тестируется в E2E-тесте, а приложение работает так с теми же настройками, что и у пользователя.

С увеличением количества тестов объем протестированного кода увеличивается, а замоканного кода — уменьшается.

Интеграционными тестами я называю те, которые тестируют больше, чем юнит, но не тестируют все части приложения. Итак, в какой раздел вы поместите свои тесты? Многие люди утверждают, что существует пирамида тестирования: много юнит-тестов, поменьше интеграционных и малое количество E2E-тестов. Но давайте пока оставим эту тему — я собираюсь разобрать каждый из видов тестирования отдельно. Также я написал маленькое приложение, которое мы будем использовать в учебных целях — его исходники можно найти на GitHub.

Перевод статьи «Testing Your Frontend Code: Part I (Introduction)»