Почему работает TDD? [закрыто]


92

Разработка через тестирование (TDD) сегодня очень важна. Я часто вижу его рекомендованным в качестве решения для широкого круга проблем здесь, в Programmers SE и других местах. Интересно, почему это работает.

С инженерной точки зрения это озадачивает меня по двум причинам:

  1. Подход "написать тест + рефакторинг до прохождения" выглядит невероятно антиинженерным. Если бы инженеры-строители использовали этот подход для строительства мостов или, например, дизайнеров автомобилей для своих автомобилей, они бы перестроили свои мосты или автомобили по очень высокой цене, и в результате получился бы залатанный беспорядок без хорошо продуманной архитектуры. , Рекомендация «Рефакторинг до сдачи» часто принимается как обязательство забыть архитектурный проект и сделать все необходимое, чтобы выполнить тест; другими словами, тест, а не пользователь, устанавливает требование. В этой ситуации, как мы можем гарантировать хорошие «способности» в результатах, то есть конечный результат, который не только правильный, но и расширяемый, надежный, простой в использовании, надежный, безопасный, надежный и т. Д.? Это то, что архитектура обычно делает.
  2. Тестирование не может гарантировать, что система работает; это может только показать, что это не так. Другими словами, тестирование может показать вам, что система содержит дефекты, если она не проходит тест, но система, которая проходит все тесты, не безопаснее, чем система, которая их не проходит. Тест покрытия, качество теста и другие факторы имеют решающее значение здесь. В гражданских и аэрокосмических отраслях ложные безопасные ощущения, которые производят "все зеленые" результаты, были объявлены чрезвычайно опасными в гражданской и аэрокосмической отраслях, поскольку их можно интерпретировать как "система в порядке", когда на самом деле означает, что "система так же хороша" как наша стратегия тестирования ". Часто стратегия тестирования не проверяется. Или кто тестирует тесты?

Таким образом, меня больше беспокоит «управляемый» бит в TDD, чем «тестовый» бит. Тестирование в порядке; что я не получаю, так это управляя дизайном.

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


53
Мосты, машины и другие физические конструкции далеко не так гибки, как программное обеспечение. Это важное различие и означает, что сравнение между программным обеспечением и реальной разработкой не всегда актуально. То, что работает для мостов, может не работать для программного обеспечения, и наоборот.
Ларс Вирзениус

9
Я несколько согласен с вашими сомнениями. Я, к примеру, должен признаться, у меня сложилось впечатление, что наличие набора тестов может иметь побочный эффект как-то «смягчить» внимание при написании кода. Конечно, тесты - это хорошая вещь (обязательная, если вы хотите иметь возможность провести рефакторинг), но только если они дополняют внимание к деталям, граничным случаям, эффективности или расширяемости, а не заменяют их.
6502

2
@ 6502: Во что бы то ни стало! TDD не является серебряной пулей и не решит все проблемы, возникающие при разработке программного обеспечения. Это, однако, полезный метод организации рабочего процесса. Например, вы можете наложить требование, чтобы все пограничные случаи были покрыты тестами. Вам все еще нужно знать, каковы эти пограничные случаи, но теперь у вас также есть инструмент, чтобы проверить, правильно ли ваш код обрабатывает их.
MCHL

2
@CesarGon, вам также может быть интересен этот вопрос, который я задал на SO некоторое время назад ... Не совсем TDD, но связанный ... Некоторые очень поучительные ответы там.
AviD

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

Ответы:


66

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

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

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

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

Это все, что вы можете использовать с TDD.

И действительно, тестирование не является гарантией. Программы рушатся, машины ломаются, а здания начинают делать забавные вещи, когда дует ветер. Но ... «безопасность» не является логическим вопросом. Даже когда вы не можете включить все, возможность покрыть, скажем, 99% возможных случаев лучше, чем покрыть только 50%. Не тестирование, а затем обнаружение, что сталь плохо осела, хрупкая и ломается при первом же ударе молотка, когда вы просто поднимаете основную конструкцию, - пустая трата денег. То, что есть другие проблемы, которые могут все еще повредить здание, не делает его менее глупым, чтобы позволить легко предотвратимому недостатку разрушить Ваш дизайн.

Что касается практики TDD, это вопрос баланса. Стоимость выполнения этого одним способом (например, не тестирование, а затем сбор частей), в отличие от стоимости выполнения этого другим способом. Это всегда баланс. Но не думайте, что в других процессах проектирования нет тестирования и TDD.


7
+1 за разговор о том, где происходит тестирование на производстве. Отличный момент.
Адам Лир

11
Вы говорите "части проверены". Конечно, но не тест-драйв. Компонент самолета не спроектирован испытанным способом, а выполнен в архитектурном стиле с большим дизайном. Сходства с TDD здесь не существует.
CesarGon

3
В добавление к этому: TDD, по моему мнению, главным образом о способах убедиться, что вы можете проверить детали, а не большое «все или ничего» в конце. Но адажиум TDD «сначала создай тест» не означает «сделай тест, прежде чем думать о том, чего хочешь достичь». Потому что думать о тесте - это часть проектирования. Определение того, что вы хотите, чтобы именно эта часть выполняла, - это проектирование. Прежде чем вы начнете печатать, вы уже выполнили некоторые разработки. (Таким образом, я думаю, что термин «дизайн, управляемый тестами» вводит в заблуждение, говоря об одностороннем пути, где это действительно цикл обратной связи).
Инка

2
+1: софт чисто дизайнерский. Мостовая аналогия в вопросе совершенно неверна. TDD полностью применяется для внешнего модульного тестирования. Тест-управляемый дизайн применяется на всех уровнях дизайна.
С.Лотт

3
@CesarGon: Нет, TDD является движущей DEVELOPMENT путем тестирования. Это отличается от вождения дизайна. Дизайн диктует, как вы будете использовать систему, и, следовательно, какие тесты вам нужно будет выполнить, чтобы воспроизвести это поведение. Реализация этих тестов часто помогает вам улучшить дизайн.
deworde

26

ИМО, большинство историй успеха для TDD являются поддельными и только для маркетинговых целей. Может быть очень мало успеха с ним, но только для небольших приложений. Я работаю над большим приложением Silverlight, в котором используются принципы TDD. Приложение прошло сотни тестов, но оно все еще не стабильно. Некоторые части приложения не могут быть протестированы из-за сложных взаимодействий с пользователем. Результирующие тесты с большим количеством насмешек и сложным для понимания кодом.

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

Питер Норвиг объясняет свой взгляд на TDD в книге «Кодировщики на работе».

Сейбел: А как насчет идеи использования тестов для разработки дизайна?

Norvig: тесты я вижу скорее как способ исправления ошибок, а не как способ проектирования. Этот крайний подход говорит: «Ну, во-первых, вы пишете тест, который говорит, что в конце я получаю правильный ответ», а затем вы запускаете его и видите, что он терпит неудачу, а затем вы говорите: «Что мне делать? дальше нужно? »- это не похоже на правильный способ придумать что-то для меня. Кажется, только если бы это было так просто, что решение было предопределено, это имело бы смысл. Я думаю, что вы должны подумать об этом в первую очередь. Вы должны сказать: «Какие кусочки? Как я могу писать тесты для кусочков, пока не узнаю, что некоторые из них? »И потом, как только вы это сделаете, будет хорошей дисциплиной иметь тесты для каждого из этих кусочков и хорошо понимать, как они взаимодействуют друг с другом. и граничные случаи и тд. У всех должны быть тесты. Но я не думаю, что вы управляете всем проектом, говоря: «Этот тест не удался».


7
Теперь, если вы расскажете об этих фактах людям и консультантам TDD, вы получите ответ:well, you haven't done TDD right!
Navaneeth KN

10
И они были бы правы. Мы выполняем BDD / TDD в очень громоздкой системе, и она работает хорошо. Тесты должны сказать вам, что вы нарушили ожидаемое поведение. Если вы собираетесь изменить это позже, «нарушив» тесты, вы на самом деле делаете это неправильно. Тесты должны быть изменены в первую очередь, чтобы подтвердить НОВОЕ поведение системы, а затем изменить его. И да, если вы все делаете правильно, вы пишете свои тесты, начинающиеся с «что нужно сделать для этого», а процесс написания теста помогает вам подумать «что ИТ-отделам нужно для своей работы». О, и никакие консультанты никогда не использовались ...
Энди

4
Проведение множества тестов не освобождает вас от создания правильного дизайна. Сильно спроектированный дизайн, независимо от того, сколько тестов построено вокруг него, всегда будет хрупким. тесты на встраивание в этот дизайн могут сделать все это еще хуже.
Newtopian

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

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

25

Test Driven Design работает для меня по следующим причинам:

Это работоспособная форма спецификации.

Это означает, что вы можете видеть из тестовых случаев:

  1. То, что вызываемый код полностью заполняет спецификацию, поскольку ожидаемые результаты прямо в тестовых примерах. Визуальный осмотр (который предполагает прохождение тестовых случаев) может сразу сказать: «О, этот тест проверяет, что вызов invoiceCompany в данной ситуации должен иметь результат ТА».
  2. КАК код должен быть вызван. Фактические шаги, необходимые для выполнения тестов, указываются напрямую без каких-либо внешних лесов (базы данных макетируются и т. Д.).

Сначала вы пишете вид снаружи.

Часто код пишется таким образом, что вы сначала решаете проблему, а затем думаете о том, как должен быть вызван код, который вы только что написали. Это часто создает неудобный интерфейс, потому что зачастую проще «просто добавить флаг» и т. Д. Думая, что «нам нужно сделать ЭТО, чтобы тестовые сценарии выглядели так, как раньше», вы поворачиваете это вокруг. Это даст лучшую модульность, так как код будет написан в соответствии с вызывающим интерфейсом, а не наоборот.

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

Вы сделали быстрее

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

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

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

Недавнее обучение

«Результаты тематических исследований показывают, что плотность дефектов перед выпуском четырех продуктов снизилась на 40–90% по сравнению с аналогичными проектами, в которых не использовалась практика TDD. Субъективно команды испытали увеличение на 15–35% время первоначальной разработки после принятия TDD. " ~ Результаты и опыт 4 промышленных команд


5
Я хотел бы добавить к этому, что у вас действительно есть несколько разумных и четких указаний относительно того, когда вы закончите. Без какой-либо четкой процедуры для объективной проверки того, что вы выполнили поставленную задачу, это трудно понять. Мой собственный опыт включает в себя много часов и дней, потраченных впустую на «переговоры» о том, завершена ли задача и постоянное, постоянное движение линии. Это влияет на все уровни управления проектами, включая планирование, как вы можете запланировать такую ​​задачу? Более четкие цели с более быстрым оборотом увеличивают пропускную способность и связь.
Эдвард Стрендж

Это должен быть принятый ответ.
Niing

19

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

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

В структурном проектировании это выглядит примерно так:

«Эти два куска металла соединены вместе, и соединение должно выдерживать сдвиговые усилия в порядке х. Давайте проверим, какой метод подключения является лучшим для этого ».

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

См. V-модель: http://en.wikipedia.org/wiki/V-Model_%28software_development%29

Давайте посмотрим, как это будет работать для моста:

  1. Местное правительство говорит мостостроительной компании: «Нам нужен мост, чтобы соединить эти две точки. Мост должен иметь возможность пропускать n трафика в час и быть готовым к 21 декабря 2012 года» - это определение приемочный тест. Компания не получит полную сумму (или любую) денег, если они не смогут пройти этот тест.

  2. Руководство компании определяет график проекта. Они создали рабочие команды и поставили цели для каждой команды. Если команды не достигнут этих целей - мост не будет построен вовремя. Однако здесь есть некоторый уровень гибкости. Если у одной из команд есть какие-то проблемы, компания может компенсировать это, изменяя требования, меняя субподрядчиков, нанимая больше людей и т. Д., Чтобы весь проект все еще достиг цели, поставленной в пункте № 1.

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


Если я вас правильно понимаю, вы говорите, что с TDD все в порядке, если (а) он используется только для модульного тестирования, и (б) он также сопровождается другими подходами к тестированию. Если это так, он может обратиться к точке № 2 в OP. Как бы вы обратились к точке № 1?
CesarGon

@CesarGon: TDD также отлично работает для интеграционных тестов.
sevenseacat

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

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

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

18

На мой взгляд, TDD работает, потому что

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

В частности, по вопросам, которые вы поднимаете

  • Код более податлив, чем кирпич или сталь, поэтому его дешевле модифицировать. Еще дешевле, если у вас есть тесты, чтобы убедиться, что поведение не изменилось
  • TDD не является оправданием, чтобы не заниматься дизайном - все же рекомендуется использовать архитектуру высокого уровня, но не слишком подробно. Big Up Front Design не рекомендуется, но рекомендуется делать достаточно дизайн
  • TDD не может гарантировать работоспособность системы, но она предотвращает множество мелких ошибок, которые могут быть пропущены. Кроме того, поскольку он обычно поощряет более разборчивый код, его часто легче понять, поэтому он менее подвержен ошибкам.

3
Также следует добавить, что при обнаружении дефектов вы можете быть уверены, что они не будут повторяться, поскольку вы добавите еще один тест.
Энди

16

TL; DR

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

Код это дизайн

В главе 7 ГЧП «Дядя Боб» рассказывает об этой проблеме напрямую. Очень рано в этой главе он ссылается на прекрасную статью Джека Ривза, в которой он предлагает, что код является дизайном (ссылка ведет на страницу, на которой собраны все три его статьи по этой теме).

Что интересно в этом аргументе, так это то, что он указывает, что в отличие от других инженерных дисциплин, где конструирование является очень дорогостоящим занятием, создание программного обеспечения является относительно бесплатным (нажмите «compile» в вашей среде IDE, и у вас будет ваше встроенное программное обеспечение). Если вы рассматриваете написание кода как деятельность по проектированию, а не как конструирование, тогда цикл красно-зеленый-рефакторинг - это, по сути, упражнение в дизайне. Ваш дизайн развивается по мере того, как вы пишете тесты, код для их удовлетворения и рефакторинг для интеграции нового кода в существующую систему.

TDD как спецификация

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

Напишите тесты на функциональность

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

public class PersonTest:Test
{
   [Test]
   TestNameProperty()
   {
      var person=new Person();
      person.Name="John Doe";
      Assert.AreEqual("John Doe", person.Name);
   }
}

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

В то время как зеленый цвет хорош, ценность лежит в красном У меня был первый настоящий «ага» момент в TDD, когда я получил неожиданный провал теста. У меня был набор тестов, которые я имел для структуры, которую я строил. Добавив новую функцию, я написал для нее тест. Затем написал код для прохождения теста. Скомпилируйте, протестируйте ... получил новый тест. Но также получил красный на другом тесте, который я не ожидал пойти красным.

Глядя на неудачу, я вздыхаю с облегчением, потому что сомневаюсь, что поймал бы эту ошибку в течение достаточно долгого времени, если бы у меня не было этого теста. И это была ОЧЕНЬ неприятная ошибка. К счастью, у меня был тест, и он сказал мне точно, что мне нужно было сделать, чтобы исправить ошибку. Без теста я бы продолжал собирать свою систему (с ошибкой, заражающей другие модули, которые зависели от этого кода), и к тому времени, когда ошибка была обнаружена, было бы серьезной задачей правильно ее исправить.

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


4
Значение красных тестов, улавливающих ошибки, является атрибутом модульного тестирования в целом, а не TDD специально.
Роберт Харви

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

1
Можете ли вы подтвердить это утверждение некоторыми доказательствами, данными или тщательным анализом?
CesarGon

1
@CesarGon Это исследование , в то время как программисты, работающие над небольшим проектом, предполагают, что разработчики, использующие TDD, создают код с лучшим охватом тестированием, чем те, которые тестируют после факта (92% -98% против 80% -90%) и, следовательно, получают больше дефекты при разработке (на 18% меньше дефектов, обнаруженных в коде, созданном с использованием TDD).
Жюль

11

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

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

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

Таким образом, разница между TDD и не-TDD заключается не в том, что проводятся тесты. Разница в том, когда тесты написаны. В TDD тесты пишутся ДО программного обеспечения. В не-TDD тесты пишутся после или совместно с программным обеспечением.

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

Те, кто изучает успех проекта, снова и снова замечают то, как часто заказчик выкладывает то, что хочет, разработчики убегают и что-то пишут, и когда они возвращаются к клиенту, говоря «сделано» оказывается, что это совершенно и совсем НЕ то, о чем просил клиент. «Но он проходит все испытания ...»

Цель TDD - сломать этот «круговой аргумент» и обеспечить основу для тестов, тестирующих программное обеспечение, а не само программное обеспечение. Тесты написаны, чтобы нацелить поведение, которое хочет "клиент". Программное обеспечение тогда написано, чтобы пройти те тесты.

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

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


+1 Спасибо за исчерпывающий ответ, Ной. Я согласен, что основное различие между TDD и не-TDD заключается в том, когда тесты написаны. Тем не менее, я также думаю, что первое «D» в TDD означает «управляемый», что означает, что в TDD вся разработка определяется тестированием. Это то, что я нахожу самым загадочным. У меня нет проблем с написанием тестов, прежде чем я на самом деле создаю то, что будет тестироваться. Но позволить тестам ездить? Как это отличается от зеленого света, чтобы делать что-нибудь, пока поверхностный (то есть результат) в порядке?
CesarGon

Что ж, Цезарь, что бы вы предложили в качестве лучшего объективного критерия для решения, когда задача разработки закончена? Если, как и в TDD, тест - это спецификация, на которую нацелен разработчик, то разработчик выполнил свою работу, когда тест пройден, нет? Да, в тесте могут быть недостатки, как и в любой спецификации. Это не задача разработчиков решить, хотя. Если тест ошибочен, тогда он исправлен, тогда разработка нацелена на новую цель, и когда все станет зеленым, все готово. Это работает, потому что ВСЕГДА тест должен пройти ... никакого лишнего, недокументированного пуха.
Эдвард Стрендж

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

Нет. Наши сборки автоматизированы. Они вызваны изменениями. Как я уже сказал, TDD - это только часть решения.
Эдвард Стрендж

9

Сначала дизайн

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

Но проверить рано

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

Тест и дизайн ... одно и то же

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

Тогда кто ведет шоу?

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

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

твердые, пока испытания твердые

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

да, но если я сделаю это со своим мостом

остановитесь прямо здесь ... разработка программного обеспечения ОЧЕНЬ отличается от любой другой практики разработки там. На самом деле разработка программного обеспечения имеет много общего с литературой. Можно взять готовую книгу, вырвать из нее 4 главы и написать две новые, чтобы заменить их, вставить их обратно в книгу, и у вас все еще есть хорошая книга. С хорошими тестами и программным обеспечением вы можете разорвать любую часть вашей системы и заменить ее другой, и затраты на это не намного выше, чем в первую очередь при ее создании. На самом деле, если вы провели свои тесты и позволили им достаточно повлиять на ваш дизайн, это может быть гораздо дешевле, чем создавать его в первую очередь, поскольку у вас будет определенный уровень уверенности в том, что эта замена не нарушит то, что охватывают тесты.

Если это так хорошо, почему это не всегда работает?

Потому что тестирование требует ОЧЕНЬ другого мышления, чем построение. Не каждый может переключиться назад и обратно, ведь некоторые люди не смогут построить надлежащие тесты просто потому, что не могут решить разрушить свое творение. Это приведет к тому, что в проектах будет слишком мало тестов или тестов, достаточных для достижения целевых показателей (охват кода). Они будут счастливы тестами пути и исключениями, но забудут о угловых случаях и граничных условиях.

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

Для этих команд TDD может оказаться не лучшим способом.


7

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

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


2
Мне это нравится - оно подчеркивает тот факт, что его не столько TDD, который создает преимущества (хотя наличие юнит-тестов явно имеет огромное значение), чем вид кода, который он производит в том смысле, что его можно тестировать (изолированно) и из этого вытекают все виды хороших вещей (разделение задач, IoC и внедрение зависимостей и т. д.)
Murph

1
@ Murph, да, TDD помогает тебе быть честным :)
Alb

1
Честно говоря, я на самом деле не убежден аргументом «легче освоиться» - тесты могут быть полезны, но код (в целом, не обязательно изолированный) может быть несколько сложнее декодировать, так как некоторые вещи будут Похоже, как по волшебству, например, вы не знаете, какую реализацию IInjectedThing вы используете.
Murph

@Murph Теория заключается в том, что реализация IInjectedThing также хорошо спроектирована и покрыта хорошими тестами, поэтому вам не нужно знать, что значит понимать класс, в который она внедрена.
Адам Лир

@ Анна - да, до определенного момента ... если вы пытаетесь понять, где что-то сломано (я всегда чувствую, что поиск ошибок - это хороший способ найти основу в проекте) или где что-то нужно изменить / добавил, что вам нужно знать, где. Даже если это хорошо инкапсулировано, вам все равно нужно его найти ... и если это означает что-то заменить (новая реализация IWhatsit), то вам нужно знать, как использовать альтернативную реализацию. Опять же, я не оспариваю, что конструкция плохая - слишком много доказательств обратного - скорее предполагаю, что некоторые вещи могут быть менее очевидными.
Murph

5

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

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

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

2) Другая точка зрения (становится философской) - следовать ментальным привычкам мастера. Вы не учитесь становиться мастером, следуя его «внешним привычкам» (например, длинная борода - это хорошо), вы должны изучить его внутреннее мышление, и это сложно. И как-то заставляя (начинающих) программистов следовать TDD, выровнять свои взгляды ближе к мастерскому.


+1 Я думаю, что ты прибил это, Маглоб. Мне особенно нравится ваше объяснение, что «TDD помогает отсеять худшие детали и привычки, [...] косвенно повышая качество». И аналогия с длинной бородой тоже очень хороша.
CesarGon

вы не пишете тесты для плохого кода, но вы пишете тест, а затем пишете код для прохождения теста.

Маглоб, из-за любви к более практичной стороне дела, ты лучше это понимаешь. @ Thorbjørn, я думаю, что Маглоб все больше следил за тем, чтобы, если ваш проектируемый проект был отстой, ваши тесты, несомненно, должны были бы напрямую подсосать вас до уровня неуместности ваших попыток материализации и гнилого запаха, который должен пахнуть в ваших тестах до Вы даже приступили к написанию любого реального кода.
Филипп Дупанович

3

Подход "написать тест + рефакторинг до прохождения" выглядит невероятно антиинженерным.

Похоже, у вас неправильное представление о рефакторинге и TDD.

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

Таким образом, вы не можете рефакторинг кода, пока он не пройдет.

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

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

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

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

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

В отличие от гражданского строительства, в разработке программного обеспечения проект обычно постоянно развивается. В гражданском строительстве у вас есть требование построить мост в положении A, который может перевозить х тонн и достаточно широкий для n транспортных средств в час.
В области разработки программного обеспечения заказчик может в любой момент решить (возможно, после завершения), что ему нужен двухэтажный мост и что он хочет, чтобы он был соединен с ближайшей автомагистралью, и что он хотел бы, чтобы он был подъемным мостом, потому что его компания Недавно начал использовать парусные корабли.
Разработчики программного обеспечения будут поставлены задача изменить дизайн. Не потому, что их конструкции несовершенны, а потому, что это образ действий. Если программное обеспечение хорошо спроектировано, оно может быть перепроектировано на высоком уровне, без необходимости переписывать все компоненты низкого уровня.

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

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

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

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


Я не думаю, что у меня есть неправильное представление; Я согласен с определением рефакторинга кода, которое вы опубликовали, но я также думаю, что вам нужно взглянуть на детализацию изменений в коде. Когда вы говорите «процесс изменения исходного кода компьютерной программы», вы должны понимать, что с точки зрения определенного целого поведение не меняется, но поведение частей действительно меняется. Вот как происходит изменение. Кроме того, я слышу о том, почему TDD работает (и я им делюсь), но как рассматривается архитектура в соответствии с моим первоначальным постом?
CesarGon

@CesarGon: сообщение обновлено.
back2dos

2

Мне не нравится, когда вы говорите: «Тест, а не пользователь, устанавливает требования». Я думаю, что вы рассматриваете только модульное тестирование в TDD, тогда как оно также охватывает интеграционное тестирование.

Помимо тестирования библиотек, составляющих основу программного обеспечения, напишите тесты, которые охватывают взаимодействие ваших пользователей с программным обеспечением / веб-сайтом / чем угодно. Они приходят прямо от пользователей, а библиотеки, такие как cucumber (http://cukes.info), могут даже позволить вашим пользователям самим писать тесты на естественном языке.

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

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


Я слышу вас о преимуществах, которые вы претендуете на TDD. Но, насколько я понимаю, вы не затрагиваете вопросы архитектуры и качества тестирования, которые я явно задаю в своем вопросе.
CesarGon

@CesarGon: Я думаю, что ваши конкретные вопросы относятся к любому типу тестирования, а не только к TDD. Поэтому я просто сосредоточился на специфических особенностях TDD, которые «работают».
sevenseacat

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

2

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

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

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

Подумайте, как это относится к гражданскому строительству. Мы строим стадион, который может вместить 150000 зрителей. После того, как мы доказали, что структурная целостность стадиона является надежной, мы в первую очередь удовлетворили безопасность . Теперь мы можем сосредоточиться на других вопросах, которые становятся незаменимыми, таких как уборная, стойки с едой, места для сидения и т. Д., Что делает восприятие аудитории более приятным Это упрощение, так как TDD гораздо больше, но суть в том, что вы не получаете максимально возможного опыта пользователя, если сосредотачиваетесь на новых и захватывающих функциях и одновременно сохраняете целостность. Вы получаете это наполовину в обоих случаях. Я имею в виду, как вы можете точно знать, какмного туалетов и где разместить 150000 человек? Я редко видел, как стадионы рушатся в моей собственной жизни, но мне приходилось ждать в очереди во время перерыва во многих случаях. Это говорит о том, что проблема туалета, возможно, более сложная, и если инженеры могут тратить меньше времени на безопасность, они, наконец, смогут решить проблему туалета.

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


+1 за хорошее объяснение моего первого пункта и за ссылку на Хэнка Муди. Славный.
CesarGon

2
Спасибо, я ценю это. Я рассматриваю TDD скорее как психологический феномен, а не как технический подход / процесс. Но это только мое мировоззрение по этому вопросу.
Филипп Дупанович

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

1

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

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

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

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

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

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


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

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

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

1

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


1
Есть ли у вас доказательства того, что ошибки обнаруживаются раньше в настройках TDD? Кроме того, как насчет побочных эффектов TDD, таких как влияние на архитектуру?
CesarGon

0

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

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


6
-1. Многие люди продолжают говорить это, но мне еще предстоит увидеть магию, которая делает это возможным.
Барт ван Инген Шенау

@ Барт ван Инген Шенау, ты сделал TDD? Я занимаюсь этим около 4 лет, и я определенно видел, как происходит «волшебство».
Марси

0

Я дам вам краткий ответ. Обычно TDD выглядит не так, как модульное тестирование. Я никогда не понимал юнит-тестирование до недавнего времени после просмотра хорошего видео-ролика. По сути, TDD просто заявляет, что вы хотите, чтобы следующие вещи работали. Они ДОЛЖНЫ быть реализованы. Затем вы разрабатываете остальную часть программного обеспечения, как обычно.

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


0

Программное обеспечение органично, когда структурная инженерия конкретна.

Когда вы строите свой мост, он останется мостом, и вряд ли он превратится во что-то другое в течение короткого периода времени. Улучшения будут вноситься месяцами и годами, а не часами и днями, как в программном обеспечении.

Когда вы тестируете изолированно, обычно есть два типа фреймворков, которые вы можете использовать. Ограниченные рамки и неограниченные. Неограниченные фреймворки (в .NET) позволяют вам тестировать и заменять все, независимо от модификаторов доступа. Т.е. вы можете заглушки и издеваться над частными и защищенными компонентами.

Большинство проектов, которые я видел, используют ограниченные фреймворки (RhinoMocks, NSubstitute, Moq). Когда вы тестируете с этими платформами, вы должны спроектировать свое приложение таким образом, чтобы вы могли внедрять и заменять зависимости во время выполнения. Это подразумевает, что у вас должен быть слабо связанный дизайн. Слабосвязанный дизайн (если все сделано правильно) подразумевает лучшее разделение проблем, что является хорошей вещью.

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

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


0

Почему работает TDD?

Это не так.

Пояснение: автоматизированные тесты лучше, чем отсутствие тестов. Однако я лично считаю, что большинство модульных тестов - пустая трата времени, потому что они обычно тавтологичны (то есть говорят вещи, очевидные из фактического тестируемого кода), и трудно доказать, что они согласуются, не являются избыточными и охватывают все пограничные случаи (где обычно происходят ошибки). ).

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.