Модульные тесты MVC 5 против интеграционных тестов

В настоящее время я работаю над проектом MVC 5, используя Entity Framework 5 (скоро я могу переключиться на 6). Сначала я использую базу данных и MySQL с существующей базой данных (около 40 таблиц). Этот проект начинался как «проверка концепции», и теперь моя компания решила использовать программное обеспечение, которое я разрабатываю. Я борюсь с тестовой частью.

Моей первой идеей было использовать в основном интеграционные тесты. Таким образом, я почувствовал, что могу протестировать свой код, а также базовую базу данных. Я создал скрипт, который выгружает существующую схему базы данных в «тестовую базу данных» в MySQL. Я всегда начинаю свои тесты с чистой базы данных без данных и создаю/удаляю немного данных для каждого теста. Дело в том, что я запускаю свои тесты довольно долго (я запускаю свои тесты очень часто).

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

  1. Как вы думаете, может ли имитация моей базы данных «скрыть» ошибки, которые могут возникнуть только тогда, когда мой код работает с реальной базой данных? Обратите внимание, что я не хочу тестировать Entity Framework (я уверен, что замечательные люди из Microsoft отлично с этим справились), но сможет ли мой код хорошо работать против фиктивных и взломов MySQL?
  2. Считаете ли вы, что переход от интеграционного тестирования к модульному тестированию — это король «понижения»?
  3. Считаете ли вы, что отказаться от интеграционного тестирования и принять модульное тестирование из соображений скорости — это нормально?
  4. Я знаю, что существует некоторая структура, которая запускает тесты для базы данных в памяти (например, среда Effort), но я не вижу преимуществ этого перед насмешкой, что я упускаю?

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

В качестве побочного вопроса, какой инструмент вы бы порекомендовали для насмешек. Мне сказали, что «moq» — хороший фреймворк, но немного медленный. Как вы думаете?


person Pierre    schedule 01.07.2015    source источник
comment
Модульные тесты предназначены для тестирования кода, который вы написали, интеграционные тесты предназначены для тестирования взаимодействия с тем, что написали другие. Вы не должны исключать интеграционные тесты, но они не должны быть тестами, которые вы запускаете каждые 10 минут.   -  person Claies    schedule 02.07.2015
comment
как правило, хорошее разделение проблем и внедрение зависимостей позволит вам протестировать почти каждую функцию в вашем приложении, как если бы это было все приложение само по себе. Если ваша функция полагается на результат какой-либо другой функции/службы/библиотеки, чтобы дать правильный ответ, то, скорее всего, она недостаточно реорганизована.   -  person Claies    schedule 02.07.2015


Ответы (1)


  1. Как вы думаете, может ли имитация моей базы данных «скрыть» ошибки, которые могут возникнуть только тогда, когда мой код работает с реальной базой данных? Обратите внимание, что я не хочу тестировать Entity Framework (я уверен, что замечательные люди из Microsoft отлично с этим справились), но сможет ли мой код хорошо работать против фиктивных и взломов MySQL?

Да, если вы тестируете свой код только с помощью Mocks, вам очень легко получить ложную уверенность в своем коде. Когда вы издеваетесь над базой данных, вы говорите: «Я ожидаю, что эти вызовы будут иметь место». Если ваш код делает такие вызовы, он пройдет тест, но если это неправильные вызовы, он не будет работать в рабочей среде. На простом уровне, если вы добавляете/удаляете столбец из своей базы данных, взаимодействие с базой данных может измениться, но процесс добавления/удаления столбца скрыт от ваших тестов, пока вы не обновите макеты.

  1. Считаете ли вы, что переход от интеграционного тестирования к модульному тестированию — это король «понижения»?

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

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

Хорошо, это очень субъективно. Я бы сказал нет, однако вам не нужно запускать все тесты все все время. Большинство сред тестирования (если не все) позволяют вам тем или иным образом классифицировать ваши тесты. Это позволяет вам создавать подмножества ваших тестов, так что вы можете, например, иметь категорию «DatabaseIntegration», в которую вы помещаете все свои тесты интеграции с базой данных, или «EndToEnd» для полных сквозных тестов. Мой предпочтительный подход - иметь отдельные сборки. Обычная/непрерывная сборка, которую я запускаю до/после каждой регистрации, запускает только модульные тесты. Это дает быструю обратную связь и подтверждение того, что ничего не сломалось. Менее распространенная / ежедневная / ночная сборка, в дополнение к запуску модульных тестов, также будет выполнять более медленные / повторяющиеся интеграционные тесты. Я бы также предпочел запустить интеграционные тесты для областей, над которыми я работал, прежде чем проверять код, если есть вероятность того, что код повлияет на интеграцию.

  1. Я знаю, что существует какой-то фреймворк, который запускает тесты для базы данных в памяти (например, фреймворк Effort), но я не вижу преимуществ этого по сравнению с имитацией, что я упускаю?

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

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

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

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

В качестве побочного вопроса, какой инструмент вы бы порекомендовали для насмешек. Мне сказали, что «moq» — хороший фреймворк, но немного медленный. Как вы думаете?

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

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

Два фреймворка, которые я использовал, немного отличаются друг от друга: подделки/прокладки MS и Typemock. Версия MS требует определенного уровня визуальной студии, но позволяет создавать поддельные сборки с прокладками определенных типов объектов, что означает, что вам не нужно передавать свои макеты из теста туда, где они используются. Typemock — это коммерческое решение, которое использует API профилирования для внедрения кода во время выполнения ваших тестов, что означает, что оно может достигать тех частей, которые не могут другие фреймворки. Они оба особенно полезны, если у вас есть кодовая база, которая не была написана с учетом модульного тестирования, которое может помочь преодолеть разрыв.

person forsvarir    schedule 02.07.2015