Все примеры, которые я читал и видел на обучающих видео, имеют упрощенные примеры. Но что я не вижу, как я делаю «настоящий» код после того, как я становлюсь зеленым. Это часть "Refactor"?
Если у меня есть довольно сложный объект со сложным методом, и я пишу свой тест и минимальный минимум, чтобы он прошел (после первого сбоя, красный). Когда я вернусь и напишу настоящий код? И сколько реального кода я пишу перед повторным тестированием? Я предполагаю, что последний - больше интуиции.
Изменить: Спасибо всем, кто ответил. Все ваши ответы очень помогли мне. Кажется, есть разные идеи о том, что я спрашивал или смущал, и, может быть, есть, но я спрашивал, скажем, у меня есть заявление на строительство школы.
В моем дизайне у меня есть архитектура, с которой я хочу начать, пользовательские истории и так далее. Отсюда я беру эти пользовательские истории и создаю тест для проверки пользовательской истории. Пользователь говорит: у нас есть люди, которые записываются в школу и платят за регистрацию. Итак, я думаю о том, как это сделать. При этом я создаю тестовый класс для класса X (возможно, ученик), который не пройдёт. Я тогда создаю класс "Студент". Может быть, "Школа" я не знаю.
Но, в любом случае, TD Design заставляет меня задуматься над историей. Если я могу сделать тест неудачным, я знаю, почему он не проходит, но это предполагает, что я могу его пройти. Речь идет о разработке.
Я сравниваю это с мыслью о рекурсии. Рекурсия не сложная концепция. Может быть, на самом деле сложнее отслеживать это в своей голове, но на самом деле самое сложное - это знать, когда рекурсия «ломается», когда останавливаться (мое мнение, конечно.) Так что я должен думать о том, что останавливает Рекурсия первая. Это только несовершенная аналогия, и она предполагает, что каждая рекурсивная итерация является «проходом». Опять просто мнение.
В реализации, школу труднее увидеть. Цифровые и банковские регистры являются «простыми» в том смысле, что вы можете использовать простую арифметику. Я могу видеть a + b и возвращать 0 и т. Д. В случае системы людей, я должен подумать над тем, как это реализовать . У меня есть понятие провал, пасс, рефакторинг (в основном из-за изучения и этого вопроса.)
То, что я не знаю, основано на отсутствии опыта, по моему мнению. Я не знаю, как не подписать нового студента. Я не знаю, как ошибиться, если кто-то введет фамилию и она будет сохранена в базе данных. Я знаю, как сделать +1 для простой математики, но с такими объектами, как человек, я не знаю, проверяю ли я только, получаю ли я уникальный идентификатор базы данных или что-то еще, когда кто-то вводит имя в база данных или оба или нет.
Или, может быть, это показывает, что я все еще в замешательстве.
Ответы:
Вы не «возвращаетесь» и не пишете «реальный код». Это все настоящий код. Что вы делаете, это возвращаетесь и добавляете еще один тест, который заставляет вас изменить свой код, чтобы пройти новый тест.
Что касается того, сколько кода вы пишете перед повторным тестированием? Никто. Вы пишете нулевой код без неудачного теста, который заставляет вас писать больше кода.
Обратите внимание на шаблон?
Давайте рассмотрим (другой) простой пример в надежде, что это поможет.
Легко peazy.
Не то, что вы бы назвали реальным кодом, верно? Давайте добавим тест, который вызывает изменения.
Мы могли бы сделать что-то глупое
if n == 1
, но мы перейдем к правильному решению.Здорово. Это будет работать для всех номеров, не относящихся к FizzBuzz. Какой следующий ввод заставит изменить производственный код?
И снова. Напишите тест, который еще не прошел.
И теперь мы покрыли все кратные три (которые также не кратны пяти, мы отметим это и вернемся).
Мы еще не написали тест для "Buzz", поэтому давайте напишем это.
И снова, мы знаем, что есть еще один случай, который нам нужно рассмотреть.
И теперь мы можем обрабатывать все кратные 5, которые также не кратны 3.
До этого момента мы игнорировали этап рефакторинга, но я вижу некоторое дублирование. Давайте очистим это сейчас.
Здорово. Теперь мы удалили дублирование и создали хорошо названную функцию. Какой следующий тест, который мы можем написать, заставит нас изменить код? Что ж, мы избежали случая, когда число делится на 3 и 5. Давайте напишем это сейчас.
Тесты пройдены, но у нас больше дублирования. У нас есть варианты, но я собираюсь применить «Извлечь локальную переменную» несколько раз, чтобы мы вместо рефакторинга провели рефакторинг.
И мы рассмотрели каждый разумный вклад, но как насчет необоснованного ввода? Что произойдет, если мы передадим 0 или отрицательный результат? Напишите эти тесты.
Это уже начинает выглядеть как «реальный код»? Что еще более важно, в какой момент он перестал быть «нереальным кодом» и перешел в «реальный»? Об этом стоит подумать ...
Итак, я смог сделать это, просто посмотрев тест, который, как я знал, не пройдёт на каждом этапе, но у меня было много практики. Когда я на работе, все не так просто, и я не всегда знаю, какой тест приведет к изменениям. Иногда я пишу тест и удивляюсь, когда он уже пройден! Я настоятельно рекомендую вам привыкнуть создавать «Тестовый список» перед началом работы. Этот список тестов должен содержать все «интересные» входные данные, которые вы можете придумать. Вы можете не использовать их все, и вы, скорее всего, будете добавлять дела, но этот список служит дорожной картой. Мой список тестов для FizzBuzz будет выглядеть примерно так.
источник
«Настоящий» код - это код, который вы пишете для прохождения теста. Действительно . Это так просто.
Когда люди говорят о написании минимума, чтобы сделать тест зеленым, это просто означает, что ваш реальный код должен следовать принципу YAGNI .
Идея этапа рефакторинга состоит в том, чтобы просто очистить то, что вы написали, когда вы будете удовлетворены требованиями.
Пока тесты, которые вы пишете, действительно соответствуют вашим требованиям к продукту, когда они пройдут, код будет завершен. Подумайте об этом, если у всех ваших бизнес-требований есть тест, и все эти тесты зеленого цвета, что еще можно написать? (Хорошо, в реальной жизни у нас нет склонности к полному тестовому освещению, но теория обоснована.)
источник
switch
с кейсом для каждого модульного теста, который прошел бы все тесты и потерпел неудачу для любых других входных данных.switch
» был задуман как логическая крайность «написания минимума, чтобы сделать тесты зелеными». Я рассматриваю вопрос ОП как: где в TDD принцип, который избегает этого большогоswitch
?Краткий ответ: «реальный код» - это код, который проходит тест. Если вы можете пройти тест с помощью чего-то другого, кроме реального кода, добавьте больше тестов!
Я согласен, что многие учебники о TDD являются упрощенными. Это работает против них. Слишком простой тест для метода, который, скажем, вычисляет 3 + 8, действительно не имеет другого выбора, кроме как также вычислить 3 + 8 и сравнить результат. Это создает впечатление, что вы просто дублируете код повсюду, и это тестирование является бессмысленной, подверженной ошибкам дополнительной работой.
Когда вы хорошо разберетесь в тестировании, вы узнаете, как вы структурируете свое приложение и как вы пишете свой код. Если у вас возникли проблемы с продуманными и полезными тестами, вам, вероятно, следует немного переосмыслить свой дизайн. Хорошо спроектированная система легко тестируется - это означает, что разумные тесты легко продумать и реализовать.
Когда вы сначала пишете свои тесты, наблюдаете, как они проваливаются, а затем пишете код, который делает их успешными, это дисциплина, гарантирующая, что весь ваш код имеет соответствующие тесты. Я не рабски следую этому правилу, когда пишу код; часто пишу тесты по факту. Но выполнение тестов в первую очередь помогает вам быть честным. Имея некоторый опыт, вы начнете замечать, когда закодируете себя в угол, даже если вы сначала не пишете тесты.
источник
assertEqual(plus(3,8), 11)
, а неassertEqual(plus(3,8), my_test_implementation_of_addition(3,8))
. В более сложных случаях вы всегда ищете способ доказать правильный результат, кроме динамического вычисления правильного результата в тесте и проверки равенства.plus(3,8)
вернул правильный результат, вычтя из него 3, вычтя из этого 8 и сравнив результат с 0. Это так очевидно эквивалентно тому,assertEqual(plus(3,8), 3+8)
чтобы быть немного абсурдно, но если тестируемый код строит нечто более сложное, чем просто целое число, то взятие результата и проверка каждой части на правильность часто является правильным подходом. В качестве альтернативы, что-то вродеfor (i=0, j=10; i < 10; ++i, ++j) assertEqual(plus(i, 10), j)
plus()
может добавить 10 к вещам. Конечно, мы все еще полагаемся на проверенные программистом значения начальных циклов.Иногда некоторые примеры о TDD могут вводить в заблуждение. Как уже отмечали другие люди, код, который вы пишете для прохождения тестов, является реальным кодом.
Но не думайте, что настоящий код выглядит как волшебство - это неправильно. Вам нужно лучше понять, чего вы хотите достичь, а затем вам нужно выбрать тест соответственно, начиная с самых простых случаев и угловых случаев.
Например, если вам нужно написать лексер, вы начинаете с пустой строки, затем с группы пробелов, затем числа, затем с числом, окруженным пробелами, затем неправильным числом и т. Д. Эти небольшие преобразования приведут вас к правильный алгоритм, но вы не перепрыгнете с самого простого случая на очень сложный случай, выбранный тупо, чтобы получить реальный код.
Боб Мартин прекрасно объясняет это здесь .
источник
Часть рефактора очищается, когда вы устали и хотите пойти домой.
Когда вы собираетесь добавить функцию, часть рефакторинга - это то, что вы изменяете перед следующим тестом. Вы реорганизуете код, чтобы освободить место для новой функции. Вы делаете это, когда знаете, что это за новая функция. Не тогда, когда вы просто воображаете это.
Это может быть столь же просто , как переименование ,
GreetImpl
чтобыGreetWorld
перед тем, как создатьGreetMom
класс (после добавления теста) , чтобы добавить функцию , которая будет печатать «Привет мама».источник
Но реальный код появится на стадии рефакторинга фазы TDD. Т.е. код, который должен быть частью финальной версии.
Тесты должны выполняться каждый раз, когда вы вносите изменения.
Девиз жизненного цикла TDD будет следующим: RED GREEN REFACTOR
КРАСНЫЙ : написать тесты
ЗЕЛЕНЫЙ : Сделайте честную попытку получить функциональный код, который проходит тесты как можно быстрее: дублирующий код, неизвестные переменные, хаки высшего порядка и т. Д.
РЕФАКТОР : Очистите код, правильно назовите переменные. СУШИТЕ код.
источник
Красная фаза , где писать код.
На этапе рефакторинга основной целью является удаление кода.
В красной фазе вы делаете все, чтобы пройти тест максимально быстро и любой ценой . Вы полностью игнорируете то, что когда-либо слышали о хороших методах кодирования или шаблонах проектирования. Сделать тест зеленым - это все, что имеет значение.
На этапе рефакторинга вы убираете только что созданный беспорядок. Теперь вы сначала посмотрите, является ли изменение, которое вы только что внесли, самым верхним в списке Приоритет преобразования, и если есть какое-либо дублирование кода, вы, скорее всего, можете удалить его, применив шаблон проектирования.
Наконец, вы улучшаете читабельность, переименовывая идентификаторы и извлекая магические числа и / или буквенные строки в константы.
Спасибо за указание на это.
Так что это зеленая фаза, где вы пишете реальный код
В красной фазе вы пишете исполняемую спецификацию ...
источник
Вы пишете настоящий код все время.
На каждом этапе Вы пишете код, удовлетворяющий условиям, которые будет выполнять Ваш код для будущих абонентов Вашего кода (которые могут быть Вами или нет ...).
Вы думаете, что не пишете полезный ( настоящий ) код, потому что через мгновение вы можете его реорганизовать.
Это означает, что, даже если Вы меняете код, условия, которые он выполнял, остаются без изменений. И проверки ( тесты ), которые Вы реализовали для проверки Вашего кода, уже существуют, чтобы проверить, изменились ли Ваши изменения. Таким образом, код, который Вы написали все время, там, просто по-другому.
Другая причина, по которой вы можете подумать, что это не настоящий код, заключается в том, что вы делаете примеры, когда конечная программа уже может быть предвидена вами. Это очень хорошо, так как он показывает вас есть знания о домене Вы программируете в.
Но много раз программистов в области , которая является новой , неизвестной им. Они не знают, каким будет конечный результат, и TDD - это метод написания программ шаг за шагом, документирующий наши знания о том, как должна работать эта система, и проверка того, что наш код работает таким образом.
Когда я читал «Книгу» (*) на TDD, для меня наиболее важной особенностью был список TODO. Это показало мне, что TDD также является техникой, помогающей разработчикам сосредоточиться на одной вещи за раз. Так что это также ответ на Ваш вопрос о том, сколько Реального кода написать ? Я бы сказал, достаточно кода, чтобы сосредоточиться на одной вещи за раз.
(*) «Разработка через тестирование: на примере» Кента Бека
источник
Вы не пишете код, чтобы сделать ваши тесты неудачными.
Вы пишете свои тесты, чтобы определить, как должен выглядеть успех, который изначально должен потерпеть неудачу, потому что вы еще не написали код, который будет проходить.
Весь смысл написания изначально неудачных тестов состоит в том, чтобы сделать две вещи:
Смысл красно-зеленого-рефактора в том, что написание правильных тестов сначала дает вам уверенность в том, что код, который вы написали для прохождения тестов, является правильным, и позволяет вам проводить рефакторинг с уверенностью, что ваши тесты сообщат вам, как только что-то ломается, поэтому вы можете сразу же вернуться и починить это.
По моему собственному опыту (C # /. NET), чистый первый тест - это недостижимый идеал, потому что вы не можете скомпилировать вызов метода, который еще не существует. Таким образом, «сначала проверка» на самом деле касается кодирования интерфейсов и реализации заглушек, а затем написания тестов для заглушек (которые первоначально не пройдут) до тех пор, пока заглушки не будут правильно выделены. Я никогда не пишу «провальный код», просто строю из заглушек.
источник
Я думаю, вы можете запутаться между юнит-тестами и интеграционными тестами. Я считаю, что также могут быть приемочные испытания, но это зависит от вашего процесса.
После того, как вы проверили все маленькие «блоки», вы тестируете их в собранном виде или «интегрированы». Обычно это целая программа или библиотека.
В написанном мной коде интеграция тестирует библиотеку с различными тестовыми программами, которые считывают данные и передают их в библиотеку, а затем проверяют результаты. Тогда я делаю это с потоками. Затем я делаю это с потоками и fork () посередине. Затем я запускаю его и через 2 секунды убиваю -9, затем запускаю и проверяю его режим восстановления. Я размышляю над этим. Я мучаю это всеми способами.
Все это ТАКЖЕ тестирование, но у меня нет довольно красного / зеленого дисплея для результатов. Это либо успешно, либо я копаю несколько тысяч строк кода ошибки, чтобы выяснить, почему.
Вот где вы тестируете «реальный код».
И я только что подумал об этом, но, возможно, вы не знаете, когда вам следует писать модульные тесты. Вы закончили написание модульных тестов, когда ваши тесты выполняют все, что вы должны сделать. Иногда вы можете потерять отслеживание этого среди всех случаев обработки ошибок и крайних случаев, поэтому вы можете захотеть создать хорошую группу тестов счастливого пути, которые просто идут по спецификациям.
источник
В ответ на заголовок вопроса: «Когда вы пишете« реальный »код в TDD?», Ответ: «почти никогда» или «очень медленно».
Вы говорите как студент, поэтому я отвечу так, как будто советую студенту.
Вы будете изучать множество теорий и техник кодирования. Они отлично подходят для того, чтобы проводить время на курсах для студентов с завышенными ценами, но для вас очень мало пользы, которую вы не могли бы прочитать в книге в половине случаев.
Работа кодера заключается исключительно в создании кода. Код, который работает действительно хорошо. Вот почему вы, программист, планируете код в своем уме, на бумаге, в подходящем приложении и т. Д., И вы заранее планируете обходить возможные недостатки / пробелы, логически и латерально думая перед кодированием.
Но вам нужно знать, как разбить ваше приложение, чтобы иметь возможность разрабатывать достойный код. Например, если вы не знали о Little Bobby Table (xkcd 327), то, вероятно, вы не очистите свои входные данные перед работой с базой данных, поэтому вы не сможете защитить свои данные с помощью этой концепции.
TDD - это просто рабочий процесс, предназначенный для минимизации ошибок в вашем коде путем создания тестов того, что может пойти не так, прежде чем кодировать ваше приложение, потому что кодирование может стать экспоненциально сложным, чем больше кода вы вводите, и вы забываете ошибки, о которых когда-то думали. Когда вы думаете, что завершили свое приложение, вы запускаете тесты и бум, надеюсь, ошибки будут обнаружены в ваших тестах.
TDD - это, как полагают некоторые, не написать тест, выполнить его с минимальным кодом, написать другой тест, получить его с минимальным кодом и т. Д. Вместо этого, это способ помочь вам уверенно писать код. Этот идеал непрерывного рефакторинга кода, чтобы заставить его работать с тестами, является идиотским, но это хорошая идея среди студентов, потому что это заставляет их чувствовать себя прекрасно, когда они добавляют новую функцию, и они все еще учатся кодировать ...
Пожалуйста, не бросайте эту ловушку и посмотрите, какова ваша роль кодирования - работа кодера заключается исключительно в создании кода. Код, который работает действительно хорошо. Теперь помните, что вы будете профессиональным программистом, и вашему клиенту будет все равно, если вы напишите 100 000 утверждений или 0. Они просто хотят, чтобы код работал. Действительно хорошо, на самом деле.
источник