Стоит ли модульное тестирование или разработка через тестирование?

48

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

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

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

Кроме того, есть ли что-то, что делает TDD особенно полезным для Scrum?

Оуэн Джонсон
источник
27
Если вы хотите убедиться, что ваше программное обеспечение часто выходит из строя, более или менее полностью не обслуживается и должно быть заменено до того, как оно фактически будет готово к работе; тогда я бы посоветовал вам полностью отказаться от модульного тестирования и никогда не тратить время на изучение TDD.
Дауд говорит восстановить Монику
3
Подумайте о желании / необходимости рефакторинга. Будете ли вы быть более уверенными в том, чтобы действительно выполнить рефакторинг (любой величины) с полным набором тестов или без него, чтобы поймать вас, когда вы случайно что-то сломали?
Марьян Венема
2
«Дает людям опору, когда они пишут настоящий код»? Разве большинство лучших практик не могут быть описаны таким образом?
user16764
4
@DavidWallace: это проблема некомпетентных разработчиков, а не недостаток TDD. Более того, даже когда TDD широко используется, это дает нулевую гарантию того, что внесенные вами изменения ничего не нарушат.
Кодер
6
@NimChimpsky: У меня нет негатива к TDD, я просто не слежу за шумихой. У него есть как положительные стороны, так и отрицательные. Ложное чувство безопасности является одним из них.
Кодер

Ответы:

69

Краткий ответ: абсолютно положительно.

Длинный ответ: Модульные тесты являются одной из наиболее важных практик, которые я пытаюсь использовать на своем рабочем месте (крупный банк, валютная торговля). Да, это дополнительная работа, но это работа, которая окупается снова и снова. Автоматизированные модульные тесты не только помогают вам на самом деле выполнить код, который вы пишете, и, конечно, проверяют ваши ожидания, но они также служат своего рода сторожем для будущих изменений, которые вы или кто-то другой могли бы внести. Пробой теста будет происходить, когда кто-то изменяет код нежелательным образом. Я думаю, что относительная ценность модульных тестов снижается в зависимости от уровня ожидаемого изменения и роста в кодовой базе, но первоначальная проверка того, что код делает, делает его стоящим, даже когда ожидаемое изменение является низким. Значение юнит-теста также зависит от стоимости дефектов. Если стоимость (где затраты - это потеря времени / денег / репутации / будущих усилий) дефекта равна нулю, то относительная ценность теста также равна нулю; однако это почти никогда не имеет место в коммерческой среде.

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

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

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

rupjones
источник
5
Я хотел бы добавить, что модульное тестирование также заставляет задуматься о дизайне интерфейса. Когда вы попадаете в ту часть, где вы думаете: «Как мне выполнить модульное тестирование частных методов?», Вы знаете, что, вероятно, ваш интерфейс ошибочен.
TC1
1
«Я призываю вас попробовать это в течение длительного периода и испытать преимущества самостоятельно». Одной попытки было достаточно для меня, преимущества казались очевидными.
НимЧимпский
1
+1 за «Как правило, мы больше не нанимаем людей, которые обычно не создают модульные тесты как часть своей работы». Недавно мне пришлось отклонить кандидата, который среди прочих недостатков решительно заявил, что он не любит писать автоматические тесты, потому что это пустая трата времени, и он может сам протестировать код.
FTR
4
Вы не можете доказать, что нетривиальный код работает каким-либо соответствующим образом, просто используя автоматические тесты. С помощью автоматических тестов вы можете только доказать, что код проходит тесты - если тесты покрывают 100% ваших вариантов использования, у вас, вероятно, есть «определенный уровень», но это все еще не означает, что код «доказуемо работает». Чтобы иметь реальную доказуемость, вам понадобится en.wikipedia.org/wiki/Formal_verification - как таковой, вы используете термин «доказуемо» неправильно здесь.
vaxquis
1
@vaxquis Да, вы абсолютно правы насчет использования термина «доказательство». Но я бы поспорил, что наличие тестов (или практика TDD) является лучшим доказательством работающей системы, чем отсутствие тестов.
rupjones
16

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

введите описание изображения здесь

Источник изображения

Мартин Викман
источник
Что вы подразумеваете под традиционным ? Что-нибудь, что не является TDD?
Джорджио
Не похоже, что этот график основан на какой-то реальной статистике, он представляет только опыт одного человека, который написал эту запись в блоге в 2006 году. Не то чтобы я говорил, что это совершенно неправильно, но реальность гораздо сложнее.
Док Браун
9

Стоит ли проводить модульное тестирование или разработку через тестирование?

Да, это так . Дядя Боб (Роберт С Мартин) рассказал в презентации;

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

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

На ней написано много вещей,

  1. Вы несете ответственность за работу этой функции. Написать тест. Просто сделай это.
  2. Когда заменить модульные тесты интеграционными тестами

Связаны ли SCRUM, модульное тестирование и TDD?

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

Есть ли что-то, что делает TDD особенно хорошим для SCRUM?

Как я сказал выше, они составляют хорошую комбинацию ; Если вы добавите к нему некоторое автоматизированное тестирование, то оно будет более особенным .

ManuPK
источник
8

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

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

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

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

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

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

Кроме того, есть ли что-то, что делает TDD особенно хорошим для SCRUM?

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

S.Robins
источник
6

Люди думают, что это дополнительные усилия, потому что это прямое занятие. То, что вы теряете во времени сейчас, вы получите позже.

Мои причины для модульного тестирования также включают в себя:

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

Дает вам ощущение прогресса.

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

Обеспечивает дополнительный уровень документации (особенно если вы правильно прокомментируете свои тесты).

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

В этой теме есть и другие статьи, которые также освещаются. Оно того стоит.

Ян
источник
2

Стоит ли модульное тестирование или разработка через тестирование?

Определенно да (см. Другие ответы)

[Это] действительно хорошая идея и стоит усилий и времени?

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

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

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

Если вы делаете TDD, код автоматически легко тестируется.

k3b
источник
2

Позвольте мне подойти к этому с другой стороны. Что происходит, когда вы разрабатываете нетривиальное приложение без юнит-тестов? Если у вас хороший отдел контроля качества, первое, что произойдет, это то, что вы обнаружите, что у вас есть большое количество сообщений о проблемах. Почему, потому что вы не проверяли то, что вы делали, и предполагали, что это сработает, а также потому, что вы не обращали особого внимания на требования, а ваше приложение не соответствует им. Упс обратно на чертежную доску переписать и исправить. Теперь вы внесли исправления и обнаружили целый ряд новых проблем, потому что у вас не было возможности проверить, что ваши исправления не повлияли ни на что другое, прежде чем вы переходите в QA. К сожалению, срок уже наступил, и менеджмент расстроен.

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

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

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

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

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

HLGEM
источник
1

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

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

Что касается подхода красно-зеленого рефактора к TDD, я нахожу это немного утомительным. Но каждому свое.

tylerl
источник
1
Для моего 2c: Чтобы узнать, действительно ли работают ваши тесты, вы должны увидеть, как они провалились, прежде чем увидите, что они пройдут. Я, к сожалению, видел, как многие разработчики писали тесты, которые, казалось, работали, но когда условия теста были изменены, код все равно проходил тест, даже если он должен был провалиться. Если тест не пройден первым и пройден вторым, более вероятно, что вы написали тест без ошибок. Если вы в конечном итоге изменили тест после изменения кода, то вы не можете быть уверены, что код верный. Да, это утомительно, но у него больше шансов быть правильным. :-)
S.Robins
0

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

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

На самом деле есть один тип тестирования, который, как я обнаружил, является общепринятым и который я считаю бесполезным. А именно тестирование на основе графического интерфейса, например, с использованием селена, веб-драйвера, watir или arquillian. Вот так мы получаем 7-часовые циклы сборки, а не 5-минутные циклы сборки в моих проектах TDD.

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

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

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

Себастьян Гозин
источник
1
тесты не являются документацией. TDD - хорошая практика, но разработчики слишком часто используют инструменты автоматического генерирования, которые выдают слишком упрощенные тестовые заглушки. Если у вас есть разработчик, который устойчив к этому, вместо того, чтобы писать мелкозернистые тесты, попробуйте написать больший тестовый набор, который будет использовать больше всего продукта. Они найдут это, очевидно, полезным. Вы все еще должны написать надлежащую документацию, от этого никуда не деться.
gbjbaanb
@gbjbaanb: если разработчики используют инструменты auto-gen, возможно, есть написание модульных тестов, но определенно не TDD. В TDD вы должны написать тест перед методами. Вы не можете автоматизировать скаффолдинг теста метода, который еще не существует. Также хорошо написанными тестами являются документация (техническая документация для коллег-разработчиков проекта, а не требования и руководство пользователя). Хорошо написанные и поддерживаемые модульные тесты покажут вам, какими методами должны быть тесты. И если тесты регулярно проверяются и проходят успешно, они, очевидно, более точны, чем устаревшая документация. Вы не можете этого отрицать.
Крис
Юниттесты могут быть очень хорошей документацией для разработчиков, поскольку они показывают примеры использования API.
k3b
Селен, вебдрайвер и т. Д. В том, что вам не нужно вручную проверять сайт. Таким образом, вы не экономите время, удаляя их из процесса сборки, потому что они сами должны экономить время.
13:30