Поскольку вы говорите, что вы новичок в модульном тестировании и попросили фиктивные объекты в «терминах непрофессионала», я попробую пример дилетанта.
Модульное тестирование
Представьте себе модульное тестирование для этогоsystem:
cook <- waiter <- customer
Как правило, легко представить тестирование низкоуровневого компонента, такого как cook
:
cook <- test driver
Тестовый водитель просто заказывает разные блюда и проверяет, что повар возвращаетправильное блюдо для каждого заказа.
Сложнее проверить средний компонент, например официанта, который использует поведение других компонентов.Наивный тестировщик может проверить компонент официанта так же, как мы тестировали компонент повара:
cook <- waiter <- test driver
Тестировщик закажет разные блюда и обеспечит, чтобы официант вернул правильное блюдо.К сожалению, это означает, что этот тест компонента официанта может зависеть от правильного поведения компонента приготовления.Эта зависимость еще хуже, если у компонента cook есть какие-либо недружественные к тесту характеристики, такие как недетерминированное поведение (меню включает сюрприз шеф-повара как блюдо), множество зависимостей (cook не готовит без всего своего персонала) или многоресурсы (для некоторых блюд требуются дорогостоящие ингредиенты или для их приготовления требуется час).
Поскольку это тест для официантов, в идеале мы хотим тестировать только официанта, а не повара.В частности, мы хотим убедиться, что официант правильно передает заказ клиента повару и правильно доставляет еду повара.
Юнит-тестирование означает независимое тестирование юнитов, поэтому лучшим подходом будет изоляция компонента.тестируемый (официант) с помощью того, что Фаулер называет тестовыми двойниками (манекены, заглушки, подделки, издевательства) .
-----------------------
| |
v |
test cook <- waiter <- test driver
Здесь тест-повар "в сговоре" с тест-драйвером.В идеале тестируемая система спроектирована таким образом, чтобы тестируемый повар мог легко заменить ( впрыскивается ) на работу с официантом без изменения производственного кода (например, без изменения кода официанта).
Mock Objects
Теперь тестовый повар (тестовый дубль) может быть реализован различными способами:
- поддельный повар - кто-то, притворяющийся поваром, используя замороженные обеды и микроволновую печь,
- тупой повар - продавец хот-догов, который всегда дает вам хот-доги, независимо от того, что вы заказываете, или
- поддельный повар - полицейский под прикрытием, следуя сценарию, притворяющемуся поваром вжгучая операция.
См. статью Фаулера для более подробной информации о подделках, окурках, фиктивных и манекенах , но сейчас давайте сосредоточимся на фальшивом поваре.
-----------------------
| |
v |
mock cook <- waiter <- test driver
Большая часть модульного тестирования компонента официанта фокусируется на том, как официант взаимодействует с компонентом повара.Подход, основанный на имитации, фокусируется на полном определении правильного взаимодействия и обнаружении, когда оно идет не так.
Имитируемый объект заранее знает, что должно произойти во время теста (например, какие из его вызовов методов будутвызывается и т. д.), и фиктивный объект знает, как он должен реагировать (например, какое возвращаемое значение предоставить).Насмешка покажет, отличается ли то, что действительно происходит, от того, что должно произойти.Пользовательский фиктивный объект может быть создан с нуля для каждого тестового примера, чтобы выполнить ожидаемое поведение для этого тестового случая, но фреймворк стремится к тому, чтобы такая характеристика поведения была четко и легко указана непосредственно в тестовом примере.
Разговор о фиктивном тесте может выглядеть следующим образом:
тест-водитель до фиктивный повар : ожидать заказа хот-догаи дайте ему этот фиктивный хот-дог в ответ
тест-водитель (выдавая себя за клиента) на официант : Я хотел бы хот-дог, пожалуйста
официант до ложный повар : 1 хот-дог, пожалуйста
ложный повар до официант : оформление заказа: 1 хот-дог готов (дает фиктивного хот-дога официанту)
официант до тест-водитель : вот ваш хот-дог (дает фиктивного хот-дога тест-драйверу)
тестовый водитель : ИСПЫТАНИЕ УСПЕШНО!
Но так как наш официант новичок, вот что может произойти:
тест-водитель до фальшивый повар : ожидайте приказ хот-дога и дайте ему этот фиктивный хот-дог в ответ
тест-водитель (выдавая себя за клиента) до официант : Хотелось бы хот-дог, пожалуйста
официант до ложный повар : 1 гамбургер, пожалуйста
Ложный повар останавливает тест: Мне сказали ожидать заказа хот-дога!
тестовый драйвер отмечает проблему: ТЕСТ НЕ ПРОВЕРЕН! - официант изменил порядок
или
тест-водитель до фальшивый повар : ожидайте приказ хот-дога и дайте ему этот фиктивный хот-дог в ответ
тест-водитель (выдавая себя за клиента) до официант : Хотелось бы хот-дог, пожалуйста
Официант до Ложный повар : 1 хот-дог, пожалуйста
Ложный повар до Официант : Заказ: 1 хот-дог готов (дает фиктивного хот-дога официанту)
официант до тестовый водитель : вот ваш картофель фри (дает картофель фри из какого-то другого заказа для тестирования водителя)
тест-водитель отмечает неожиданную картошку фри: ТЕСТ НЕ УДАЛ! официант вернул неправильное блюдо
Может быть трудно ясно увидеть разницу между фиктивными объектами и заглушками без контрастирующего примера на основе заглушек, но этот ответ уже слишком длинный: -)
Также обратите внимание, что это довольно упрощенный пример, и что фреймворки позволяют использовать довольно сложные спецификации ожидаемого поведения компонентов для поддержки комплексных тестов. Существует множество материалов по макетам объектов и фреймворкам для получения дополнительной информации.