Подтвердить что ты не робот

Являются ли использование интерфейсов Soley для облегчения ступлений и издевательств в модульных тестах теперь устаревшими?

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

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

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Заключение:

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

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

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

Томас

Ответ 3

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

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

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

Ответ 4

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

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

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

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

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

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