Вопрос

Когда я впервые познакомился с Mocks, я почувствовал, что основная цель — макетировать объекты, полученные из внешних источников данных.Таким образом, мне не нужно было поддерживать базу данных автоматизированного модульного тестирования, я мог просто подделать ее.

Но теперь я начинаю думать об этом по-другому.Мне интересно, являются ли Mocks более эффективным средством полной изоляции тестируемого метода от чего-либо за его пределами.Изображение, которое постоянно приходит на ум, — это фон, который вы используете при рисовании.Вы хотите, чтобы краска не попала на все.Я только тестирую этот метод и хочу только знать, как он реагирует на эти надуманные внешние факторы?

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

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

Это было полезно?

Решение

Рекомендую вам взглянуть на статью Мартина Фаулера. Моки — это не заглушки за более авторитетную трактовку Mocks, чем я могу вам дать.

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

Поначалу моки могут показаться утомительными, но они сделают модульное тестирование намного проще и надежнее, как только вы научитесь их использовать.В большинстве языков есть библиотеки Mock, которые делают издевательство относительно тривиальным.Если вы используете Java, я порекомендую мой личный фаворит: ИзиМок.

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

Другие советы

Не идите темным путем, мастер Люк.:) Не издевайтесь над всем.Ты мог бы, но не должен...вот почему.

  • Если вы продолжите тестировать каждый метод по отдельности, вас ждут сюрпризы и работа, когда вы объедините их все вместе. БОЛЬШОЙ ВЗРЫВ.Мы строим объекты так, чтобы они могли работать вместе для решения более серьезной проблемы.Сами по себе они незначительны.Ты необходимо знать, все ли соавторы работают должным образом.
  • Издевается сделать тесты хрупкими путем введения дублирования. Да, я знаю, это звучит тревожно.Для каждого ожидаемого вами макета существует n мест, где существует сигнатура вашего метода.Фактический код и ваши ложные ожидания (в нескольких тестах).Изменить фактический код проще...обновлять все ложные ожидания утомительно.
  • Твой тест теперь доступен для инсайдерской информации о реализации.Таким образом, ваш тест зависит от того, как вы решили реализовать решение...плохой.Тесты должны представлять собой независимую спецификацию, которой можно соответствовать нескольким решениям.У меня должна быть свобода просто нажать «Удалить» блок кода и переопределить без приходится переписывать набор тестов..потому что требования остаются прежними.

В заключение я скажу: «Если оно крякает, как утка, ходит, как утка, то, вероятно, это и есть утка» — Если это кажется неправильным..вероятно, это так.*Используйте макеты, чтобы абстрагировать проблемные дочерние элементы, такие как операции ввода-вывода, базы данных, сторонние компоненты и т. п.Как и соль, немного ее необходимо..слишком много и :х *
Это священная война тестирования на основе состояний и итераций.Гугление даст вам более глубокое понимание.

Уточнение:Я сталкиваюсь с некоторым сопротивлением.интеграционные тесты здесь :) Итак, чтобы прояснить мою позицию..

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

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

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

Что касается сложности, я считаю, что тесты должны быть простыми в написании просто потому, что вы пишете больше тестов, если они таковы.

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

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

Да, это обратная сторона тестирования с использованием макетов.Вам нужно проделать много работы, и это кажется жестоким.Но в этом суть модульного тестирования.Как вы можете тестировать что-то изолированно, если не имитируете внешние ресурсы?

С другой стороны, вы издеваетесь над медленными функциями (такими как базы данных и операции ввода-вывода).Если тесты будут выполняться быстрее, это порадует программистов.Нет ничего более болезненного, чем ожидание очень медленных тестов, выполнение которых занимает более 10 секунд, пока вы пытаетесь реализовать одну функцию.

Если бы каждый разработчик вашего проекта тратил время на написание модульных тестов, то эти 16 слоев (косвенности) не были бы такой уж большой проблемой.Надеюсь, у вас должно быть такое тестовое покрытие с самого начала, верно?:)

Кроме того, не забудьте написать тест функции/интеграции между объектами, работающими совместно.Или же вы можете что-то упустить.Эти тесты не нужно будет запускать часто, но они по-прежнему важны.

С одной стороны, да, макеты предназначены для имитации внешних источников данных, таких как база данных или веб-сервис.Однако в более детальном масштабе, если вы разрабатываете слабосвязанный код, вы можете практически произвольно рисовать линии по всему коду относительно того, что в любой момент может быть «внешней системой».Возьмем проект, над которым я сейчас работаю:

Когда кто-то пытается зарегистрироваться, CheckInUi отправляет CheckInInfo возражать против CheckInMediator объект, который проверяет его с помощью CheckInValidator, то, если все в порядке, он заполняет объект домена с именем Сделка с CheckInInfo с использованием ЧекИнИнфоАдаптер затем передает Сделка к экземпляру ITransactionDao.SaveTransaction() за настойчивость.

Я прямо сейчас пишу несколько автоматизированных интеграционные тесты и, очевидно, CheckInUi и ITransactionDao являются окнами во внешние системы, и именно над ними следует высмеивать.Однако чье слово, что в какой-то момент CheckInValidator не будет звонить в веб-сервис?Вот почему, когда вы пишете модульные тесты вы предполагаете, что все, кроме конкретной функциональности вашего класса, является внешней системой.Поэтому в моем модульном тесте CheckInMediator Я издеваюсь над всеми объектами, с которыми он разговаривает.

РЕДАКТИРОВАТЬ: Гишу технически прав, не надо все издеваться, я например не издеваюсь CheckInInfo поскольку это просто контейнер для данных.Однако все, что вы когда-либо могли рассматривать как внешний сервис (а это почти все, что преобразует данные или имеет побочные эффекты), должно быть высмеяно.

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

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

Действительно найдите время, чтобы выучить это как следует, день, когда я понял Mocks, был огромным моментом ага.Объедините это с инверсией контейнера управления, и я никогда не вернусь.

Кстати, один из наших ИТ-специалистов только что пришел и подарил мне бесплатный ноутбук!

Как кто-то сказал ранее, если вы имитируете все, чтобы изолировать более детально, чем класс, который вы тестируете, вы отказываетесь от обеспечения связности в тестируемом коде.

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

Моки были изобретены частично для того, чтобы Ответ на вопрос:Как бы вы относились к объектам модульного тестирования, если бы у них не было геттеров или сеттеров?

В эти дни, рекомендуемые практика состоит в том, чтобы высмеивать роли, а не объекты.Используйте Mocks как инструмент проектирования, чтобы говорить о совместной работе и разделении обязанностей, а не как «умные заглушки».

Мок-объекты 1) часто используются как средство изоляции тестируемого кода, НО 2), как уже указывал Кейтб, важны для "сосредоточить внимание на отношениях между взаимодействующими объектами".В этой статье приводятся некоторые сведения и история, связанные с этой темой: Ответственный дизайн с использованием макетов объектов.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top