Обнаружение других объектов при выполнении TDD

Я пытаюсь практиковать TDD.

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

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

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

Каким должен быть настоящий TDD'r в этот момент?

  • Оставьте существующий тестовый список в покое и создайте новый для вновь обнаруженного класса (та же проблема может проявиться при реализации нового класса offcourse).
  • Переходите к методу тестирования, основанному на взаимодействии, и отмахивайтесь от нового класса, продолжайте с тестовыми тестами класса, над которым вы работаете, и вернитесь позже, чтобы создать правильную реализацию издевающегося класса.
  • Эта ситуация не должна присутствовать. Я, наверное, не очень хорошо продумал свой первоначальный дизайн. (но разве это не победит одну из целей TDD?!).

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

Ответ 1

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

Я бы добавил, что главный успех TDD заключается в том, чтобы войти в ритм red-green-refactor. Когда вы чувствуете пользу этого ритма, вы начали "получать" его. Это не значит, что вы сочтете это целесообразным во всех случаях, но пока вы не почувствуете, что ритм вы не получили, к чему его защитники любят.

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

EDIT: (В ответ на комментарий). Должен ли новый класс пройти тестирование самостоятельно? Не обязательно. Это зависит от того, развивает ли класс свое значение. Когда вы тестируете устройство, вы тестируете функциональность. Это не интеграционный тест только потому, что есть два класса. Это становится интеграционным тестом, когда две единицы начинают взаимодействовать. Граница, о которой я обычно думаю, заключается в том, что мне нужно настроить значительное состояние в группе классов A для взаимодействия с группой классов B, и особенно если группа классов A вызывает группу классов B и что Я заинтересован в тестировании, как B отреагировал на A, тогда я смотрю на интеграционный тест.

Ответ 2

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

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

Но это тебя беспокоит. Так что делать? Признать, что делегирование другому классу является рефакторингом; это нужно сделать после шага 6 во время шага 7. Как только вы будете зелеными, рефакторинг к лучшему дизайну. У вас уже есть тесты для нового класса; они просто подключены для вызова первоначального класса. Это прекрасно. После извлечения класса и делегирования, если вам было бы более удобно, если бы тесты вызывали извлеченный класс напрямую: пойдите для него. Никакого вреда. Если извлеченный класс начинает использоваться другими абонентами, я бы порекомендовал его, и, возможно, когда вы начнете называть его из других классов, это подходящее время для этого (но если он сейчас васчет, сделайте это сейчас).

Ответ 3

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

Ответ 4

Вы должны создать класс mock. Один интерфейс с предсказуемыми повторами. Таким образом, вы можете протестировать оригинал.

Позже вы можете повторить процедуру с новым классом.