Статьи

Модульное тестирование — стоимость против выгоды

тенденция к понижению Я был большим поклонником модульного тестирования в течение очень долгого времени; мой блог заполнен сообщениями об этом. Если я посмотрю на то, как автоматизировалось модульное тестирование в моих проектах за последнее десятилетие, я заметил, что склонности к проведению модульного тестирования просто нет . Недавно я наткнулся на эту серию подкастов между Мартином Фаулером, Кентом Беком и DHH, которая была в ответ на сообщение DHD, что TDD мертв, да здравствует тестирование . Подкаст не открыл мне ничего нового, но помог мне просветить. Я провел последний вечер, анализируя и размышляя над тем, как я продвигал TDD / Unit Testing в целом по своим проектам, и я вижу тенденцию, что те, в которых я был более вовлечен как разработчик или старший разработчик или даже архитектор, пытались там было сделано модульное тестирование, НО модульное тестирование (не TDD) не очень хорошо работало в последнем большом проекте. И так как я взял на себя обязанности архитектора решений и, как и мои обязанности, я немного отошел от кода, я вижу, что на следующем уровне не проводится модульное тестирование.

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

  1. Написание автоматических модульных тестов не так весело, как кодирование
  2. Написание автоматических модульных тестов не так весело, как кодирование

Вы получаете точку! Я сравниваю случаи, когда я впервые проводил модульное тестирование еще в 2004 году (мой первый проект с организацией ИТ-консультантов), а затем последний в 2012 году, и я понимаю, почему это так. Среда, в которой я проводил модульное тестирование еще в 2004 году, а затем в 2012 году (с интервалом в 8 лет), сильно отличалась. Когда-то я был разработчиком Enterprise / Core Java / .Net, и моя жизнь заключалась в том, чтобы заниматься такими вещами, как вызовы базы данных, сервисы написания — бизнес-логика, валидации, yada yada yada. Часть, которая включала в себя написание автоматизированных тестовых примеров для веб-слоя, была минимальной, потому что код, входящий в Web Controller (используемые нами MVC-фреймворки, был только вид). И мы использовали функциональное / системное тестирование для тестирования пользовательского интерфейса. Ответственность за создание этих тестов Selinium была не на функции QA, а на мне, как разработчике. Таким образом, все тестирование было «что имеет смысл» — мы сделали TDD для кода сервисов, а затем провели функциональное тестирование (посткодирование) во Front-end.
Но самой важной частью было то, что, как разработчик, я должен был убедиться, что ничего не сломалось, когда я зафиксировал код. Инструменты CI не были такими продвинутыми в те времена, но они были там. Мы использовали Ant для сборки, и там была задача, которая отвечала за выполнение тестовых примеров, в противном случае сборка была неудачной (я даже написал скрипт сборки ant). Мы не смогли интегрировать Ant-скрипт Selenium Test Runner, так что это был ручной шаг, но мы должны были запустить весь пакет, чтобы все работало. Явление «Код самопроверки» существовало, и мы следовали ему до глубины души. Место строительства штрафов — 50 индийских рупий, так как нам не удалось сделать перерыв; 3 последовательных перерыва — до 500 индийских рупий; 20 INR за любые дефекты регрессии (у QA были свои собственные костюмы, чтобы держать нас под контролем). Когда я кодировал и когда кодировал, я знал, что ночью никто не собирается звонить мне, чтобы сказать, что другие члены моей команды застряли. Я работал в Индии, и у меня была команда, работающая из Бостона, и я знал, что когда я уйду и когда они приедут, их не будут закрывать, потому что я испортил компиляцию или что-то сломал — они могут просто выполнять свою работу и быть продуктивными , Все так и сделали, и мы все были счастливы группой разработчиков / команды. У нас не было Непрерывной Доставки, но как только история была закончена, пару раундов тестирования качества, и она была демонстрационной для клиентов. Наш тестовый охват составил 80% +, и у нас был солидный набор тестов. Однако запуск комплекта занял 2 часа (я расскажу о нем очень скоро, поскольку именно эта часть делает тестирование модулей приятным).

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

Перемотка вперед 2007-08; Я был архитектором в команде из 40 человек (разработчики, QA, разработчики сайтов), и мы работали над веб-разработкой — тяжелой веб-разработкой. Он использовал Backbase, JSF на JBoss, общался с MySQL через hibernate, все было связано с Spring. Мы начали с проекта, и, как и прежде, я хотел сделать полноценный TDD (не только модульное тестирование). Мы начали, но очень скоро (Sprint 1) появились отзывы разработчиков о том, что модульное тестирование было слишком трудоемким, оно занимает больше времени, чем кода. Я не был архитектором, и я создал Золотую копию в качестве ориентира, который использовала команда; поэтому команда обратной связи давала мне никакого смысла. Я позволил команде бороться за это еще за один спринт, думая, что им просто нужно время, чтобы обойти его, но когда он начал поражать наши точки скорости, я был вынужден посмотреть, что происходит в этих отделах модульного тестирования, и то, что я увидел, шокировало душа из меня. Автоматизированные тесты были там для формальности — тесты действительно что-то тестировали, они обеспечивали некоторый охват, но они были чудовищными. Они были везде с насмешками (почти). Неудивительно, что команде потребовалось так много времени, чтобы написать контрольные примеры. Для всего, что нужно было проверить, они должны были создать макет. Отчасти это было связано с отсутствием опыта, когда команда не создавала классы помощников для обеспечения этих распространенных насмешек, а пыталась имитировать такие вещи, как HTTPSession, HTTPRequest, логика адаптеров данных для MySQL — то есть каждый сотрудник был там. Что ж, они поступили правильно (согласно определению модульного тестирования) — протестировали сам модуль, поэтому они высмеивали даже те классы, которые обращались к базам данных. Это намного усложняет тестирование функциональности. Мы быстро перевернули это и установили некоторые основные правила

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

Это означало следующее: а) это не было модульное тестирование в его самой чистой форме (я даже не знаю, что такое юнит-тестирование в его самой чистой форме, но какие определения и мои старшие сказали мне) и б) у нас было немного меньшее освещение , Но я был в порядке с этими последствиями. В результате команде не нужно было писать вещи, которые использовались только для тестирования; это сделало весь наш набор тестов немного медленным, потому что теперь он выполнял вызовы к БД, но БД была локальной, поэтому она не была такой медленной — команда стала тратить меньше времени на модульное тестирование, мы написали меньше тестов и добились лучшего охвата кода , Это не было модульное тестирование, но мы достигли кода самопроверки. Наша сборка CI теперь снова говорила нам, что коммит нарушил что-то еще. Веселье возвращалось в игру, и мы начали прогрессировать. Затем, в январе 2008 года, мы решили отключить Backbase и перейти на Flex, что потребовало изменения дизайна не только нашего внешнего интерфейса, но и наших внутренних служб. Когда мы собрали команду для реорганизации и переоснащения сервисов, им был предоставлен солидный набор из 300 нечетных тестов. Реализация была выброшена, несколько интерфейсов были изменены. Мы исправили только набор тестов (мы решили позволить нашей команде QA исправить набор тестов — для этого нужен специалист по QA для написания кода / скрипта на Java, что вызвало много откатов, но я выиграл эту битву), часть интерфейса, а затем снова начал писать эти сервисы, и все, что нам нужно было сделать, — это пройти эти 300 тестов. Это был бриз; нам даже не нужна команда QA для тестирования наших услуг. Наш тестовый набор был достаточно хорош для этого.

Мы никогда не достигли совершенства, но тогда я смог достичь поставленных целей.

Fast Forward 2012-2013; Я был архитектором проекта Adobe CQ 5.5, и фреймворки изменились. Мы не писали никаких сервисов. Традиционная среда MVC не была в распоряжении разработчиков. Я видел код, и было чудовищно, что JSP имеет бизнес-логику в скриптах, одноуровневых Java-классах, которые делают все от получения данных, манипулирования ими, проверки входных данных, отправки выходных данных в очень гибких форматах, таких как Maps (ValueMaps, специфичные для реализации Sling) , Среди всего этого мы приняли несколько жестких дизайнерских решений, таких как отсутствие скриплетов или бизнес-логики в JSP. Следовательно, теперь должен был быть Java Code, но было множество зависимостей слинга и JCR, с которыми нам приходилось иметь дело. Я еще раз хотел сделать то, что делал раньше — без МОКАСОВ / СТАБОВ. Но рамки, которые могли бы сделать это, не были в моем распоряжении тогда. Они существовали, но сообщество тогда было тонким, поддержки было меньше, и все, что существовало, не работало. И в итоге я решил сделать Mocks. 3 месяца, и это было именно то, что было в 2008 году — это не работало.

Насмешки были настолько плохими, что мы могли изменить логику, и тесты все равно прошли бы.

Случилось так, что разработчики просто все испортили, а тесты даже не тестировали состояние или поведение. Они просто пошли на освещение. Инструменты были лучше на этот раз, и у нас был сонар. Идея заключалась в том, чтобы написать контрольный пример, сделать его успешным и показать увеличенный покрытый сонар. Мы использовали mockit, и в то время это казалось хорошей идеей, но просто не работало. Я понимаю издевательства, но я просто не понимаю их. Мы устанавливаем какое-то состояние и проверяем это состояние — все имеет смысл. Но когда все поступает от Collaborators и объект, который вы тестируете, просто объединяет и собирает данные в ValueObject (в нашем случае Map), тестирование этой сборки не имеет смысла. Это все равно что сказать, что разработчик может кодировать следующее неправильно.

1
outputData.put("athletes", athleteList);

Что ж, если разработчик не может правильно составить несколько базовых Java-операторов, у них нет бизнес-кодирования; давайте отправим их на тренировку и спасем себя от мира боли.

Fast Forward 2014, я не архитектор решений и не уделяю много внимания программированию. Я люблю кодировать, но это не моя дневная работа (я хотел бы, чтобы программирование было моей дневной работой когда-нибудь). Но теперь я вижу, что команды много борются за то, чтобы провести юнит-тестирование даже с земли. Среда похожа на ту, что была у меня в 2012 году, но теперь у меня есть решение, и я думаю, что есть способ сделать это без Mocks. Тем не менее, борьба есть, разработчики больше не считают это забавным — это выглядит бременем.

Аргумент «цена против выгоды» является верным в каждом сценарии, и в случае нашего жизненного цикла разработки программного обеспечения, когда получить какую-либо уверенность слишком сложно, как разработчику необходимо иметь что-то, на что можно опереться, и зная, что мы не сломать систему с моим следующим коммитом огромно. В моем жизненном цикле разработки мы, вероятно, все еще можем жить с некоторой регрессией, но по мере того, как мы достигаем зрелости приложения, когда мы начинаем достигать стабилизации, не имея кода для самопроверки, мы становимся похожими на мамонтов (не слонов), которые двигаются очень медленно. В современном мире маркетинга, где у нас есть клиенты, которые хотят запускать кампании в течение следующих 2 недель, мы не можем медлить с тем, как скоро мы выпустим код. Вы можете быть значимыми в отрасли только в том случае, если вы можете двигаться быстро, добиться непрерывной доставки или, по крайней мере, достичь того момента, когда вы сможете выпускать релизы в производство с разумной скоростью. Те дни, когда релизы случались раз в 6 месяцев, прошли; или, по крайней мере, ушел в среду / рынок, на котором я работаю.

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

Ссылка: Модульное тестирование — стоимость и выгода от нашего партнера по JCG Капиля Вирена Ахаджи в блоге Scratch Pad .