Недостатки разработки, основанной на тестировании?[закрыто]

StackOverflow https://stackoverflow.com/questions/64333

  •  09-06-2019
  •  | 
  •  

Вопрос

Что я теряю, внедряя дизайн, основанный на тестировании?

Перечислите только негативы;не перечисляйте преимущества, написанные в отрицательной форме.

Это было полезно?

Решение

Несколько недостатков (и я не утверждаю, что нет никаких преимуществ - особенно при написании основы проекта - это сэкономило бы много времени в конце):

  • Большие инвестиции во времени. В простом случае вы теряете около 20% от фактической реализации, но в сложных случаях вы теряете гораздо больше.
  • Дополнительная сложность. Для сложных случаев ваши тестовые примеры сложнее рассчитать, я бы посоветовал в подобных случаях попробовать использовать автоматический ссылочный код, который будет выполняться параллельно в отладочной версии / тестовом запуске, вместо модульного тестирования простейших случаев.
  • Влияние дизайна. Иногда дизайн неясен с самого начала и развивается по мере продвижения - это вынудит вас переделать тест, что приведет к большой потере времени.Я бы предложил отложить модульные тесты в этом случае до тех пор, пока вы не получите некоторое представление о дизайне.
  • Постоянная настройка. Для структур данных и алгоритмов "черного ящика" модульные тесты были бы идеальны, но для алгоритмов, которые, как правило, изменяются, настраиваются тонко, это может привести к большим затратам времени, которые, как можно было бы утверждать, неоправданны.Поэтому используйте его, когда считаете, что он действительно подходит системе, и не подгоняйте дизайн под TDD.

Другие советы

Если вы хотите сделать "настоящий" TDD (читать:сначала протестируйте с помощью красных, зеленых шагов рефакторинга), затем вам также нужно начать использовать mocks / stubs, когда вы хотите протестировать точки интеграции.

Когда вы начнете использовать mocks, через некоторое время вам захочется начать использовать внедрение зависимостей (DI) и контейнер инверсии управления (IoC).Чтобы сделать это, вам нужно использовать интерфейсы для всего (которые сами по себе имеют много подводных камней).

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

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

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

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

Все эти тесты значительно усложняют "изменение" (в отличие от рефакторинга) поведения вашей системы, и простые изменения становятся слишком сложными и отнимают много времени.

Если вы почитаете литературу по TDD, то всегда найдете несколько очень хороших примеров, но часто в реальных приложениях у вас должен быть пользовательский интерфейс и база данных.Вот тут TDD становится действительно сложным, и большинство источников не предлагают хороших ответов.И если они это делают, то это всегда включает в себя больше абстракций:макетные объекты, программирование для интерфейса, шаблоны MVC / MVP и т.д., которые опять же требуют больших знаний, и...вам нужно написать еще больше кода.

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

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

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

Я думаю, что самая большая проблема для меня - это ОГРОМНАЯ потеря времени, которое требуется, чтобы "вникнуть в это".Я все еще нахожусь в самом начале своего пути с TDD (см. Мой Блог за обновлениями моих тестовых приключений, если вам интересно) и я буквально потратил часы работы Приступая к работе.

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

ТБХ, я при всем уважении не согласен с Комментарии Джейсона Коэна что касается того, чтобы сделать частные методы общедоступными, то речь идет не об этом. В моем новом способе работы я опубликовал не больше общедоступных методов, чем раньше.Однако это требует архитектурных изменений и позволяет вам "горячо подключать" модули кода, чтобы упростить тестирование всего остального.Ты должен нет сделайте внутренние компоненты вашего кода более доступными для этого.В противном случае мы возвращаемся к исходной точке, когда все является общедоступным, где же в этом инкапсуляция?

Итак, (ИМО) в двух словах:

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

PS:Если вам нужны ссылки на положительные отзывы, я задал и ответил на несколько вопросов по этому поводу, ознакомьтесь с моим Профиль.

За те несколько лет, что я практикую разработку на основе тестирования, я бы сказал, что самыми большими недостатками являются:

Продажа его руководству

TDD лучше всего выполнять в парах.Во-первых, трудно удержаться от желания просто написать реализацию, когда вы ЗНАТЬ как написать если/else заявление.Но пара будет держать вас в напряжении, потому что вы будете держать в напряжении его.К сожалению, многие компании / менеджеры не считают, что это хорошее использование ресурсов.Зачем платить двум людям за написание одной функции, когда у меня есть две функции, которые нужно выполнять одновременно?

Продавать его другим разработчикам

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

Поддержание тестового кода вместе с вашим производственным кодом

В идеале ваши тесты будут прерываться только тогда, когда вы примете неправильное кодовое решение.То есть вы думали, что система работает в одну сторону, а оказалось, что это не так.Преодоление теста или (небольшого) набора тестов на самом деле является хорошей новостью.Ты знаешь именно так как ваш новый код повлияет на систему.Однако, если ваши тесты плохо написаны, тесно связаны или, что еще хуже, сгенерированы (кашель VS Test), тогда ведение ваших тестов может быстро превратиться в хор.И после того, как достаточное количество тестов начнет приводить к увеличению объема работы по сравнению с предполагаемой ценностью, которую они создают, тесты будут первым делом удалены, когда расписания станут сжатыми (например.наступает решающий момент)

Написание тестов таким образом, чтобы охватить все (100% покрытие кода)

В идеале, опять же, если вы будете придерживаться методологии, ваш код по умолчанию будет протестирован на 100%.Как правило, я думаю, что в итоге покрытие кода превышает 90%.Обычно это происходит, когда у меня есть некоторая архитектура в стиле шаблона, и база протестирована, и я пытаюсь срезать углы и не тестировать настройки шаблона.Кроме того, я обнаружил, что когда я сталкиваюсь с новым барьером, с которым ранее не сталкивался, у меня есть время научиться его тестировать.Я признаю, что написал несколько строк кода старым способом skool, но мне действительно нравится иметь это на 100%.(Наверное, я был сверхуспевающим в школе, э-э-э, в школе).

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

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

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

В вашем первом проекте TDD есть две большие потери: время и личная свобода

Вы теряете время, потому что:

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

Вы теряете личную свободу, потому что:

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

Надеюсь, это поможет

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

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

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

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

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

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

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

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

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

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

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

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

Я сталкивался с несколькими ситуациями, когда TDD сводил меня с ума.Чтобы назвать некоторые:

  • Ремонтопригодность тестового примера:

    Если вы работаете на крупном предприятии, велика вероятность того, что вам не придется писать тестовые примеры самостоятельно или, по крайней мере, большинство из них будут написаны кем-то другим, когда вы придете в компанию.Функции приложения время от времени меняются, и если у вас нет системы для их отслеживания, такой как HP Quality Center, вы в мгновение ока сойдете с ума.

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

  • Сложность автоматизации тестирования:

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

    Кроме того, вы потратите время на отладку кодов, которые помогут вам выявлять ошибки.На мой взгляд, большинство этих ошибок происходит из-за того, что команда тестирования не смогла отразить изменения приложения в сценарии тестирования автоматизации.Изменения в бизнес-логике, графическом интерфейсе и других внутренних компонентах могут привести к тому, что ваши скрипты перестанут выполняться или будут работать ненадежно.Иногда изменения очень незаметны, и их трудно обнаружить.Однажды все мои скрипты сообщают о сбое, потому что они основывали свои вычисления на информации из таблицы 1, в то время как таблица 1 теперь была таблицей 2 (потому что кто-то поменял местами имена объектов таблицы в коде приложения).

Самая большая проблема - это люди, которые не знают, как писать правильные модульные тесты.Они пишут тесты, которые зависят друг от друга (и они отлично работают при запуске с Ant, но затем внезапно терпят неудачу, когда я запускаю их из Eclipse, просто потому, что они выполняются в другом порядке).Они пишут тесты, которые не тестируют ничего конкретного - они просто отлаживают код, проверяют результат и меняют его на test, называя "test1".Они расширяют область применения классов и методов просто потому, что для них будет проще писать модульные тесты.Код модульных тестов ужасен, со всеми классическими проблемами программирования (тяжелая связь, методы длиной в 500 строк, жестко закодированные значения, дублирование кода), и поддерживать его чертовски сложно.По какой-то странной причине люди относятся к модульным тестам как к чему-то низшему по сравнению с "реальным" кодом, и их вообще не волнует их качество.:-(

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

Вы теряете возможность сказать, что вы "закончили", прежде чем протестировать весь свой код.

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

Вы теряете возможность учиться с помощью отладки.

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

Вы теряете свободу плотно связывать свои модули.

Вы теряете возможность пропустить написание низкоуровневой проектной документации.

Вы теряете стабильность, которая приходит с кодом, который все боятся менять.

Вы теряете звание "хакер".

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

Если вы работаете в компании, которая платит вам по KLOC (или внедренным требованиям, даже если они не протестированы), держитесь подальше от TDD (или обзоров кода, или парного программирования, или непрерывной интеграции и т.д.и т.д.и т.д.).

Я поддерживаю ответ о начальном времени разработки.Вы также теряете способность комфортно работать без безопасности тестов.Меня также описывали как чокнутого TDD, так что вы можете потерять нескольких друзей ;)

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

Подумайте об этом, вы, скорее всего, в конечном итоге будете разрабатывать для конкретных тестовых случаев, поэтому вы не станете проявлять творческий подход и не начнете думать: "было бы круто, если бы пользователь мог делать X, Y и Z".Поэтому, когда этот пользователь начинает приходить в восторг от потенциальных интересных требований X, Y и Z, ваш дизайн может быть слишком жестко сфокусирован на уже заданных тестовых примерах, и его будет трудно скорректировать.

Это, конечно, палка о двух концах.Если вы тратите все свое время на разработку для всех мыслимых X, Y и Z, которые только могут понадобиться пользователю, вы неизбежно никогда ничего не завершите.Если вы что-то завершите, никто (включая вас самих) не сможет иметь ни малейшего представления о том, что вы делаете в своем коде / дизайне.

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

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

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

Джейсон Коэн сказал что - то вроде:TDD требует определенной организации вашего кода.Это может быть неправильно с архитектурной точки зрения;например, поскольку частные методы не могут быть вызваны вне класса, вы должны сделать методы непубличными, чтобы сделать их тестируемыми.

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

Дэйв Манн

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

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

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

Однако в целом недостатки решаются по мере того, как люди становятся опытнее, и в конечном итоге вы абстрагируетесь от "вонючего" кода и получаете более стабильную систему.

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

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

Хорошие ответы на все вопросы.Я бы добавил несколько способов избежать темной стороны TDD:

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

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

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

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

Когда код меняется, вы также должны изменить тесты.С рефакторинг это может быть много дополнительной работы.

Позвольте мне добавить, что если вы примените принципы BDD к проекту TDD, вы сможете устранить некоторые из основных недостатков, перечисленных здесь (путаница, недопонимание и т.д.).Если вы не знакомы с BDD, вам следует прочитать введение Дэна Норта.Он разработал эту концепцию в ответ на некоторые проблемы, возникшие в связи с применением TDD на рабочем месте.Вступление Дэна к BDD можно найти здесь.

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

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

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

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

Его девизом был рефакторинг, рефакторинг, рефакторинг.Я пришел к пониманию, что рефакторинг означает "не планировать заранее".

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top