Что такое лондонская и чикагская школы TDD?

88

Я слышал о лондонском и чикагском стилях (иногда их называют стилем Детройта) в Test Driven Development (TDD).

Семинар группы пользователей Utah Extreme Programming:

TDD в стиле взаимодействия также называют mockist-style или London-style после лондонского клуба Extreme Tuesday, где он стал популярным. Это обычно противопоставляется Детройтскому стилю или классическому TDD, который больше основан на состоянии.

Мастерская Джейсона Гормана :

Семинар охватывает как чикагскую школу TDD (тестирование поведения и триангуляции на основе состояния), так и лондонскую школу , которая больше фокусируется на интерактивном тестировании, моделировании и сквозном TDD, с особым акцентом на ответственный дизайн и Скажите, не спрашивайте подход к ОО, недавно повторно популяризированный превосходной книгой Стива Фримена и Ната Прайса « Растущее объектно-ориентированное программное обеспечение, управляемое тестами» .

Пост Классический TDD или "Лондонская школа"? Джейсон Горман был полезен, но его примеры меня смутили, потому что он использует два разных примера вместо одного примера с обоими подходами. В чем различия? Когда вы используете каждый стиль?

Артуро Эрреро
источник

Ответы:

76

Предположим, у вас есть класс с именем «регистр» - метод с именем «вычисления», который использует «калькулятор» для выполнения различных типов вычислений в зависимости от аргументов, переданных для «вычисления», например «multiply (x, y)» или «subtract ( х, у) ".

Теперь предположим, что вы хотите проверить, что происходит, когда вы вызываете ledger.calculate ("5 * 7").

Школа London / Interaction попросит вас подтвердить, был ли вызван Calculator.multiply (5,7). Для этого полезны различные фреймворки, и это может быть очень полезно, например, если вы не являетесь владельцем объекта «Калькулятор» (предположим, что это внешний компонент или сервис, который вы не можете напрямую протестировать, но вы делаете это). знаю, что вы должны позвонить определенным образом).

Чикагская / государственная школа попросила бы вас утверждать, является ли результат 35. Платформы jUnit / nUnit обычно ориентированы на это.

Оба являются действительными и важными тестами.

Мэтью Флинн
источник
Очень хороший пример.
Seseseacat
1
Я добавлю еще несколько причин для использования каждого из них: если важно определить, что что-то изменилось или не изменилось в зависимости от предпринимаемого действия (например, ledger.bucket.value становится 35, когда ledger.calculate ("5 * 7 ") называется), вы хотите использовать утверждения государства (чикагская школа). Это наиболее полезно, когда у вас есть полный контроль над состоянием системы перед вызовом метода, и когда вы фактически контролируете, что делает метод.
Мэтью Флинн
1
Если важно знать, что вызывается второй метод (например, Calculator.multiply (5, 7)), вы хотите использовать утверждения активности, например, через фиктивный объект. Это наиболее полезно, если вызываемый метод имеет желаемый побочный эффект (например, сохранение данных, увеличение счетчика, отправка сообщения и т. Д.), Если вы действительно не контролируете, что делает метод, поэтому возвращаемое значение может быть несовместимым , Кроме того, если вы не можете легко контролировать состояние системы, лучшее, что вы можете сделать, это определить, какие действия происходят.
Мэтью Флинн
Лондонский подход полезен, когда класс Calculator потенциально по какой-то причине долго работает, или использует сеть, и поэтому может быть ошибочным в настройках dev / qa. Т.е. издевательство позволяет вашим тестам быть быстрыми и надежными в тех случаях, когда это было бы иначе невозможно.
Кевин
1
Лондонский подход также предусматривает более четкие сигналы обратной связи, потому что, если Calculatorпроизойдет регрессия multiply, вы увидите два теста не пройдены: тест бухгалтерской книги и тест калькулятора, но только один тест не пройдёт, если вы прогоните калькулятор. Это может помочь определить источник ошибки, особенно если система сложная.
Матиас
30

Статья Мартина Фаулера « Насмешки не заглушки » - хорошее введение в тему.

В зависимости от выбранного вами стиля дизайна (и принципов дизайна, на которых вы строите свои программы), существует как минимум два способа увидеть объект:

  1. Как блок, который выполняет вычисления на основе входных данных. В результате этого вычисления объект может вернуть значение или изменить его состояние.
  2. Как активный элемент, который связывается с другими элементами в системе посредством передачи сообщений.

В первом случае вас интересует, что выходит из обработки или в каком состоянии объект остается после этой обработки. Это где методы, такие как assertEquals()введите изображение. В этом случае не имеет большого значения, какие другие объекты были задействованы в обработке, какие методы были вызваны и т. Д. Этот тип проверки называется проверкой на основе состояния и представляет собой «классический» стиль.

Во втором случае, поскольку большинство объектов даже не возвращают никакого результата (например, voidметоды в Java), вас больше интересует, как объекты взаимодействуют друг с другом и передают ли они правильные сообщения при обстоятельствах, наложенных тестом. Эти взаимодействия обычно проверяются с помощью фиктивных рамок. Этот вид проверки называется проверкой на основе поведения или взаимодействия. Одним из его последствий является метод под названием Behavior Driven Development, с помощью которого вы разрабатываете класс, предполагая, что его соавторы уже существуют (даже если они еще не существуют), поэтому вы можете кодировать их интерфейсы.

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

Отавио Маседо
источник