Разработка через тестирование (TDD) сегодня очень важна. Я часто вижу его рекомендованным в качестве решения для широкого круга проблем здесь, в Programmers SE и других местах. Интересно, почему это работает.
С инженерной точки зрения это озадачивает меня по двум причинам:
- Подход "написать тест + рефакторинг до прохождения" выглядит невероятно антиинженерным. Если бы инженеры-строители использовали этот подход для строительства мостов или, например, дизайнеров автомобилей для своих автомобилей, они бы перестроили свои мосты или автомобили по очень высокой цене, и в результате получился бы залатанный беспорядок без хорошо продуманной архитектуры. , Рекомендация «Рефакторинг до сдачи» часто принимается как обязательство забыть архитектурный проект и сделать все необходимое, чтобы выполнить тест; другими словами, тест, а не пользователь, устанавливает требование. В этой ситуации, как мы можем гарантировать хорошие «способности» в результатах, то есть конечный результат, который не только правильный, но и расширяемый, надежный, простой в использовании, надежный, безопасный, надежный и т. Д.? Это то, что архитектура обычно делает.
- Тестирование не может гарантировать, что система работает; это может только показать, что это не так. Другими словами, тестирование может показать вам, что система содержит дефекты, если она не проходит тест, но система, которая проходит все тесты, не безопаснее, чем система, которая их не проходит. Тест покрытия, качество теста и другие факторы имеют решающее значение здесь. В гражданских и аэрокосмических отраслях ложные безопасные ощущения, которые производят "все зеленые" результаты, были объявлены чрезвычайно опасными в гражданской и аэрокосмической отраслях, поскольку их можно интерпретировать как "система в порядке", когда на самом деле означает, что "система так же хороша" как наша стратегия тестирования ". Часто стратегия тестирования не проверяется. Или кто тестирует тесты?
Таким образом, меня больше беспокоит «управляемый» бит в TDD, чем «тестовый» бит. Тестирование в порядке; что я не получаю, так это управляя дизайном.
Я хотел бы видеть ответы, содержащие причины, по которым TDD в разработке программного обеспечения является хорошей практикой, и почему проблемы, которые я объяснил выше, не имеют отношения (или недостаточно) в случае программного обеспечения. Спасибо.
Ответы:
Я думаю, что здесь есть одно заблуждение. В разработке программного обеспечения дизайн очень близок к продукту. В гражданском строительстве, архитектуре дизайн отделен от фактического продукта: есть чертежи, которые содержат дизайн, которые затем материализуются в готовый продукт, и они отделяются огромным количеством времени и усилий.
TDD тестирует дизайн. Но каждый дизайн автомобиля и дизайн здания также проверены. Методы строительства сначала рассчитываются, затем тестируются в меньшем масштабе, затем тестируются в большем масштабе, а затем разрабатываются в реальном здании. Когда они изобрели Н-лучи и нагрузку, например, успокоились, убедившись, что это было опробовано и попробовано еще раз, прежде чем они фактически построят первый мост с ним.
Проектирование автомобилей также проверяется путем разработки прототипов и, конечно, путем корректировки не совсем правильных вещей, пока они не оправдают ожиданий. Часть этого процесса, однако, медленнее, потому что, как вы сказали, вы не можете много возиться с продуктом. Но каждая модернизация автомобиля основывается на опыте, извлеченном из предыдущих, и каждое здание имеет около двух тысяч лет основополагающих принципов важности пространства, света, изоляции, прочности и т. Д. Детали меняются и улучшаются как в зданиях. и в редизайне для новых.
Также запчасти проверяются. Возможно, не совсем в том же стиле, что и программное обеспечение, но механические детали (колеса, воспламенители, кабели) обычно измеряются и подвергаются напряжению, чтобы знать, что размеры правильны, никаких отклонений от нормы не видно и т. Д. Они могут быть рентгеновскими или лазерными. измеряя, они стучат кирпичи, чтобы обнаружить сломанные, они могут быть фактически проверены в той или иной конфигурации, или они рисуют ограниченное представление большой группы, чтобы действительно проверить это.
Это все, что вы можете использовать с TDD.
И действительно, тестирование не является гарантией. Программы рушатся, машины ломаются, а здания начинают делать забавные вещи, когда дует ветер. Но ... «безопасность» не является логическим вопросом. Даже когда вы не можете включить все, возможность покрыть, скажем, 99% возможных случаев лучше, чем покрыть только 50%. Не тестирование, а затем обнаружение, что сталь плохо осела, хрупкая и ломается при первом же ударе молотка, когда вы просто поднимаете основную конструкцию, - пустая трата денег. То, что есть другие проблемы, которые могут все еще повредить здание, не делает его менее глупым, чтобы позволить легко предотвратимому недостатку разрушить Ваш дизайн.
Что касается практики TDD, это вопрос баланса. Стоимость выполнения этого одним способом (например, не тестирование, а затем сбор частей), в отличие от стоимости выполнения этого другим способом. Это всегда баланс. Но не думайте, что в других процессах проектирования нет тестирования и TDD.
источник
ИМО, большинство историй успеха для TDD являются поддельными и только для маркетинговых целей. Может быть очень мало успеха с ним, но только для небольших приложений. Я работаю над большим приложением Silverlight, в котором используются принципы TDD. Приложение прошло сотни тестов, но оно все еще не стабильно. Некоторые части приложения не могут быть протестированы из-за сложных взаимодействий с пользователем. Результирующие тесты с большим количеством насмешек и сложным для понимания кодом.
Первоначально, когда мы попробовали TDD, все это кажется хорошим. Я был в состоянии написать много тестов и макет частей, которые являются трудными для юнит-теста. Если у вас есть достаточное количество кода и требуется смена интерфейса, вы облажались. Необходимо исправить множество тестов, и вы перепишете больше тестов, чем реальное изменение в коде.
Питер Норвиг объясняет свой взгляд на TDD в книге «Кодировщики на работе».
источник
well, you haven't done TDD right!
Test Driven Design работает для меня по следующим причинам:
Это работоспособная форма спецификации.
Это означает, что вы можете видеть из тестовых случаев:
Сначала вы пишете вид снаружи.
Часто код пишется таким образом, что вы сначала решаете проблему, а затем думаете о том, как должен быть вызван код, который вы только что написали. Это часто создает неудобный интерфейс, потому что зачастую проще «просто добавить флаг» и т. Д. Думая, что «нам нужно сделать ЭТО, чтобы тестовые сценарии выглядели так, как раньше», вы поворачиваете это вокруг. Это даст лучшую модульность, так как код будет написан в соответствии с вызывающим интерфейсом, а не наоборот.
Это обычно приводит к более чистому коду, который требует меньше поясняющей документации.
Вы сделали быстрее
Поскольку у вас есть спецификация для запускаемой формы, вы закончите, когда пройдёт полный набор тестов. Вы можете добавить больше тестов, когда будете прояснять ситуацию на более детальном уровне, но в качестве основного принципа у вас есть очень четкий и видимый индикатор прогресса и того, когда вы закончите.
Это означает, что вы можете сказать, когда работа необходима или нет (помогает ли она пройти тест), в итоге вам нужно делать меньше.
Для тех, кто размышляет над этим, это может быть полезно для них, я призываю вас использовать TDD для вашей следующей библиотечной процедуры. Медленно установите работоспособную спецификацию и заставьте код пройти тесты. Когда все готово, работоспособная спецификация доступна всем, кому нужно посмотреть, как вызвать библиотеку.
Недавнее обучение
«Результаты тематических исследований показывают, что плотность дефектов перед выпуском четырех продуктов снизилась на 40–90% по сравнению с аналогичными проектами, в которых не использовалась практика TDD. Субъективно команды испытали увеличение на 15–35% время первоначальной разработки после принятия TDD. " ~ Результаты и опыт 4 промышленных команд
источник
Процесс создания программного обеспечения - это не процесс написания кода. Ни один программный проект не должен начинаться без «широкого плана». Точно так же, как проект по соединению двух берегов реки, сначала нужен такой план.
Подход TDD (главным образом) относится к модульному тестированию - по крайней мере, так люди думают об этом, - это создание самых низкоуровневых фрагментов программного кода. Когда все функции и поведение уже определены, и мы действительно знаем, чего хотим достичь.
В структурном проектировании это выглядит примерно так:
Для тестирования программного обеспечения в целом мы разрабатываем другие виды тестов, такие как юзабилити-тесты, интеграционные тесты и приемочные тесты. Они также должны быть определены до начала фактической работы по написанию кода и выполняются после того, как модульные тесты станут зелеными.
См. V-модель: http://en.wikipedia.org/wiki/V-Model_%28software_development%29
Давайте посмотрим, как это будет работать для моста:
Местное правительство говорит мостостроительной компании: «Нам нужен мост, чтобы соединить эти две точки. Мост должен иметь возможность пропускать n трафика в час и быть готовым к 21 декабря 2012 года» - это определение приемочный тест. Компания не получит полную сумму (или любую) денег, если они не смогут пройти этот тест.
Руководство компании определяет график проекта. Они создали рабочие команды и поставили цели для каждой команды. Если команды не достигнут этих целей - мост не будет построен вовремя. Однако здесь есть некоторый уровень гибкости. Если у одной из команд есть какие-то проблемы, компания может компенсировать это, изменяя требования, меняя субподрядчиков, нанимая больше людей и т. Д., Чтобы весь проект все еще достиг цели, поставленной в пункте № 1.
В команде, ответственной за разработку конкретных компонентов моста, это выглядит как в приведенном выше примере. Иногда решение очевидно, потому что у нас есть большой опыт в создании мостов (это похоже на использование хорошо протестированной библиотеки при разработке программного обеспечения - вы просто предполагаете, что она работает так, как рекламируется). Иногда вам нужно создать несколько дизайнов и протестировать их, чтобы выбрать лучший. Тем не менее, критерии, по которым тестируется компонент, известны заранее.
источник
На мой взгляд, TDD работает, потому что
В частности, по вопросам, которые вы поднимаете
источник
TL; DR
Программирование - все еще проектная деятельность, это не строительство. Написание модульных тестов после факта только подтверждает, что код делает то, что делает, а не то, что он делает что-то полезное. Неудачные тесты - это реальная ценность, потому что они позволяют рано выявлять ошибки.
Код это дизайн
В главе 7 ГЧП «Дядя Боб» рассказывает об этой проблеме напрямую. Очень рано в этой главе он ссылается на прекрасную статью Джека Ривза, в которой он предлагает, что код является дизайном (ссылка ведет на страницу, на которой собраны все три его статьи по этой теме).
Что интересно в этом аргументе, так это то, что он указывает, что в отличие от других инженерных дисциплин, где конструирование является очень дорогостоящим занятием, создание программного обеспечения является относительно бесплатным (нажмите «compile» в вашей среде IDE, и у вас будет ваше встроенное программное обеспечение). Если вы рассматриваете написание кода как деятельность по проектированию, а не как конструирование, тогда цикл красно-зеленый-рефакторинг - это, по сути, упражнение в дизайне. Ваш дизайн развивается по мере того, как вы пишете тесты, код для их удовлетворения и рефакторинг для интеграции нового кода в существующую систему.
TDD как спецификация
Модульные тесты, которые вы пишете для TDD, являются прямым переводом спецификации, как вы их понимаете. При написании кода, который минимально удовлетворяет вашей спецификации (заставляет ваши тесты становиться зелеными), весь код, который вы написали, предназначен для конкретной цели. Была ли достигнута эта цель, подтверждается повторяющимся тестом.
Напишите тесты на функциональность
Распространенная ошибка в модульном тестировании возникает, когда вы пишете тесты после кода, в итоге вы проверяете, что код делает то, что делает. Другими словами, вы увидите такие тесты
Хотя я думаю, что этот код может быть полезен (убедитесь, что кто-то не сделал что-то непристойное с простым свойством). Это не служит для проверки спецификации. И, как вы сказали, написание такого рода тестов только у вас далеко.
В то время как зеленый цвет хорош, ценность лежит в красном У меня был первый настоящий «ага» момент в TDD, когда я получил неожиданный провал теста. У меня был набор тестов, которые я имел для структуры, которую я строил. Добавив новую функцию, я написал для нее тест. Затем написал код для прохождения теста. Скомпилируйте, протестируйте ... получил новый тест. Но также получил красный на другом тесте, который я не ожидал пойти красным.
Глядя на неудачу, я вздыхаю с облегчением, потому что сомневаюсь, что поймал бы эту ошибку в течение достаточно долгого времени, если бы у меня не было этого теста. И это была ОЧЕНЬ неприятная ошибка. К счастью, у меня был тест, и он сказал мне точно, что мне нужно было сделать, чтобы исправить ошибку. Без теста я бы продолжал собирать свою систему (с ошибкой, заражающей другие модули, которые зависели от этого кода), и к тому времени, когда ошибка была обнаружена, было бы серьезной задачей правильно ее исправить.
Истинное преимущество TDD заключается в том, что он позволяет нам вносить изменения безрассудно. Это как сеть безопасности для программирования. Подумайте о том, что произойдет, если художник трапеции совершит ошибку и упадет. С сетью это неловкая ошибка. Без, это трагедия. В этом отношении TDD избавляет вас от превращения ошибок с головой в катастрофы, убивающие проект.
источник
Вы не найдете никого, кто выступал бы за разработку через тестирование или даже за дизайн, управляемый тестами (они разные), который говорит, что тесты подтверждают приложения. Так что давайте просто назовем это соломенным человеком и все будет готово.
Вы не найдете никого, кто не любит или не впечатлен TDD, который говорит, что тесты - пустая трата времени и усилий. Хотя тесты не подтверждают приложения, они весьма полезны при поиске ошибок.
С учетом этих двух вещей ни одна из сторон не делает ничего особенного в том, что касается выполнения тестов программного обеспечения. Оба делают тестирование. Оба полагаются на тестирование, чтобы найти как можно больше ошибок, и оба используют тесты, чтобы убедиться, что программа работает так же хорошо, как и может быть обнаружена в то время. Никто с половинной подсказкой не продает программное обеспечение без тестирования, и никто с половинной догадкой не ожидает, что тестирование сделает код, который они продают, абсолютно безошибочным.
Таким образом, разница между TDD и не-TDD заключается не в том, что проводятся тесты. Разница в том, когда тесты написаны. В TDD тесты пишутся ДО программного обеспечения. В не-TDD тесты пишутся после или совместно с программным обеспечением.
Проблема, с которой я столкнулся в связи с последним, заключается в том, что тестирование имеет тенденцию нацеливаться на написанное программное обеспечение больше, чем на желаемый результат или спецификацию. Даже при том, что команда тестирования отделена от команды разработчиков, команда тестирования стремится смотреть на программное обеспечение, играть с ним и писать тесты, которые нацелены на него.
Те, кто изучает успех проекта, снова и снова замечают то, как часто заказчик выкладывает то, что хочет, разработчики убегают и что-то пишут, и когда они возвращаются к клиенту, говоря «сделано» оказывается, что это совершенно и совсем НЕ то, о чем просил клиент. «Но он проходит все испытания ...»
Цель TDD - сломать этот «круговой аргумент» и обеспечить основу для тестов, тестирующих программное обеспечение, а не само программное обеспечение. Тесты написаны, чтобы нацелить поведение, которое хочет "клиент". Программное обеспечение тогда написано, чтобы пройти те тесты.
TDD является частью решения, предназначенного для решения этой проблемы. Это не единственный шаг, который вы делаете. Другие вещи, которые вам нужно сделать, это убедиться, что есть больше отзывов клиентов и чаще.
По моему опыту, TDD - очень сложная вещь для успешной реализации. Трудно получить тесты, написанные до того, как появится продукт, потому что для многих автоматизированных тестов требуется что-то, с чем можно поиграть, чтобы программное обеспечение для автоматизации работало правильно. Также трудно заставить разработчиков, которые не привыкли к юнит-тестированию, делать это. Снова и снова я говорил людям из моей команды писать тесты в первую очередь. У меня никогда не было того, кто это сделал. В конце концов, временные ограничения и политика разрушили все усилия, поэтому мы даже больше не проводим модульные тесты. Это, конечно, неизбежно приводит к тому, что дизайн оказывается случайно и жестко связанным, так что даже если бы мы захотели, его реализация была бы чрезмерно дорогостоящей. Избегание ЭТО - то, что TDD в конечном счете предоставляет разработчикам.
источник
Сначала дизайн
TDD не освобождает от ответственности за пропуск дизайна. Я видел, как многие прыгали в «проворный» фургон, потому что они могли начать кодировать сразу. Подлинная гибкость позволит вам гораздо быстрее использовать стат-кодирование, чем (в других областях), для разработки передовых методов, которые вдохновили процесс водопада.
Но проверить рано
Когда кто-то говорит, что тест является движущей силой проекта, это просто означает, что можно использовать тесты очень рано на этапе проектирования, задолго до его завершения. Выполнение этих тестов сильно повлияет на ваш дизайн, бросая вызов серым областям и сопоставляя их с реальным миром задолго до того, как продукт будет завершен. заставляя вас часто возвращаться к дизайну и корректировать его, чтобы принять это во внимание.
Тест и дизайн ... одно и то же
По моему мнению, TDD просто делает тестирование неотъемлемой частью дизайна, а не тем, что делается в конце для его проверки. По мере того, как вы все больше и больше начинаете использовать TDD, вы начинаете думать о том, как разрушать / разрушать вашу систему при ее проектировании. Лично я не всегда делаю свои тесты первыми. Конечно, я делаю очевидные (модульные) тесты на интерфейсе, но реальная выгода приходит от тестов интеграции и спецификации, которые я создаю, когда думаю о новом и творческом способе, которым этот дизайн может сломаться. Как только я придумываю способ, я пишу тест для него и смотрю, что произойдет. Иногда я могу жить со следствием, в этом случае я перемещаю тест в отдельный проект, который не является частью основной сборки (так как он по-прежнему будет неуспешным).
Тогда кто ведет шоу?
В TDD это означает, что ваши тесты настолько сильно влияют на ваш дизайн, что можно почувствовать, что они действительно управляют им. Однако на этом все заканчивается, и здесь я понимаю ваши опасения, это немного страшно ... кто ведет шоу?
ВЫ едете, а не тесты. Тесты существуют для того, чтобы, продвигаясь вперед, вы обрели хороший уровень уверенности в том, что вы создали, что позволяет вам строить дальше, зная, что оно основано на прочных основаниях.
твердые, пока испытания твердые
Собственно , отсюда и загнали в TDD. Это не столько тесты, которые движут всем этим, но они будут иметь такое глубокое влияние на то, как вы делаете вещи, на то, как вы проектируете и думаете о своей системе, что вы делегируете большую часть вашего мыслительного процесса тестам и взамен они окажут глубокое влияние на ваш дизайн.
да, но если я сделаю это со своим мостом
остановитесь прямо здесь ... разработка программного обеспечения ОЧЕНЬ отличается от любой другой практики разработки там. На самом деле разработка программного обеспечения имеет много общего с литературой. Можно взять готовую книгу, вырвать из нее 4 главы и написать две новые, чтобы заменить их, вставить их обратно в книгу, и у вас все еще есть хорошая книга. С хорошими тестами и программным обеспечением вы можете разорвать любую часть вашей системы и заменить ее другой, и затраты на это не намного выше, чем в первую очередь при ее создании. На самом деле, если вы провели свои тесты и позволили им достаточно повлиять на ваш дизайн, это может быть гораздо дешевле, чем создавать его в первую очередь, поскольку у вас будет определенный уровень уверенности в том, что эта замена не нарушит то, что охватывают тесты.
Если это так хорошо, почему это не всегда работает?
Потому что тестирование требует ОЧЕНЬ другого мышления, чем построение. Не каждый может переключиться назад и обратно, ведь некоторые люди не смогут построить надлежащие тесты просто потому, что не могут решить разрушить свое творение. Это приведет к тому, что в проектах будет слишком мало тестов или тестов, достаточных для достижения целевых показателей (охват кода). Они будут счастливы тестами пути и исключениями, но забудут о угловых случаях и граничных условиях.
Другие будут просто полагаться на тесты, отказывающиеся от проектирования частично или полностью. Каждый участник делает свое дело, а затем интегрируется друг с другом. Дизайн - это прежде всего инструмент коммуникации, ставки, которые мы ставим на местах, чтобы сказать, что я буду там, эскизы, которые говорят, что именно там будут двери и окна. Без этого ваше программное обеспечение обречено независимо от того, сколько тестов вы в него вложили. Интеграция и слияния всегда будут болезненными, и им не хватит тестов на самых высоких уровнях абстракций.
Для этих команд TDD может оказаться не лучшим способом.
источник
С TDD вы, как правило, не пишете код, который непросто или быстро протестировать. Это может показаться небольшим, но это может оказать глубокое влияние на проект, поскольку оно влияет на то, насколько легко рефакторинг, тестирование, воспроизведение ошибок с тестами и проверка исправлений.
Новому разработчику в проекте также легче освоиться, если у вас есть лучший факторный код, поддерживаемый тестами.
источник
Я много думал об этом, хотя сам не так много практикую TDD. Кажется, существует (сильная?) Положительная корреляция между качеством кода и последующим TDD.
1) Мое первое предположение заключается в том, что это (в первую очередь) не связано с тем, что TDD добавляет «лучшее качество» в код (как таковой), это больше похоже на то, что TDD помогает отсеять наихудшие детали и привычки и, таким образом, косвенно повышает качество.
Я бы даже сказал, что это не сами тесты, а процесс написания этих тестов. Трудно писать тесты на плохой код, и наоборот. И держать это в затылке во время программирования, устраняет много плохого кода.
2) Другая точка зрения (становится философской) - следовать ментальным привычкам мастера. Вы не учитесь становиться мастером, следуя его «внешним привычкам» (например, длинная борода - это хорошо), вы должны изучить его внутреннее мышление, и это сложно. И как-то заставляя (начинающих) программистов следовать TDD, выровнять свои взгляды ближе к мастерскому.
источник
Похоже, у вас неправильное представление о рефакторинге и TDD.
Таким образом, вы не можете рефакторинг кода, пока он не пройдет.
И TDD, в частности модульное тестирование (которое я считаю улучшением ядра, так как другие тесты кажутся мне вполне правдоподобными), не сводится к перестройке компонента до его работы. Речь идет о разработке компонента и работе над реализацией до тех пор, пока компонент не будет работать как задумано.
Также важно понимать, что модульное тестирование - это тестирование модулей . Из-за тенденции всегда писать много вещей с нуля, важно протестировать такие модули. Инженер-строитель уже знает спецификации единиц, которые он использует (различные материалы), и может ожидать, что они будут работать. Это две вещи, которые часто не применимы к разработчикам программного обеспечения, и это очень проработано, чтобы протестировать устройства перед их использованием, потому что это означает использование проверенных, высококачественных компонентов.
Если у инженера-строителя возникла идея использовать новую волокнистую ткань для создания крыши для покрытия стадиона, можно ожидать, что он протестирует ее как единое целое, то есть определит необходимые характеристики (например, вес, проницаемость, устойчивость и т. Д.) И после этого проверьте и доработайте его, пока он не встретит их.
Вот почему TDD работает. Потому что, если вы создаете программное обеспечение из тестируемых модулей, скорее всего, оно работает лучше, когда вы соединяете их вместе, а если нет, вы можете ожидать, что проблема будет в вашем связующем коде, предполагая, что ваши тесты имеют хорошее покрытие.
редактировать:
рефакторинг означает: без изменений в функциональности. Один из пунктов написания модульного теста - убедиться, что рефакторинг не нарушает код. Таким образом, TDD должен гарантировать, что рефакторинг не имеет побочных эффектов.
Детализация не является предметом перспективы, потому что, как я уже сказал, модульные тесты тестируют блоки, а не системы, в результате чего гранулярность точно определяется.
TDD поощряет хорошую архитектуру. Это требует от вас определения и реализации спецификаций для всех ваших устройств, вынуждая их разрабатывать их до начала реализации, что совершенно противоречит тому, что вы думаете. TDD диктует создание блоков, которые могут быть проверены индивидуально и, таким образом, полностью отделены.
TDD не означает, что я провожу программный тест со спагетти-кодом и размешиваю пасту, пока она не пройдет.
В отличие от гражданского строительства, в разработке программного обеспечения проект обычно постоянно развивается. В гражданском строительстве у вас есть требование построить мост в положении A, который может перевозить х тонн и достаточно широкий для n транспортных средств в час.
В области разработки программного обеспечения заказчик может в любой момент решить (возможно, после завершения), что ему нужен двухэтажный мост и что он хочет, чтобы он был соединен с ближайшей автомагистралью, и что он хотел бы, чтобы он был подъемным мостом, потому что его компания Недавно начал использовать парусные корабли.
Разработчики программного обеспечения будут поставлены задача изменить дизайн. Не потому, что их конструкции несовершенны, а потому, что это образ действий. Если программное обеспечение хорошо спроектировано, оно может быть перепроектировано на высоком уровне, без необходимости переписывать все компоненты низкого уровня.
TDD - это создание программного обеспечения с индивидуально протестированными компонентами с высокой степенью разделения. Хорошо выполненный, он поможет вам реагировать на изменения требований значительно быстрее и безопаснее, чем без них.
TDD добавляет требования к процессу разработки, но не запрещает другие методы обеспечения качества. Конечно, TDD не обеспечивает такую же безопасность, как формальная проверка, но опять же, формальная проверка является чрезвычайно дорогой и невозможной для использования на системном уровне. И все же, если вы хотите, вы можете объединить оба.
TDD также включает в себя тесты, отличные от модульных тестов, которые выполняются на системном уровне. Я нахожу это легко объяснить, но трудно выполнить и трудно измерить. Кроме того, они вполне правдоподобны. Хотя я абсолютно вижу их необходимость, я не очень ценю их как идеи.
В конце концов, ни один инструмент на самом деле не решает проблему. Инструменты только облегчают решение проблемы. Вы можете спросить: как долото поможет мне с великолепной архитектурой? Хорошо, если вы планируете делать прямые стены, вам пригодятся прямые кирпичи. И да, конечно, если вы дадите этот инструмент идиоту, он, вероятно, в конце концов ударит его по ноге, но это не ошибка долота, поскольку это не недостаток TDD, который дает ложную защиту новичкам, кто не пишет хорошие тесты.
Таким образом, можно сказать, что TDD работает намного лучше, чем отсутствие TDD.
источник
Мне не нравится, когда вы говорите: «Тест, а не пользователь, устанавливает требования». Я думаю, что вы рассматриваете только модульное тестирование в TDD, тогда как оно также охватывает интеграционное тестирование.
Помимо тестирования библиотек, составляющих основу программного обеспечения, напишите тесты, которые охватывают взаимодействие ваших пользователей с программным обеспечением / веб-сайтом / чем угодно. Они приходят прямо от пользователей, а библиотеки, такие как cucumber (http://cukes.info), могут даже позволить вашим пользователям самим писать тесты на естественном языке.
TDD также поощряет гибкость в коде - если вы потратите навсегда на разработку архитектуры чего-либо, будет невероятно сложно внести эти изменения позже, если это необходимо. Начните с написания пары тестов, затем напишите небольшой код, который пройдет эти тесты. Добавьте больше тестов, добавьте больше кода. Если вам нужно радикально изменить код, ваши тесты остаются в силе.
И в отличии от мостов и машин, одна часть программного обеспечения может претерпевать огромные изменения в течение своей жизни, и делать сложный рефакторинг без тестов , написанных первым , это просто просим неприятность.
источник
Я думаю, что вы приближаетесь к первой точке с неправильного угла.
С теоретической точки зрения мы доказываем, что что-то работает, проверяя точки отказа. Это используемый метод. Может быть много других способов доказать, что что-то функционирует, но TDD зарекомендовал себя благодаря простоте его побитового подхода: если он не ломается, он работает.
На практике это просто откровенно означает: теперь мы можем перейти к следующему пункту (после того, как мы успешно применили TDD для удовлетворения всех предикатов). Если вы подходите к TDD с этой точки зрения, тогда речь идет не о «записи тестов + рефакторинг до прохождения», а скорее о завершении этого, теперь я полностью сосредоточен на следующей функции, как на самой важной .
Подумайте, как это относится к гражданскому строительству. Мы строим стадион, который может вместить 150000 зрителей. После того, как мы доказали, что структурная целостность стадиона является надежной, мы в первую очередь удовлетворили безопасность . Теперь мы можем сосредоточиться на других вопросах, которые становятся незаменимыми, таких как уборная, стойки с едой, места для сидения и т. Д., Что делает восприятие аудитории более приятным Это упрощение, так как TDD гораздо больше, но суть в том, что вы не получаете максимально возможного опыта пользователя, если сосредотачиваетесь на новых и захватывающих функциях и одновременно сохраняете целостность. Вы получаете это наполовину в обоих случаях. Я имею в виду, как вы можете точно знать, какмного туалетов и где разместить 150000 человек? Я редко видел, как стадионы рушатся в моей собственной жизни, но мне приходилось ждать в очереди во время перерыва во многих случаях. Это говорит о том, что проблема туалета, возможно, более сложная, и если инженеры могут тратить меньше времени на безопасность, они, наконец, смогут решить проблему туалета.
Ваш второй пункт не имеет значения, потому что мы уже согласились с тем, что абсолюты - это глупая попытка, и потому что Хэнк Муди говорит, что их не существует (но я не могу найти ссылку на это).
источник
TDD в разработке программного обеспечения является хорошей практикой, так же как обработка ошибок в приложениях является хорошей практикой, а также ведение журнала и диагностика (хотя это является частью обработки ошибок).
TDD не должен использоваться в качестве инструмента для превращения разработки программного обеспечения в метод проб и кодирования ошибок. Но, тем не менее, большинство программистов смотрят в журналы времени выполнения, наблюдают за исключениями в отладчике или используют другие признаки неудачи / успеха на этапе разработки, который состоит из кодирования / компиляции / запуска приложения - в течение всего дня.
TDD - это просто способ формализовать и автоматизировать эти шаги, чтобы сделать вас как разработчика более продуктивным.
1) Вы не можете сравнивать программную инженерию с мостостроением, гибкость в мостостроении совсем не похожа на гибкость разработки программ. Построение моста - это все равно, что снова и снова писать одну и ту же программу на машине с потерями. Мосты не могут быть продублированы и использованы повторно как программное обеспечение. Каждый мост уникален и должен быть изготовлен. То же самое касается автомобилей и других конструкций.
Самое сложное в разработке программного обеспечения - это воспроизведение ошибок, когда отказ моста обычно очень легко определить, что пошло не так, и теоретически легко воспроизвести ошибку. Когда компьютерная программа дает сбой, это может быть сложная цепочка событий, приведшая систему в неисправное состояние, и может быть очень трудно определить, где находится ошибка. TDD и модульное тестирование облегчают тестирование надежности программных компонентов, библиотек и алгоритмов.
2) Использование слабых модульных тестов и неглубоких тестовых примеров, которые не нагружают систему для создания ложного чувства уверенности, является просто плохой практикой. Игнорирование архитектурного качества системы и просто выполнение тестов, конечно же, плохо. Но обманывать на стройке небоскреб или мост, чтобы сэкономить материал и не следовать чертежам, так же плохо, и это происходит постоянно ...
источник
Если вы согласитесь с тем, что чем раньше будут обнаружены ошибки, тем меньше будет стоимость их устранения, то это само по себе делает TDD оправданным.
источник
TDD на самом деле не о тестировании. И это, конечно, не замена для хорошего тестирования. Это дает вам хорошо продуманный дизайн , удобный для потребителя, легкий в обслуживании и последующем рефакторинге. Эти вещи, в свою очередь, приводят к меньшему количеству ошибок и лучшему, более адаптируемому дизайну программного обеспечения. TDD также помогает вам продумывать и документировать свои предположения, часто обнаруживая, что некоторые из них были неверными. Вы обнаружите это очень рано в процессе.
И как приятное побочное преимущество, у вас есть большой набор тестов, которые вы можете запустить, чтобы убедиться, что рефакторинг не меняет поведение (входы и выходы) вашего программного обеспечения.
источник
Я дам вам краткий ответ. Обычно TDD выглядит не так, как модульное тестирование. Я никогда не понимал юнит-тестирование до недавнего времени после просмотра хорошего видео-ролика. По сути, TDD просто заявляет, что вы хотите, чтобы следующие вещи работали. Они ДОЛЖНЫ быть реализованы. Затем вы разрабатываете остальную часть программного обеспечения, как обычно.
Это похоже на написание сценариев использования для библиотеки до ее создания. За исключением того, что вы можете изменить вариант использования в библиотеке, и вы не можете использовать TDD (я использую TDD для разработки API). Вам также рекомендуется добавить больше тестов и подумать о вводных / использованных тестах. Я нахожу это полезным при написании библиотек или API, где, если вы что-то меняете, вы должны знать, что что-то сломали. В большинстве повседневных программ я не беспокоюсь, так как зачем мне тестовый случай для пользователя, нажимающего кнопку, или если я хочу принять список CSV или список с одной записью в строке ... Это действительно не имеет значения, я могу чтобы изменить его, я не должен использовать TDD.
источник
Программное обеспечение органично, когда структурная инженерия конкретна.
Когда вы строите свой мост, он останется мостом, и вряд ли он превратится во что-то другое в течение короткого периода времени. Улучшения будут вноситься месяцами и годами, а не часами и днями, как в программном обеспечении.
Когда вы тестируете изолированно, обычно есть два типа фреймворков, которые вы можете использовать. Ограниченные рамки и неограниченные. Неограниченные фреймворки (в .NET) позволяют вам тестировать и заменять все, независимо от модификаторов доступа. Т.е. вы можете заглушки и издеваться над частными и защищенными компонентами.
Большинство проектов, которые я видел, используют ограниченные фреймворки (RhinoMocks, NSubstitute, Moq). Когда вы тестируете с этими платформами, вы должны спроектировать свое приложение таким образом, чтобы вы могли внедрять и заменять зависимости во время выполнения. Это подразумевает, что у вас должен быть слабо связанный дизайн. Слабосвязанный дизайн (если все сделано правильно) подразумевает лучшее разделение проблем, что является хорошей вещью.
Подводя итог, я считаю, что за этим стоит мысль: если ваш дизайн тестируемый, то он слабо связан и имеет хорошее разделение проблем.
Кроме того, я видел приложения, которые были действительно тестируемыми, но плохо написанными с точки зрения объектно-ориентированного проектирования.
источник
Это не так.
Пояснение: автоматизированные тесты лучше, чем отсутствие тестов. Однако я лично считаю, что большинство модульных тестов - пустая трата времени, потому что они обычно тавтологичны (то есть говорят вещи, очевидные из фактического тестируемого кода), и трудно доказать, что они согласуются, не являются избыточными и охватывают все пограничные случаи (где обычно происходят ошибки). ).
И самое главное: хороший дизайн программного обеспечения волшебным образом не выпадает из тестов, так как его рекламируют многие проворцы и провайдеры TDD. Все, кто заявляет об обратном, пожалуйста, предоставят ссылки на рецензируемые научные исследования, которые это подтверждают, или, по крайней мере, ссылку на какой-нибудь проект с открытым исходным кодом, где преимущества TDD могут быть потенциально изучены его историей изменений кода.
источник