Цикл Красный - Зеленый - Рефактор для TDD хорошо установлен и принят. Мы пишем один провальный модульный тест и делаем его максимально простым. Каковы преимущества этого подхода по сравнению с написанием множества неудачных модульных тестов для класса и заставляют их пройти все сразу?
Набор тестов по-прежнему защищает вас от написания неверного кода или ошибок на этапе рефакторинга, так в чем же вред? Иногда проще сначала написать все тесты для класса (или модуля) в виде «разгрузки мозгов», чтобы быстро записать все ожидаемое поведение за один раз.
unit-testing
development-process
tdd
оборота RichK
источник
источник
Ответы:
Проектирование, основанное на тестировании, направлено на то, чтобы получить правильный API , а не код.
Преимущество написания простейших неудачных тестов заключается в том, что вы получаете свой API (который, по сути, разрабатываете на лету) настолько просто, насколько это возможно. Впереди.
Любое будущее использование (которым являются следующие тесты, которые вы пишете) будет исходить из первоначального простого проекта, а не из неоптимального проекта, справляющегося с более сложными случаями.
источник
Когда вы пишете один тест, вы концентрируетесь на одном .
С помощью множества тестов вы распространяете свое внимание на множество задач, так что это не очень хорошая идея.
источник
Одна из трудностей при написании модульных тестов заключается в том, что вы пишете код, и это само по себе потенциально может быть подвержено ошибкам. Существует также вероятность того, что вам может понадобиться изменить свои тесты позже в результате рефакторинга при написании кода реализации. С TDD это означает, что вы можете в конечном итоге немного увлечься своим тестированием и почувствовать, что вам нужно переписать много по существу «непроверенного» тестового кода по мере развития вашей реализации в ходе проекта. Один из способов избежать такого рода проблем - просто сосредоточиться на выполнении по одной вещи за раз. Это гарантирует, что вы минимизируете влияние любых изменений на ваши тесты.
Конечно, это во многом зависит от того, как вы пишете свой тестовый код. Вы пишете модульный тест для каждого отдельного метода, или вы пишете тесты, которые фокусируются на особенностях / требованиях / поведении? Другой подход мог бы заключаться в использовании подхода, управляемого поведением, с подходящей структурой, и сосредоточиться на написании тестов, как если бы они были спецификациями. Это будет означать либо принятие метода BDD, либо адаптацию тестирования BDD, если вы хотите придерживаться TDD более формально. В качестве альтернативы вы можете полностью придерживаться парадигмы TDD, но при этом изменить способ написания тестов, чтобы вместо того, чтобы полностью сосредоточиться на методах тестирования по отдельности, вы тестировали поведение в более общем смысле как средство удовлетворения специфики реализуемых вами функций требований.
Независимо от конкретного подхода, который вы используете, во всех описанных выше случаях вы используете тестовый подход, поэтому, хотя может показаться заманчивым просто загрузить свой мозг в прекрасный набор тестов, вы также хотите бороться с искушение сделать больше, чем это абсолютно необходимо. Всякий раз, когда я собираюсь запустить новый набор тестов, я начинаю повторять YAGNI для себя, а иногда даже добавляю это в свой комментарий в своем коде, чтобы напомнить мне, чтобы я оставался сосредоточенным на том, что имеет непосредственное значение, и выполняю только минимум, необходимый для удовлетворения требования функции, которую я собираюсь реализовать. Придерживаясь Red-Green-Refactor, убедитесь, что вы это сделаете.
источник
Я думаю, что, делая это, вы упускаете процесс TDD. Просто написав все свои тесты в начале, вы на самом деле не проходите процесс разработки с использованием TDD. Вы просто заранее угадываете, какие тесты вам понадобятся. Это будет совсем другой набор тестов, чем те, которые вы в конечном итоге будете писать, если будете выполнять их по одному во время разработки своего кода. (Если ваша программа не будет тривиальной по своей природе.)
источник
Я «записываю» все тесты, которые могу придумать, во время «мозгового штурма», однако пишу каждый тест как отдельный комментарий, описывающий тест.
Затем я конвертирую один тест в код и выполняю работу, чтобы он скомпилировался и прошел . Часто я решаю, что мне не нужны все тесты, которые я думал, или мне нужны другие тесты, эта информация приходит только от написания кода для прохождения тестов.
Проблема в том, что вы не можете написать тест в коде, пока не создадите метод и классы, которые он тестирует, иначе вы просто получите множество ошибок компилятора, которые помогут вам работать над одним тестом за раз.
Теперь, если вы используете систему, подобную потоку спецификаций, когда тесты написаны на «английском», вы можете попросить клиентов согласиться на набор тестов, пока у вас есть время, а не только на создание одного теста.
источник
Идея TDD - быстрые итерации.
Если у вас есть множество тестов, которые нужно написать перед написанием кода, сложно итеративно реорганизовать ваш код.
Без простого рефакторинга кода вы потеряете много преимуществ TDD.
источник
Из моего (ограниченного) опыта работы с TDD я могу вам сказать, что каждый раз, когда я нарушал дисциплину написания одного теста за раз, дела шли плохо. Это простая ловушка, в которую можно попасть. «О, этот метод тривиален, - подумаете вы, - поэтому я просто выбью эти два других связанных теста и продолжу двигаться». Ну, угадай что? Ничто не так тривиально, как кажется. Каждый раз, когда я попал в эту ловушку, я заканчивал тем, что отлаживал что-то, что, как мне казалось, было легко, но оказалось, что есть странные угловые случаи. И так как я написал несколько тестов одновременно, было много работы, чтобы отследить, где была ошибка.
Если вам нужна мозговая информация, у вас есть много вариантов:
Обратите внимание, что нигде в этом списке нет компилятора. :-)
источник
Вы предполагаете, что знаете, как будет выглядеть ваш код, прежде чем писать его. TDD / BDD - это такой же процесс разработки / обнаружения, как и процесс обеспечения качества. Для данной функции вы пишете простейший тест, который проверяет, удовлетворена ли функция (иногда это может потребовать несколько из-за сложности функции). Этот первый тест, который вы пишете, загружен предположениями о том, как будет выглядеть рабочий код. Если вы пишете весь набор тестов до того, как напишите первую строку кода для его поддержки, вы сделаете целый ряд непроверенных предположений. Вместо этого напишите одно предположение и проверьте его. Тогда напиши следующее. В процессе проверки следующего предположения вы можете просто нарушить более раннее предположение, поэтому вам придется вернуться назад или изменить это первое предположение, чтобы оно соответствовало реальности, или изменить реальность так, чтобы первое предположение все еще действовало.
Думайте о каждом модульном тесте, который вы пишете, как о теории в научной тетради. Заполняя тетрадь, вы доказываете свои теории и формируете новые. Иногда доказательство новой теории опровергает предыдущую теорию, поэтому вы должны ее исправить. Проще доказать одну теорию за раз, чем пытаться доказать, скажем, 20 сразу.
источник
TDD - это итеративный подход, который (по моему опыту) лучше подходит для реальных путей развития. Обычно моя реализация формируется постепенно в течение этого процесса, и каждый шаг может принести дополнительные вопросы, идеи и идеи для тестирования. Это идеально, чтобы сосредоточить свой ум на реальной задаче, и очень эффективно, потому что мне нужно только ограниченное количество вещей хранить в кратковременной памяти в любой момент времени. Это, в свою очередь, уменьшает вероятность ошибок.
Ваша идея - это в основном подход Big Test Up Front, с которым ИМХО сложнее справиться, и он может стать более расточительным. Что если в середине вашей работы вы поймете, что ваш подход не очень хорош, ваш API имеет недостатки и вам нужно начинать все сначала или использовать стороннюю библиотеку вместо этого? Тогда большая часть работы по написанию ваших тестов будет потрачена впустую.
Тем не менее, если это работает для вас, хорошо. Я могу себе представить, что если вы работаете с фиксированной, подробной технической спецификацией, в домене, с которым у вас есть глубокий опыт, и / или над довольно небольшой задачей, у вас может быть готово большинство или все необходимые тестовые сценарии, и ваша реализация будет ясна прямо из начало. Тогда имеет смысл начать с написания всех тестов одновременно. Если ваш опыт показывает, что это делает вас более продуктивным в долгосрочной перспективе, вам не нужно слишком беспокоиться о книгах правил :-)
источник
Помимо одной мысли - одна парадигма TDD - написать наименьший возможный код для прохождения теста. Когда вы пишете один тест за раз, гораздо проще увидеть путь к написанию кода, достаточного для прохождения этого теста. С полным набором тестов, которые вы должны пройти, вы не переходите к коду небольшими шагами, а должны сделать большой скачок, чтобы все они прошли за один раз.
Теперь, если вы не ограничиваете себя написанием кода, заставляющего их все проходить «за один раз», а скорее пишете достаточно кода для прохождения одного теста за раз, он все равно может работать. Вы должны были бы быть более дисциплинированными, чтобы не просто писать дальше и писать больше кода, чем вам нужно. Как только вы начинаете идти по этому пути, вы оставляете себя открытым для написания большего количества кода, чем описывают тесты, что может быть непроверено , по крайней мере, в том смысле, что он не определяется тестом, а возможно, в том смысле, что он не нужен (или выполняется) любым тестом.
Понять, что должен делать метод, в виде комментариев, историй, функциональной спецификации и т. Д., Вполне приемлемо. Я бы подождал, чтобы перевести их в тесты по одному, хотя.
Другая вещь, которую вы можете упустить, написав тесты одновременно, - это процесс мышления, с помощью которого прохождение теста может побудить вас подумать о других тестовых примерах. Без банка существующих тестов вам нужно подумать о следующем тестовом примере в контексте последнего прохождения теста. Как я уже сказал, очень хорошо иметь представление о том, что должен делать метод, но много раз я обнаруживал, что нахожу новые возможности, которые я не рассматривал априори, но которые возникали только в процессе написания тесты. Существует опасность того, что вы можете пропустить их, если только у вас нет привычки думать, какие новые тесты я могу написать, которых у меня еще нет.
источник
Я работал над проектом, в котором разработчики, написавшие (провальные) тесты, отличались от разработчиков, реализующих необходимый код для их прохождения, и я нашел его действительно эффективным.
В этом случае только тесты, связанные с текущей итерацией, были написаны один раз. Так что то, что вы предлагаете, вполне возможно в таком сценарии.
источник
источник
Цикл Red-Green-Refactor - это контрольный список, предназначенный для начинающих разработчиков TDD. Я бы сказал, что было бы неплохо следовать этому контрольному списку, пока вы не узнаете, когда его выполнять, и когда вы можете его сломать (то есть, пока не знаете, не нужно задавать этот вопрос по stackoverflow :)
Проработав TDD в течение почти десятилетия, я могу вам сказать, что я очень редко, если вообще когда-либо, пишу много неудачных тестов, прежде чем писать производственный код.
источник
Вы описываете BDD, где у некоторого внешнего участника есть исполняемая спецификация. Это может быть полезно, если существует заранее определенная предварительная спецификация (например, спецификация формата, промышленный стандарт или если программист не является экспертом в области).
Обычный подход заключается в том, чтобы постепенно охватывать все больше приемочных испытаний, что является прогрессом, видимым для менеджера проекта и заказчика.
Обычно эти тесты указываются и выполняются в среде BDD, такой как Cucumber, Fitnesse или что-то подобное.
Тем не менее, это не то, что вы смешиваете с вашими модульными тестами, которые намного ближе к деталям реализации с множеством аспектов, связанных с интерфейсом API, проблемами инициализации и т. Д., В основном сфокусированными на тестируемом элементе , который является артефактом реализации .
Дисциплина красно-зеленого рефактора имеет много преимуществ, и единственное преимущество, на которое вы можете надеяться, набрав их заранее, - это безубыточность.
источник
Один тест за раз: главное преимущество - сосредоточиться на одном. Подумайте о глубоком дизайне: вы можете углубиться и сосредоточиться на быстрой обратной связи. Вы можете пропустить суть всей проблемы, хотя! Это момент (большой) рефакторинг вступает в игру. Без этого TDD не работает.
Все тесты: анализ и проектирование могут раскрыть вам большую часть проблемы. Подумайте о дизайне в ширину. Вы анализируете проблему с разных сторон и добавляете свой опыт. Это по своей сути сложнее, но может принести интересную выгоду - меньше рефакторинга - если вы делаете «достаточно». Остерегайтесь, это легко переоценить и все же полностью пропустить отметку!
Мне трудно вообще рекомендовать отдавать предпочтение одному или другому, потому что факторов много: опыт (особенно с той же проблемой), знание предметной области и навыки, удобство кода для рефакторинга, сложность проблемы ...
Я предполагаю, что если мы сфокусируемся на типичных бизнес-приложениях, то TDD с его быстрым методом проб и ошибок обычно выигрывает с точки зрения эффективности.
источник
Предполагая, что ваш тестовый фреймворк поддерживает это, я хотел бы предложить вместо того, чтобы реализовывать тесты, которые вы хотите осуществить с помощью мозгового дампинга, вместо этого писать описательные ожидающие тесты, которые вы позже внедрите. Например, если ваш API должен выполнять foo и bar, но не biz, просто добавьте следующий код (этот пример на rspec) для вашего набора тестов, а затем атакуйте их один за другим. Вы быстро обдумываете свои мысли и можете решать все свои проблемы один за другим. Когда все тесты пройдут, вы узнаете, когда решите все проблемы, возникшие у вас во время мозгового приступа.
источник