TDD против модульного тестирования [закрыто]

117

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

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

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

Как лучше всего привлечь в TDD команду, испытывающую трудности? И если это не так, стоит ли писать модульные тесты, даже если это происходит после написания кода?

РЕДАКТИРОВАТЬ

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

СЛЕДОВАТЬ ЗА

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

Уолтер
источник
1
Вы можете найти эту ветку полезной: stackoverflow.com/questions/917334/should-i-use-tdd
Randolpho
29
+1 для ПОСЛЕДУЮЩИХ ДЕЙСТВИЙ. Это отличная история.
Карл Манастер,

Ответы:

76

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

Когда они овладеют модульным тестированием (и всем, что с ним связано), вы можете работать над тем, чтобы они сначала создавали тесты ... а затем код.

Джастин Нисснер
источник
3
Верно, что раньше команда не создавала никаких модульных тестов. Это похоже на хорошую ступеньку к полной TDD.
Уолтер
Не могу больше с этим согласиться. На самом деле, мне кажется, что я написал нечто подобное для аналогичного вопроса несколько месяцев назад. Где это ... Ааа! stackoverflow.com/questions/917334/should-i-use-tdd/…
Randolpho
27

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

Я думаю, что хороший прагматичный способ вовлечь команду в TDD - это предоставить альтернативный метод «тестирования во время разработки» в переходный период или, возможно, в долгосрочной перспективе. Их следует поощрять к использованию TDD участков кода, которые кажутся им естественными. Однако в разделах кода, которые кажутся сложными для подхода к тестированию, или при использовании объектов, которые предопределены неагильным процессом A&D, разработчикам может быть предоставлена ​​возможность написать небольшой фрагмент кода, а затем написать тесты, чтобы охватить это. код и повторяя этот процесс. Лучше писать модульные тесты для некоторого кода сразу после написания этого кода, чем вообще не писать никаких модульных тестов.

Калеб Браси
источник
16

По моему скромному мнению, лучше иметь 50% тестовое покрытие с «сначала код, потом тест» и 100% завершенную библиотеку, чем 100% тестовое покрытие и 50% завершенную библиотеку с TDD. Мы надеемся, что через некоторое время ваши коллеги-разработчики сочтут интересным и познавательным писать тесты для всего publicкода, который они пишут, поэтому TDD прокрадывается в их рутину разработки.

Асбьёрн Ульсберг
источник
3
Я понимаю ваш дрейф, но я настороженно отношусь к «100% завершенной библиотеке» с 50% тестовым покрытием ... просто исходя из моего опыта, каждый фрагмент кода, не охваченный некоторыми тестами, содержит хотя бы одну ошибку. Или, другими словами: люди склонны избегать написания тестов для кода, которые действительно выиграют от дополнительного тестирования :)
Аарон Дигулла,
2
Другими словами, ошибочный код, который был выпущен, лучше, чем идеальный код, который томится вечно. Очевидно, что есть исключения, кашель НАСА, кашель , но по большей части распространите свой код. Вы все еще можете добавлять тесты после его выпуска.
jcdyer
3
Что вы имеете в виду под «100% завершенной библиотекой». Считаете ли вы его полным, если глючит? Разве вы не включаете "тестирование" в определение "готово"?
Паскаль Тивент
10
тестирование не является достаточным условием для отсутствия ошибок
fa.
2
Покрытие тестами, измеряемое инструментами покрытия тестами, - палка о двух концах. Если это достигается путем вызова всех методов в IUT, но тесты на самом деле не проверяют поведение, которое может нарушиться, разработчики и другие заинтересованные стороны будут иметь ложное чувство безопасности. Все движение в сторону TDD в вашей организации может обернуться вам неприятностями, если критическое поведение останется непроверенным, но при этом у вас есть 100% тестовое покрытие. Главное не количество, а качество.
Дуг Кнесек
12

Я только что прочитал это в календаре: «Каждое правило, выполняемое до предела, становится смешным или даже опасным». Поэтому я предлагаю не относиться к этому религиозно. Каждый член вашей команды должен найти баланс между тем, что он считает «правильным», когда дело касается тестирования. Таким образом, каждый член вашей команды будет наиболее продуктивным (вместо того, чтобы, скажем, думать «зачем мне писать этот строгий тест ??»).

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

Аарон Дигулла
источник
«что они чувствуют» Как разработчик я не помню, чтобы у меня когда-либо возникало (правильное) желание проводить какое-либо автоматическое модульное тестирование с помощью собственных ощущений, только вручную. Не думаю, что одному мне не хватает азарта от тестирования
Геннадий Ванин Геннадий Ванин
@ vgv8: Значит, ваши тесты вам не помогают. Причин может быть множество; Предлагаю копнуть глубже. Любой проект выигрывает от хороших тестов и страдает от плохих. Вы заметите, когда начнете писать хорошие тесты, и с этого момента ничто не сможет помешать вам писать больше.
Аарон Дигулла,
что мне кажется правильным, так это уровень тестирования, который охватывает то, что должны делать программные модули, и с функционального уровня: что пользователи делают нормально, включая плохие результаты, которые некоторые называют «сообщенными ошибками». Если ошибка подтверждается, будет написан хотя бы один тест! чем крупнее проект и больше команда, тем важнее.
DaFi4
12

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

Одно из предложений, которое я могу дать вам, чтобы попытаться убедить вашу команду принять TDD, - это использовать некоторые из техник, описанных в книге «Бесстрашные изменения: шаблоны для внедрения новых идей» Мэри Линн Маннс и Линды Райзинг .

Диего Диас
источник
3
+1: Разработка через тестирование означает, что дизайн был основан на соображениях тестирования.
S.Lott
+1. Позже модульные тесты, конечно, помогут вам, но вы потеряете все преимущества «тестируемого дизайна», если не напишете модульные тесты заранее.
Нуфал Ибрагим
9

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

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

Уэйн Молина
источник
6

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

Нет абсолютно никаких сомнений в том, что в модульном тестируемом коде есть ценность (независимо от того, когда были написаны тесты), и я включаю «код модульно протестирован» в «Определение готово». Люди могут использовать TDD или нет, пока они тестируют.

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

Паскаль Тивент
источник
4

Это то, что вашей команде нужно будет добиться, прежде чем они начнут в это верить. Я буду разглагольствовать о своем прозрении nUnit всем, кому небезразлично:

Около 5 лет назад я открыл для себя nUnit, работая над проектом. Мы почти завершили V1.0, и я создал несколько тестов, чтобы опробовать этот новый инструмент. У нас было много ошибок (очевидно!), Потому что мы были новой командой, у нас были сжатые сроки, большие ожидания (звучит знакомо?) И т. Д. В любом случае мы получили 1.0 и начали с 1.1. Мы немного реорганизовали команду, и мне назначили двух разработчиков. Я сделал для них часовую демонстрацию и сказал, что все, что мы написали, должно иметь тестовый пример. Мы постоянно «отставали» от остальной команды в течение цикла разработки 1.1, потому что мы писали больше кода, модульных тестов. В итоге мы работали больше, но вот результат - когда мы наконец приступили к тестированию, в нашем коде было ровно 0 ошибок. Мы помогли всем остальным отлаживать и исправлять их ошибки. При вскрытии, когда обнаруживается счетчик ошибок,

Я не настолько глуп, чтобы думать, что вы можете проверить свой путь к успеху, но я искренне верю, что касается модульных тестов. Проект принял nUnit и вскоре распространился на все проекты .Net в компании в результате одного успеха. Общий период времени для нашего выпуска V1.1 составил 9 недель разработки, так что это определенно НЕ было мгновенным успехом. Но в долгосрочной перспективе это оказалось успешным для нашего проекта и компании, для которой мы создавали решения.

Нет возврата, нет возврата
источник
«Проект принял nUnit и вскоре распространился по компании для всех проектов .Net» А что делать, если один продукт / проект имеет код C #, Java, C ++, SQL Server?
Геннадий Ванин Геннадий Ванин
Я не знаю ... Найти способ протестировать все компоненты перед развертыванием в производственной среде? Модульное тестирование - это лишь один из аспектов всеобъемлющего плана тестирования, прежде чем он будет запущен. Пробить дыру можно в любом сценарии.
Возврат средств
4

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

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

Дай Бок
источник
3

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

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

Дэвид Бергер
источник
3

Что ж, если вы сначала не пишете тесты, это не «Test Driven», это просто тестирование. Он имеет преимущества сам по себе, и если у вас уже есть база кода, добавление тестов для него, безусловно, полезно, даже если это не TDD, а просто тестирование.

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

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

Kriss
источник
3

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

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

В стороне, но BDD также может быть интересен

danswain
источник
Я не знал о BDD. Мне нужно будет прочитать об этом больше.
Уолтер
3

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

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

Майкл Нэш
источник
2

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

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

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

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

RSP
источник
2

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

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

Этот подход много раз работал у меня в прошлом.

Джон Сонмез
источник
2

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

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

Крис Уэлш
источник
1

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

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

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

Это в равной степени социальное / культурное изменение, так как оно носит технический характер.

Дуг Кнесек
источник