Однажды меня попросили рассказать о юнит-тестировании в JavaScript, но прежде чем говорить о тестировании в мире фронтенда, мне пришлось дать краткий обзор юнит-тестирования как такового.
В результате родилась эта статья, в которой я постарался рассказать о самых важных моментах юнит-тестирования.
Несмотря на разные интерпретации модульного тестирования, есть несколько вещей, которые объединяют этот термин.
Но есть моменты в определении модульного тестирования, которые до сих пор вызывают споры.
В частности, что считается единицей (единицей тестирования)? Подход ООП рассматривает класс как единицу, процедурный (или функциональный) подход рассматривает отдельную функцию как единицу.
Некоторые разработчики берут несколько классов и рассматривают их как единое целое или принимают за единицу набор методов.
Но на самом деле это вещь ситуативная, команда решает, какой должна быть единица тестирования в их системе.
Преимущества модульного тестирования очевидны:
- Имеют низкий уровень и сосредоточены на небольшом программном обеспечении.
- Тесты пишут сами разработчики
- Тесты выполняются очень быстро, можно запускать тесты несколько раз в минуту.
- Во время разработки вы можете выполнять не все тесты, а только те, которые вам необходимы.
Важная разница в модульном тестировании заключается в том, какой тип тестирования вы выбираете: одиночное и общительное тестирование.
Эти термины были впервые предложены Джеем Филдсом.
Общительный тест — это тест, в котором используются реальные методы (или классы), включенные в тестируемый модуль.
Например, вы тестируете метод «цена» из класса заказов.
Метод «цена» должен вызывать методы класса клиента и продукта.
В этом типе теста будут вызываться именно эти методы, и ошибка в этих методах приведет к сбою теста.
Методы классов клиента и продукта называются партнерами.
Одиночный (одиночный) тест — это тест, в котором в качестве партнеров используются дубликаты ( ТестДабл ).
Тестовые дубликаты — это общий термин для любого случая, когда вы заменяете реальный объект исключительно в целях тестирования.
Хорошую классификацию дублей сделал Жерар Месарош, подробнее об этом можно почитать Здесь
Каждый из этих методов тестирования имеет свои преимущества и недостатки, и между сторонниками этих двух методов ведутся жаркие споры.
Сторонников Одиночных (одиноких) тестов также условно называют Мок-истами (Mock – фейк), а сторонников Социальных (общительных) тестов условно называют Классицистами ( Аналогов на русском языке не нашел.
).
Хотелось бы отметить, что сторонники Sociable-тестирования также используют дублирующие тесты для доступа к внешним ресурсам, например, к базе данных.
Отчасти это сделано за счет скорости доступа.
Но использование дубликатов для доступа к внешним ресурсам не является абсолютным правилом; если доступ к ним стабильный и достаточно быстрый, то можно обойтись и без дубликатов.
В любом случае разработчик сам решает, когда ему лучше использовать дубликаты.
Одним из преимуществ метода одиночного тестирования является то, что разработчики сосредотачиваются на поведении приложения, а не на его состоянии.
Недостаток в том, что подделки могут маскировать ошибку, присутствующую в партнерском методе.
Поэтому при использовании дублирующих тестов необходимо проводить интеграционное тестирование.
Преимущество тестирования Sociable в том, что это, по сути, первоначальное интеграционное тестирование, но недостаток в том, что в случае сбоя одного метода все тесты, связанные с этим методом, завершатся неудачно, что затрудняет отладку.
Я не буду подробно останавливаться на преимуществах и недостатках того или иного подхода к тестированию; об этом можно прочитать в статье Фаулера Моки — это не заглушки Основные свойства модульного тестирования заключаются в том, что оно небольшое, выполняется самим программистом и быстрое, что означает, что его можно часто выполнять во время программирования.
Разработчики могут выполнить их после любого изменения кода.
Но вам не обязательно всегда запускать все тесты; достаточно запускать только те тесты, которые взаимодействуют с кодом, над которым вы сейчас работаете.
В конце 1990-х годов Кент Бек разработал разработку через тестирование (TDD) как часть экстремального программирования.
Это метод создания программного обеспечения, которое управляет процессом разработки посредством написания тестов.
По сути, он повторяет три простых правила:
- Сначала пишется тест
- Затем пишется код этого теста
- Рефакторинг нового и старого кода для улучшения качества кода.
Написание теста первым имеет два преимущества: 1. Это способ получить самотестируемый код. 2. Думая в первую очередь о тесте, вы заставляете себя думать об интерфейсе самого кода.
Такое внимание к интерфейсу и тому, как вы используете класс, помогает вам отделить интерфейс от реализации.
Самая большая ошибка при использовании этой методологии — пренебрежение третьим шагом — рефакторингом.
Это приводит к грязному коду (но, по крайней мере, будут тесты).
BDD (Behavior Driven Development), или разработка на основе поведения, возникла в результате эволюции модульного тестирования и была разработана Дэном Нортом в 2006 году.
Как заявляет сам автор, методология должна помочь людям освоить TDD. Он возник на основе практик Agile и призван сделать их более доступными и эффективными для команд, впервые использующих Agile. Со временем BDD начал охватывать более широкую картину гибкого анализа и автоматизированного приемочного тестирования.
Это привело к тому, что сами тесты были переименованы в поведения (спецификации), что позволило сосредоточиться на том, что должен делать объект. Таким образом, разработчики стали создавать для себя документацию и записывать названия тестов в виде предложений.
Они обнаружили, что созданная документация стала доступна предприятиям, разработчикам и тестировщикам.
Разработка на основе поведения считается одной из ветвей Mock-стилей (или одиночного тестирования), т.е.
тесты преимущественно строятся с использованием дубликатов.
Позже появился стиль написания тестов «Дано-Когда-То», или, как его стали называть, спецификация поведения системы.
Стиль разработал Дэн Норт совместно с Крисом Мэттсом.
Идея состоит в том, чтобы разбить написание тестового сценария на три части:
- Данный (Дано) – состояние до того, как начать описывать поведение.
можно рассматривать как предварительное условие для проведения теста.
- Когда (Когда) – это поведение, которое вы описываете.
- Затем (Затем) – изменения, которые вы ожидаете от поведения
Сценарий: Пользователь запрашивает продажу до закрытия аукциона.
Данный (Дано): У меня есть 100 акций MSFT и 150 акций APPL и время для закрытия.
Когда (Когда): Я прошу вас продать 20 акций MSFT. Затем (Затем): У меня должно остаться 80 акций MSFT и 150 акций APPL, и должен быть исполнен ордер на продажу 20 акций.
Несмотря на то, что с момента появления методологий TDD и BDD прошло достаточно много времени, многие разработчики до сих пор спорят друг с другом о целесообразности их использования.
Некоторые утверждают, что нет необходимости писать тесты перед кодом, другие утверждают, что писать тесты после кода бессмысленно.
Но обе стороны сходятся в одном: тесты писать нужно! Методология BDD с точки зрения программистов, как утверждает сам ее автор ( BDD ПОХОЖ на TDD, ЕСЛИ… ), ничем не отличается от TDD. Там используются все те же правила, что и в TDD: тест, код, рефакторинг.
Разница в том, что BDD достигает более широкой публики.
Спецификации становятся доступными не только программистам, но и людям, не разбирающимся в коде, но имеющим отношение к разработке программного обеспечения.
Таким образом, в процессе создания тестов участвует вся команда: аналитики, тестировщики, менеджеры.
Одним из очевидных преимуществ модульных тестов является то, что они могут радикально сократить количество ошибок, попадающих в продукт. В основе этого лежит культура , что заставляет разработчиков думать о совместном написании кода и тестов.
Но самое большое преимущество — это не просто отсутствие ошибок в продукте, а уверенность в том, что вы можете внести изменения в систему.
Старый код часто представляет собой страшилку, когда разработчики боятся его менять.
Исправление даже одной ошибки может быть опасным, потому что.
вы можете создать больше ошибок, чем исправить.
В таких случаях добавление новых возможностей происходит очень медленно, к тому же вы боитесь проводить рефакторинг системы, тем самым увеличивая технический долг( Технический долг ) и попадаем в плохую спираль, где каждое изменение заставляет людей бояться еще больших изменений.
Иная картина с тестами.
Здесь люди уверены, что логировать ошибки можно безопасно, ведь если вы допустите ошибку, сработает детектор ошибок и вы сможете быстро восстановиться и продолжить работу.
Благодаря этой системе безопасности вы всегда сможете поддерживать свой код в хорошем состоянии и не попадете в плохую ситуацию.
Процесс выполнения серии автоматических тестов (а не отдельного модуля) действует как детектор ошибок (система самотестирования), и вы уверены, что тесты пройдут и ваш код не содержит существенных дефектов.
Если кто-то из команды случайно допустит ошибку, детектор сработает. Запуская тесты часто, несколько раз в день, вы можете обнаруживать ошибки сразу же после их появления и просто просматривать последние изменения, что значительно упрощает поиск ошибок.
Ни один выпуск программного обеспечения не обходится без рабочего кода и тестов, поддерживающих его работу.
Сама тестируемая система является частью Непрерывная интеграция (непрерывная интеграция) и Continuous Delivery (непрерывная доставка), но эта тема выходит за рамки данной статьи.
Одним из важных действий команды, практикующей различные тесты, является реакция на ошибку в продукте.
Обычная реакция команды такая: сначала напишите тест, чтобы выявить ошибку , и только потом пытаться это исправить.
Зачастую написание этого теста представляет собой серию тестов, объем которых постепенно сужается, пока не дойдете до модульного теста, имитирующего ошибку.
Этот метод гарантирует, что после исправления ошибки она останется исправленной.
Позиция должна быть такой: любая ошибка — это не просто сбой в коде, это еще и сбой в тестировании защиты.
Не только модульные тесты, но также интеграционные тесты и другие автоматические тесты действуют как детекторы ошибок или автоматические тесты.
Но в основу здесь играют юнит-тесты, потому что.
Их просто писать и они выполняются очень быстро.
Тесты высокого уровня — это вторая линия защиты.
Если вы обнаружите ошибку при высокоуровневом тестировании, это не просто ошибка в коде, Это отсутствующий или неправильный модульный тест! Список источников:
- Мартин Фаулер Модульный тест
- Мартин Фаулер ТестПирамида
- Мартин Фаулер Код самотестирования
- Мартин Фаулер TestDrivenРазработка
- Джеймс Шор Искусство гибкой разработки: разработка через тестирование
- Введение в разработку, основанную на поведении (BDD)
- Мартин Фаулер УчитываяКогдаТо
-
Словакия
19 Oct, 24 -
Преимущества Bing Перед Google
19 Oct, 24 -
Геймифицированное Поколение
19 Oct, 24 -
Простой Контроллер Освещения
19 Oct, 24 -
Как Мы Делали Редизайн Райффайзен.ру
19 Oct, 24 -
Клиент И Сервер Rest На Yii
19 Oct, 24