Цель насмешек

В чем смысл издевательства?

Я слежу за некоторыми учебными пособиями по ASP.NET MVC, в которых используется NUnit для тестирования и Moq для имитации. Я немного не понимаю, что это за насмешливая часть.


person Ronnie Overby    schedule 16.06.2009    source источник


Ответы (8)


Цель имитации - изолировать тестируемый класс от других классов.

Это полезно, когда класс:

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

Это также упрощает проверку условий ошибки, поскольку вы создаете свой фиктивный объект, чтобы он возвращал и выдает ошибку, генерирует исключение ...

Макет может записывать, как он был вызван (порядок вызовов функций, параметры), и это можно проверить с помощью теста. РЕДАКТИРОВАТЬ: Например: метод, который вы тестируете, отправляет сообщение, например IPC. Метод фиктивного объекта может записывать, сколько раз он был вызван, параметр, который он получил (то есть сообщение, которое должно быть отправлено). Затем тест может опросить фиктивный объект и подтвердить количество отправленных сообщений, содержание сообщения ... Аналогичным образом, фиктивный объект может записывать методы, которые вызываются в строке журнала, и тест может извлекать эту строку и утверждать в теме.

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

Мок можно закодировать вручную или создать с помощью фреймворка имитации.

person philant    schedule 16.06.2009
comment
Филипп, спасибо за отличный ответ. Меня интересует последнее предложение: «Макет может записывать, как он был вызван (порядок вызовов функций, параметры), и это можно проверить с помощью теста». Это ново для меня, так как я новичок в модульном тестировании / издевательстве. Что было бы примером этого? Звучит полезно. - person theringostarrs; 17.07.2009

Мокинг позволяет изолировать тестируемый класс от его зависимостей. Как правило, вы создаете макет для каждой зависимости для тестируемого класса и настраиваете макет так, чтобы он возвращал ожидаемые значения. Затем вы предоставляете макет тестируемому классу вместо реальной копии класса, от которого зависит ваш тестируемый класс. Затем вы можете использовать фреймворк имитаций, чтобы проверить, были ли сделаны ожидаемые вызовы фиктивным объектам, чтобы убедиться, что ваш тестируемый класс работает правильно.

person tvanfosson    schedule 16.06.2009

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

person kingchris    schedule 16.06.2009
comment
Я знал, что Мать Гранди не справится. Но сопротивление для меня бесполезно, когда дело доходит до этого вопроса - person kingchris; 16.06.2009
comment
Я собирался сказать нечто подобное :) - person Jeff Davis; 16.06.2009
comment
Ну, пожалуйста. Мы можем выступить против коллектива. У нас может быть своя, какая это была Уни-матрица 00 или 01. Ура. - person kingchris; 16.06.2009
comment
Это помогает нам, неуверенным в себе людям, чувствовать себя лучше, указывая на полную глупость других. Признаться, что вы принимаете в этом участие, может быть немного жалко, но это также чертовски весело. - person Charlie Flowers; 10.07.2010

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

  1. Прямой вывод - результат вызова метода
  2. Внутренние изменения - изменения класса во время вызова метода
  3. Косвенный вывод - тестируемый код вызывает другой класс

Государственное тестирование - это все, что касается №1 и №2. # 1, глядя на результат, который дает вам метод. # 2 путем доступа к внутреннему состоянию объекта.

Это оставляет нас с № 3, для которого мы можем пойти двумя путями. Первый - с помощью Mock, а второй - с помощью Test Spy. Основное отличие состоит в том, что в Mock вы создаете ожидания перед выполнением тестируемого кода, а затем заставляете макет проверять их после, тогда как с Test Spy вы выполняете тестируемый код, а затем спрашиваете Test Spy, произошли ли определенные действия.

Итак, подведем итог ... когда вы думаете о тестировании того, что делает класс, если вам нужно протестировать косвенный вывод (он же вызов другого класса), именно здесь в игру вступает Mocking.

person Shane Courtrille    schedule 16.06.2009

Я тоже новичок в насмешках, но я попробую это сделать. По моему опыту, у насмешек есть два основных преимущества:

  • Вы можете начать работать с объектами до того, как напишете реализацию. Вы можете определить интерфейс и использовать имитацию для работы с интерфейсом в модульных тестах или даже в коде.
  • Мокинг позволяет изолировать тестируемый объект в модульных тестах. С помощью фиктивных объектов вы можете полностью контролировать любые объекты, с которыми взаимодействует тестируемый объект, тем самым удаляя внешние зависимости из теста.
person Jamie Ide    schedule 16.06.2009

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

person Carl Manaster    schedule 16.06.2009
comment
Полностью не согласен с последней строкой. Тестирование взаимодействия - побочный эффект имитирующих фреймворков. Моки долгое время создавались вручную с единственной целью государственного тестирования, не полагаясь на реальные ресурсы. - person womp; 16.06.2009
comment
Вот почему я упомянул Mocks Aren't Stubs. Если все, что вы делаете с фреймворком имитаций, - это тестирование состояния (что вполне допустимо для фреймворков имитирования), вы используете заглушки, а не (в более формальном смысле) имитаторы. - person Carl Manaster; 16.06.2009
comment
Полностью не согласен с womp. Я автор оригинального макета бумаги, и мы не это имели в виду. Моки были разработаны как полезный инструмент, помогающий нам задуматься о том, как взаимодействуют объекты. - person Steve Freeman; 30.06.2010

Отличный пример издевательства в реальном времени от Берта Фа

Модульное тестирование

Представьте себе модульное тестирование этой системы:

cook <- waiter <- customer

Обычно легко представить себе тестирование низкоуровневого компонента, такого как cook:

cook <- test driver

Водитель-испытатель просто заказывает разные блюда и проверяет, что повар возвращает правильное блюдо для каждого заказа.

Сложнее протестировать средний компонент, например официанта, который использует поведение других компонентов. Наивный тестировщик может протестировать компонент официанта так же, как мы тестировали компонент готовки:

cook <- waiter <- test driver

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

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

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

    -----------------------
   |                       |
   v                       |
test cook <- waiter <- test driver

Здесь повар-испытатель находится «в сговоре» с водителем-испытателем. В идеале тестируемая система спроектирована таким образом, чтобы можно было легко заменить тестового повара (введенный) работать с официантом без изменения кода продукции (например, без изменения кода официанта).

Макетные объекты

Теперь тестовый повар (тестовый дубль) можно было реализовать по-разному:

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

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

    -----------------------
   |                       |
   v                       |
mock cook <- waiter <- test driver

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

Имитационный объект заранее знает, что должно произойти во время теста (например, вызовы его методов будут вызваны и т. Д.), А фиктивный объект знает, как он должен реагировать (например, какое возвращаемое значение предоставить). Имитация покажет, отличается ли то, что происходит на самом деле, от того, что должно произойти. Пользовательский фиктивный объект может быть закодирован для ожидаемого поведения каждого тестового примера, но фиктивный фреймворк стремится к тому, чтобы такая спецификация поведения была четко и легко указана непосредственно в тестовом примере.

Разговор вокруг имитационного теста может выглядеть так:

От тест-водителя до имитации повара: ожидайте заказа хот-дога и дайте ему в ответ этот пустышка.

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

тестовый драйвер: ТЕСТИРОВАНИЕ УСПЕШНО!

Но так как официант у нас новенький, могло случиться вот что:

От тест-водителя до имитации повара: ожидайте заказа хот-дога и дайте ему в ответ этот пустышка.

тестовый водитель (изображающий из себя клиента) официанту: хотел бы хот-дог, пожалуйста
официант имитирующий повар: 1 гамбургер, пожалуйста
имитирующий повар останавливает тест: Мне сказали ожидать заказ хот-дога! < / em>

тестовый драйвер отмечает проблему: ТЕСТ НЕ ПРОШЕЛ! - официант изменил заказ

or

От тест-водителя до имитации повара: ожидайте заказа хот-дога и дайте ему в ответ этот пустышка.

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

тест-водитель замечает неожиданный картофель фри: ТЕСТ НЕ ПРОШЕЛ! официант вернул не то блюдо

Может быть трудно четко увидеть разницу между макетными объектами и заглушками без контрастного примера на основе заглушек, чтобы пойти с этим, но этот ответ уже слишком длинный :-)

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

person Umar Abbas    schedule 04.04.2014

Еще один ответ:

  • Заглушка = поддельные объекты, чтобы иметь возможность запускать ваш тест без всего реального контекста

  • Mock = поддельный объект для записи взаимодействия вашего компонента и проверки этих взаимодействий.

У вас может быть несколько заглушек в одном тесте, но только один макет, потому что, если у вас более одного макета, вы определенно тестируете более одной функции (и это противоречит цели принципа «тест одно целое»).

Чтобы выйти за рамки основ, Mocks - это больше поведенческая проверка, чем традиционная проверка состояния теста, когда вы проверяете состояние вашего компонента после воздействия на него (Arrange, Act, Assert with Mocks, это больше Arrange, Act, Verify):

Проверка состояния Assert.AreEqual (valueExpected, mycomponent.Property); Поведенческая проверка: myMock.WasCalled (MyMethod);

person MatthieuGD    schedule 23.06.2009