Как провести рефакторинг и обнаружить зависимости при выполнении BDD - PullRequest
2 голосов
/ 29 октября 2011

Выполнение BDD означает переход сверху вниз, поэтому мы сначала пишем тест для функции верхнего уровня. Теперь, чтобы настроить тест, вам обычно нужно установить некоторые макеты вместо реальных делпов. Откуда вы знаете, какие зависимости требуются, какие услуги вам нужны? Я не могу придумать, как определить зависимости на этом уровне. В классическом TDD снизу вверх это было так же просто, как рефакторинг существующего элемента в зависимые объекты.

Означает ли BDD и mocking, что мы должны иметь полный график зависимостей, составленный и грубо спроектированный заранее?

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

Например, у меня есть функция временного кэша для реализации. Мои тесты должны быть:

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

Значит ли это, что мне нужно определить все мои потенциальные зависимости и подготовить макеты? И следует ли мне проверять значения, возвращаемые из моего xall, или только ожидаемые вызовы зависимостей?

Ответы [ 3 ]

4 голосов
/ 30 октября 2011

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

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

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

Иногда я испытываю желание создать огромный набор насмешек, чтобы справиться со всеми возможными непредвиденными обстоятельствами зависимости, о которых я могу думать, и каждый раз, когда я возвращаюсь к повторению "KISS", "YAGNI" и "Make it работать, а потом заставить ее работать лучше », снова и снова в моей голове, пока я не получу сообщение о том, что я не могу позволить себе застрять, потому что я пытаюсь думать слишком далеко вперед.

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

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

1 голос
/ 30 октября 2011

С BDD вы не работаете на уровне единиц (т.е. один публичный метод одного публичного класса).Вы работаете на системном уровне.Поэтому вам захочется смоделировать все, что выходит за границы системы .Это означает, что система хранения или внешняя система будет подвергаться проверке: файлы, базы данных, службы и т. Д.

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

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

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

Надеюсь, это поможет.

0 голосов
/ 30 октября 2011

Не гони за дизайном с верхнего уровня (интеграция?) - тест.

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

Немного коротко, но я надеюсь, вы понимаете, о чем я.

...