Что такое издевательство? ,
Что такое издевательство? ,
Ответы:
Пролог: если вы посмотрите макет существительного в словаре, вы обнаружите, что одно из определений слова - это нечто, сделанное как подражание .
Насмешка в основном используется в модульном тестировании. Тестируемый объект может зависеть от других (сложных) объектов. Чтобы изолировать поведение объекта, вы хотите заменить другие объекты на макеты, которые имитируют поведение реальных объектов. Это полезно, если реальные объекты нецелесообразно включать в модульный тест.
Короче говоря, издевательство - это создание объектов, которые имитируют поведение реальных объектов.
Иногда вы можете захотеть различить насмешки, а не окурки . Могут быть некоторые разногласия по этому вопросу, но мое определение заглушки - «минимальный» моделируемый объект. Заглушка реализует достаточно поведения, чтобы тестируемый объект мог выполнить тест.
Макет похож на заглушку, но тест также проверит, что тестируемый объект вызывает макет, как и ожидалось. Часть теста проверяет, что макет использовался правильно.
Для примера: вы можете заглушить базу данных, реализовав простую структуру в памяти для хранения записей. Затем тестируемый объект может читать и записывать записи в заглушку базы данных, чтобы позволить ему выполнить тест. Это может проверить некоторое поведение объекта, не связанного с базой данных, и заглушка базы данных будет включена только для запуска теста.
Если вы хотите проверить, что тестируемый объект записывает в базу данных определенные данные, вам придется смоделировать базу данных. Ваш тест будет включать утверждения о том, что было записано в макет базы данных.
Другие ответы объясняют, что такое насмешка. Позвольте мне рассказать вам о разных примерах . И поверьте мне, это на самом деле гораздо проще, чем вы думаете.
tl; dr Это экземпляр оригинального класса. В него вводятся другие данные, поэтому вы избегаете тестирования внедренных частей и сосредотачиваетесь исключительно на проверке деталей реализации вашего класса / функций.
Простой пример:
class Foo {
func add (num1: Int, num2: Int) -> Int { // Line A
return num1 + num2 // Line B
}
}
let unit = Foo() // unit under test
assertEqual(unit.add(1,5),6)
Как видите, я не тестирую LineA, т.е. я не проверяю входные параметры. Я не проверяю, чтобы увидеть, являются ли num1, num2 целыми числами. У меня нет никаких утверждений против этого.
Я только проверяю, чтобы узнать, соответствует ли LineB (моя реализация ) проверенным значениям 1
и 5
работает ли я так, как я ожидаю.
Очевидно, что на самом деле это может стать намного сложнее. Параметры могут быть пользовательскими объектами, такими как Person, Address или подробности реализации могут быть более одного +
. Но логика тестирования была бы такой же.
Предположим, вы создаете машину, которая идентифицирует тип и торговую марку электронных устройств для обеспечения безопасности аэропорта. Машина делает это, обрабатывая то, что видит своей камерой.
Теперь ваш менеджер входит в дверь и просит вас протестировать его.
Тогда вы, как разработчик, можете взять с собой 1000 реальных объектов, таких как MacBook Pro, Google Nexus, банан, iPad и т. Д., И протестировать и посмотреть, все ли работает.
Но вы также можете использовать поддельные объекты, такие как MacBook Pro идентичного вида (без реальных внутренних деталей) или пластиковый банан перед ним. Вы можете спасти себя от инвестиций в 1000 настоящих ноутбуков и гниющих бананов.
Дело в том, что вы не пытаетесь проверить, является ли банан поддельным или нет. Не проверяя, является ли ноутбук подделкой или нет. Все , что вы делаете, тестирование , если ваша машина , когда он видит банан было бы сказать , not an electronic device
и для MacBook Pro было бы сказать: Laptop, Apple
. Для машины результат его обнаружения должен быть одинаковым для поддельной / поддельной электроники и реальной электроники
Упомянутая выше логика применима и к модульному тестированию реального кода. То есть функция должна работать точно так же с реальными значениями, которые вы получаете от реального ввода (и взаимодействий) или издевалисьзначения, которые вы вводите во время юнит-тестирования. И так же, как вы избавляете себя от использования настоящего банана или MacBook, с помощью юнит-тестов (и насмешек) вы избавляете себя от необходимости делать что-то, что заставляет ваш сервер возвращать код состояния 500, 403, 200 и т. Д. (Принуждая ваш сервер запускает 500 только тогда, когда сервер не работает, а 200 - когда сервер работает. Запускается 100 тестов, ориентированных на сеть, если вам приходится постоянно ждать 10 секунд между переключением сервера вверх и вниз). Поэтому вместо этого вы вводите / смоделируете ответ с кодом состояния 500, 200, 403 и т. Д. И проверяете свое устройство / функцию с введенным / проверенным значением.
Допустим, вы пишете приложение для iOS и выполняете сетевые вызовы. Ваша задача - протестировать ваше приложение. Тестировать / определять, работают ли сетевые вызовы должным образом, НЕ ВАША ОТВЕТСТВЕННОСТЬ. Это ответственность другой стороны (серверной команды), чтобы проверить это. Вы должны удалить эту (сетевую) зависимость и все же продолжать тестировать весь свой код, который работает вокруг нее.
Сетевой вызов может вернуть различные коды состояния 404, 500, 200, 303 и т. Д. С ответом JSON.
Предполагается, что ваше приложение будет работать для всех из них (в случае ошибок ваше приложение должно выдать ожидаемую ошибку). Что вы делаете с насмешками, так это то, что вы создаете «мнимые - похожие на реальные» сетевые ответы (например, код 200 с файлом JSON) и тестируете свой код, не «совершая реальный сетевой вызов и не ожидая ответа вашей сети». Вы вручную жестко кодируете / возвращаете сетевой ответ для ВСЕХ типов сетевых ответов и смотрите, работает ли ваше приложение так, как вы ожидаете. (вы никогда не принимаете / тестируете 200 с неверными данными, потому что это не ваша ответственность, ваша ответственность состоит в том, чтобы тестировать ваше приложение с правильными 200, или в случае 400, 500 вы проверяете, если ваше приложение выдает правильную ошибку)
Это создание воображаемого, похожего на реальное, называется насмешкой.
Чтобы сделать это, вы не можете использовать свой оригинальный код (у исходного кода нет предварительно вставленных ответов, верно?). Вы должны что-то добавить к нему, вставить / вставить те фиктивные данные, которые обычно не нужны (или часть вашего класса).
Таким образом, вы создаете экземпляр исходного класса и добавляете к нему все (в данном случае это сетевой HTTPResponse, data ИЛИ в случае сбоя, вы передаете правильный errorString, HTTPResponse), который вам нужен, и затем проверяете фиктивный класс.
Короче говоря, насмешка состоит в том, чтобы упростить и ограничить то, что вы тестируете, а также дать вам понять, от чего зависит класс. В этом примере вы избегаете тестирования самих сетевых вызовов и вместо этого проверяете, работает ли ваше приложение с введенными выводами / ответами так, как вы ожидаете, - путем насмешливых классов
Само собой разумеется, вы проверяете каждый сетевой ответ отдельно.
Теперь вопрос, который я всегда думал, заключался в следующем: контракты / конечные точки и, в основном, ответ JSON моих API постоянно обновляются. Как я могу написать модульные тесты, которые принимают это во внимание?
Чтобы уточнить это: скажем, для модели требуется ключ / поле с именем username
. Вы проверяете это, и ваш тест проходит. Через 2 недели сервер меняет название ключа на id
. Ваши тесты все еще проходят. правильно? или нет?
Это ответственность бэкэнд-разработчика за обновление макетов. Должно ли быть частью нашего соглашения, что они предоставляют обновленные макеты?
Ответ на вышеуказанный вопрос заключается в следующем: модульные тесты + ваш процесс разработки в качестве разработчика на стороне клиента должен / будет отлавливать устаревшие смоделированные ответы. Если вы спросите меня, как? хорошо ответ:
Наше реальное приложение не будет работать (или не потерпит неудачу, пока не будет иметь желаемого поведения) без использования обновленных API-интерфейсов ... следовательно, если это не удастся ... мы внесем изменения в наш код разработки. Что снова приводит к провалу наших тестов ... которые мы должны будем исправить. (На самом деле, если мы хотим правильно выполнить процесс TDD, мы не должны писать какой-либо код для поля, пока мы не напишем тест для него ... и увидим, что он не пройден, а затем перейдем к написанию фактического кода разработки для него.)
Все это означает, что бэкэнд не должен говорить: «эй, мы обновили макеты» ... это в конечном итоге происходит через разработку / отладку вашего кода. ّ Потому что это все часть процесса разработки! Хотя, если бэкэнд даст вам надуманный ответ, это будет проще.
Весь мой смысл в этом заключается в том, что (если вы не можете автоматизировать получение обновленного поддельного ответа API), необходимо некоторое человеческое взаимодействие, то есть ручное обновление JSON и проведение коротких собраний, чтобы убедиться, что их значения актуальны, и станут частью вашего процесса
Этот раздел был написан благодаря неспокойной дискуссии в нашей группе по встрече CocoaHead
Только для разработчиков iOS:
Очень хороший пример издевательства - это практическая беседа Наташа Муращева, ориентированная на протокол . Просто перейдите к минуте 18:30, хотя слайды могут не синхронизироваться с реальным видео 🤷♂️
Мне очень нравится эта часть из стенограммы:
Поскольку это тестирование ... мы хотим убедиться, что вызывается
get
функция изGettable
, потому что она может вернуться, и функция может теоретически назначить массив продуктов из любой точки мира . Нам нужно убедиться, что это называется;
Есть много ответов на SO и хорошие посты в Интернете о насмешках. Одним из мест, которое вы можете начать искать, является пост Мартина Фаулера « Насмешки не заглушки», где он обсуждает множество идей насмешки.
В одном абзаце - Mocking - один из конкретных методов, позволяющий тестировать единицу кода без зависимости от зависимостей. В общем, то, что отличает моделирование от других методов, состоит в том, что фиктивные объекты, используемые для замены зависимостей кода, позволят установить ожидания - объект-модель будет знать, как он должен вызываться вашим кодом и как реагировать.
Ваш оригинальный вопрос упоминал TypeMock, поэтому я оставил свой ответ на этот вопрос ниже:
TypeMock - это название коммерческого фреймворк- макета .
Он предлагает все функции бесплатных фреймворков, таких как RhinoMocks и Moq, а также некоторые более мощные опции.
Вопрос о том, нужен ли вам TypeMock, является предметом споров - вы можете делать большинство насмешек, которые вам когда-либо понадобятся, с помощью бесплатных библиотек насмешек, и многие утверждают, что возможности, предлагаемые TypeMock, часто уводят вас от хорошо инкапсулированного дизайна.
В другом ответе говорилось, что «TypeMocking» на самом деле не является определенным понятием, но его можно использовать для обозначения типа имитации, которую предлагает TypeMock, с использованием профилировщика CLR для перехвата вызовов .Net во время выполнения, что дает гораздо большую способность к имитации объектов (не требований). такие как необходимость интерфейсов или виртуальных методов).
Mock - это метод / объект, который имитирует поведение реального метода / объекта контролируемыми способами. Поддельные объекты используются в модульном тестировании.
Часто тестируемый метод вызывает другие внешние службы или методы внутри него. Это так называемые зависимости. После того, как издевались, зависимости ведут себя так, как мы их определили.
С помощью зависимостей, которые контролируются имитациями, мы можем легко протестировать поведение метода, который мы кодировали. Это юнит тестирование.
Целью насмешливых типов является разделение зависимостей, чтобы изолировать тест от конкретного модуля. Заглушки - это простые суррогаты, а насмешки - это суррогаты, которые могут проверить использование. Фреймворк-это инструмент, который поможет вам создавать заглушки и насмешки.
РЕДАКТИРОВАТЬ : С оригинальной формулировкой упоминания "тип издевательства" у меня сложилось впечатление, что это связано с TypeMock. По моему опыту общий термин просто «издевательство». Пожалуйста, не стесняйтесь игнорировать приведенную ниже информацию конкретно о TypeMock.
TypeMock Isolator отличается от большинства других насмешливых фреймворков тем, что он работает с моим изменением IL на лету. Это позволяет имитировать типы и экземпляры, которые большинство других фреймворков не могут имитировать. Чтобы высмеивать эти типы / экземпляры с другими платформами, вы должны предоставить свои собственные абстракции и смоделировать их.
TypeMock предлагает большую гибкость за счет чистой среды выполнения. В качестве побочного эффекта от того, как TypeMock достигает своих результатов, вы иногда получите очень странные результаты при использовании TypeMock.
Я бы подумал, что использование среды моделирования изолятора TypeMock будет TypeMocking.
Это инструмент, который генерирует макеты для использования в модульных тестах, без необходимости писать код с учетом IoC.
Если ваша имитация связана с запросом по сети, другой альтернативой является использование реального тестового сервера. Вы можете использовать этот сервис для генерации запроса и ответа на ваше тестирование. http://testerurl.com/