Использование интерфейсов Soley для облегчения заглушки и насмешек в модульных тестах устарело? - PullRequest
12 голосов
/ 06 октября 2010

В .NET, TypeMock Isolator и Microsoft Moles позволяют изолировать любой класс, свойство или метод - будь то герметичный, статический, защищенный или не виртуальный. То, что было невозможно издеваться в Moq или Rhino Mocks, теперь уже не так.

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

Однако, хотя я не могу говорить за TypeMock Isolator, я могу сказать, что использование Mocks в Microsoft Moles чрезвычайно медленное. Наличие кода, подобного следующему в модульных тестах, делает скорость теста слишком медленной для частого использования:

MFile.ReadAllLinesString = (s) => csvDataCorrectlyFormatted;
MDirectoryInfo.AllInstances.GetFilesString = (di,fi) => fileInfoArray;
MFileInfo.AllInstances.NameGet = (fi) => "Doesn't Matter";

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

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

Мне любопытно, что думает остальная часть сообщества.

ОБНОВЛЕНИЕ 10/06/10: Говоря, что я борюсь с понятием добавления сложности производственного кода ради тестирования, я имею в виду добавление интерфейса (или даже абстрактного класса). ) когда это не нужно, например, когда конкретный класс незапечатан, а методы - виртуальными. Последний по-прежнему позволяет швы для тестирования. Даже если позже обнаружится необходимость использования интерфейса для нескольких реализаций, не могли бы они извлечь его из класса? Но если в этом нет необходимости, почему бы не следовать ЯГНИ .

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

Наконец, я не говорю, что, поскольку Isolator и Moles позволяют обойти ограничения изоляции в средах на основе динамических прокси-серверов, не следует разрабатывать архитектуру, чтобы ее можно было поддерживать. Во многих случаях принципы SOLID - это то, что лучше, и, следовательно, Isolator или Moles не понадобятся. Это случаи, когда интерфейс используется исключительно для тестирования, который я ставлю под сомнение. Я поднимаю еще один аспект скорости. Если кто-то выберет использование Isolator и Moles, он, кажется, приносит штраф скорости. Так что я, конечно, не думаю, что они делают динамические фреймворки на основе прокси устаревшими.

Ответы [ 4 ]

4 голосов
/ 06 октября 2010

Это действительно интересный вопрос, который я иногда слышал при тестировании новичков.На мой взгляд, Moles / Typemock на самом деле не сопоставимы с фальшивыми фреймворками, и они, конечно, не являются заменой.Вот мои главные аргументы в пользу этого:

  • Несмотря на то, что Typemock стоит каждой копейки, он требует значительных начальных затрат на лицензию (~ 800 долларов за место), поэтому некоторые менеджеры не решаются вкладывать эту сумму денег.Moles, с другой стороны, бесплатен, но требует некоторой работы по настройке сборки Moles и поставляется с довольно странным «API», который очень трудно освоить - особенно если вы совершенно новичок в тестировании.
  • Typemock и Moles не являются в строгом смысле «Mocking frameworks» - они являются своего рода профилировщиками, которые используют инструментарий времени исполнения под капотом.Таким образом, они приходят с довольно здоровенным влиянием на производительность.У меня нет конкретных цифр по этому поводу, но по собственному опыту я бы оценил, что инструментальные тесты примерно на 100-400% медленнее (Typemock, кажется, быстрее, чем MS Moles)!С большой тестовой батареей, содержащей тысячи тестов, это само по себе может быть препятствием.
  • Не в последнюю очередь, аргумент убийцы: насмешливая структура заставляет вас не только использовать интерфейсы, , но заставляет васпримените к своему программному обеспечению очень отделенный и обслуживаемый дизайн (в соответствии с SOLID ).- И помните: это не первоначальное написание программного обеспечения, которое в первую очередь учитывает его стоимость, но это обслуживание!- С Typemock или Moles вы в основном можете делать все, что захотите, и это действительно плохая вещь и главный аргумент против разработки с Typemock или Moles.

Вывод:

  • Если вы хотите покрыть проект с коричневыми полями тестами, которые вообще не были написаны с точки зрения тестируемости, то вам нужно использовать один из Typemock или Moles (на мой взгляд, Typemock - лучший выбор).
  • Если вы начинаете новый проект (то есть вы делаете проект с нуля), используйте фальшивый фреймворк (лично мне нравится Moq из-за его простоты) и используйте MS Moles в качестве дополнения квещи, для которых у вас нет интерфейса (например, .NET Framework).

Даже Рой Ошеров, ведущий разработчик Typemock, говорит об этом (надеюсь, у него не будет проблем со своим боссомиз-за этого): Заказчик переключается на MOQ - и я счастлив

Однако есть одно исключение: если вы изучаете разработку через тестирование с нуляможет быть полезно использовать Typemock даже для нового кода.Таким образом, вы можете значительно сгладить кривую обучения TDD ...

Thomas

4 голосов
/ 06 октября 2010

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

Я предпочитаю использовать TDD с обычной средой моделирования на основе Castle Dynamic Proxy.Это все о создании слабосвязанной системы с соответствующим размещением испытательных швов.Эти испытательные швы в будущем могут стать точками расширения.Требования, предъявляемые насмешливыми соображениями, усиливают передовые методы проектирования, заставляя писать более целенаправленные классы.

3 голосов
/ 06 октября 2010

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

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

Как вы можете видеть из этих сообщений Хороший дизайн не субъективен и Дизайн и тестируемость с 2008 по 2010 год это все еще обсуждаемая тема, как вы можете видеть из комментариев.

1 голос
/ 06 октября 2010

Но затем мы вернулись к ситуации, когда добавили сложность производственного кода для возможности модульного тестирования.

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

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

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

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

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

...