Вы ставите юнит-тесты в том же проекте или другом проекте? - PullRequest
129 голосов
/ 07 декабря 2008

Вы помещаете модульные тесты в один и тот же проект для удобства или вы помещаете их в отдельную сборку?

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

Ответы [ 12 ]

104 голосов
/ 07 декабря 2008

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

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

Если вам нужен доступ к внутренним элементам производственного кода, используйте InternalsVisibleTo .

91 голосов
/ 07 декабря 2008

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

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

Я действительно не знаю ни одного профи. Наличие дополнительного проекта (или 10) не является мошенничеством.

Редактировать: Подробнее о сборке и доставке

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

Подводя итог, вот общая идея ежедневной сборки, тестирования и доставки битов и других файлов:

  1. Производственная сборка запускается, помещая производственные файлы в определенный «производственный» каталог.
    1. Создание только производственных проектов.
    2. Скопируйте скомпилированные биты и другие файлы в каталог «production».
    3. Скопируйте биты и другие файлы в каталог-кандидат на выпуск, иначе каталог рождественских релизов будет "Release20081225".
  2. Если сборка завершается успешно, выполняется сборка модульного теста.
    1. Скопируйте производственный код в каталог «tests».
    2. Сборка юнит-тестов в каталоге "tests".
    3. Запуск юнит-тестов.
  3. Отправка уведомлений о сборке и результатов модульных тестов разработчикам.
  4. Когда кандидат на выпуск (например, Release20081225) принят, отправьте эти биты.
65 голосов
/ 17 февраля 2009

Я не понимаю частых возражений против развертывания тестов с рабочим кодом. Я руководил командой на небольшом микрокапсе (вырос с 14 до 130 человек). У нас было около полудюжины или около того Java-приложений, и мы обнаружили, что КРАЙНЕ ЦЕННО развертывать тесты в полевых условиях для их выполнения на конкретной машине, которая демонстрирует необычное поведение. Случайные проблемы возникают в полевых условиях, и возможность провести несколько тысяч юнит-тестов в тайне с нулевой стоимостью была неоценима и часто выявляла проблемы за считанные минуты ... включая проблемы с установкой, проблемы с оперативной памятью, проблемы с конкретными машинами, проблемы с сетевыми сетями и т. д. и т. д. Я думаю, что это невероятно ценно - проводить испытания в полевых условиях. Кроме того, случайные проблемы возникают в случайное время, и было бы хорошо, если бы модульные тесты уже находились там, ожидая их выполнения в любой момент. Место на жестком диске дешево. Точно так же, как мы пытаемся объединить данные и функции (разработка ОО), я думаю, что есть нечто фундаментально ценное в том, чтобы хранить код и тесты вместе (функция + тесты, которые проверяют функции).

Я хотел бы поместить свои тесты в тот же проект в C # / .NET / Visual Studio 2008, но я до сих пор не исследовал это достаточно для его достижения.

Одно большое преимущество хранения Foo.cs в том же проекте, что и FooTest.cs, заключается в том, что разработчикам постоянно напоминают, что в классе отсутствует тест для одного брата! Это поощряет лучшие методы кодирования, основанные на тестировании ... дыры более очевидны.

13 голосов
/ 23 июня 2011

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

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

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

И вы можете удалить модульные тесты из производственного кода, используя теги компиляции (IF #Debug).

Автоматические интеграционные тесты (сделанные в NUnit) должны быть в отдельном проекте, поскольку они не принадлежат ни одному проекту.

10 голосов
/ 07 декабря 2008

Мои юнит-тесты всегда идут в отдельном проекте. Фактически, для каждого проекта, который я имею в своем решении, есть отдельный тестовый проект, который сопровождает его. Тестовый код не является кодом приложения и не должен смешиваться с ним. Одно из преимуществ сохранения их в отдельных проектах - по крайней мере, с помощью TestDriven.Net - заключается в том, что я могу щелкнуть правой кнопкой мыши на тестовом проекте и запустить все тесты в этом проекте, тестируя всю библиотеку кода приложения одним щелчком мыши.

8 голосов
/ 01 августа 2014

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

public static class Ext
{
     [TestCase(1.1, Result = 1)]
     [TestCase(0.9, Result = 1)]
     public static int ToRoundedInt(this double d)
     {
         return (int) Math.Round(d);
     }
}

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

Обновление : я знаю, что такое использование атрибута TestCase не было тем, что разработчики NUnit намеревались, но почему бы и нет?

3 голосов
/ 07 декабря 2008

Я положил их в отдельных проектах. Название сборки отражает имя пространства имен, как общее правило для нас. Поэтому, если существует проект с именем Company.Product.Feature.sln, он имеет выход (имя сборки) Company.Product.Feature.dll. Тестовый проект - Company.Product.Feature.Tests.sln, уступающий Company.Product.Feature.Tests.dll.

Лучше всего хранить их в одном решении и контролировать вывод через Configuration Manager. У нас есть именованная конфигурация для каждой из основных ветвей (разработка, интеграция, производство) вместо использования отладки и выпуска по умолчанию. После того, как вы настроили свои конфигурации, вы можете включить или исключить их, установив флажок «Сборка» в Configuration Manager. (Чтобы получить Configuration Manager, щелкните правой кнопкой мыши решение и перейдите в Configuration Manager.) Обратите внимание, что иногда я обнаруживаю, что CM в Visual Studio содержит ошибки. Пару раз мне приходилось заходить в файлы проекта и / или решения, чтобы очистить созданные им цели.

Кроме того, если вы используете Team Build (и я уверен, что другие инструменты сборки .NET такие же), вы можете связать сборку с именованной конфигурацией. Это означает, что, например, если вы не собираете свои модульные тесты для вашей сборки «Production», проект сборки может знать об этом параметре и не собирать их, поскольку они были помечены как таковые.

Кроме того, мы использовали XCopy для сборки машины. Скрипт просто не будет копировать что-либо с именем * .Tests.Dll из развернутого. Это было просто, но сработало.

3 голосов
/ 07 декабря 2008

Я колеблюсь между одним и тем же проектом и разными проектами.

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

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

1 голос
/ 27 сентября 2012

Я бы сказал, держите их отдельно.

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

0 голосов
/ 21 мая 2018

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

Почему?

Во-первых, я очень стараюсь сохранить структуру папок основного проекта в тестовом проекте. Итак, если у меня есть файл в Providers > DataProvider > SqlDataProvider.cs, я создаю такую ​​же структуру в моих проектах модульного тестирования, как Providers > DataProvider > SqlDataProvider.Tests.cs

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

Во-вторых, не всегда очень легко перейти от класса, подлежащего тестированию, к классу модульного тестирования. Это еще сложнее для JavaScript и Python.

Недавно я начал практиковать, что каждый созданный мной файл (например, SqlDataProvider.cs) я создаю другой файл с суффиксом теста, например SqlDataProvider.Tests.cs

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

Вы даже можете написать бизнес-правила для сканирования по проекту, определить класс, у которого нет файла .Tests, и сообщить о них владельцу. Кроме того, вы можете легко рассказать своему тестируемому о цели .Tests классах.

Специально для Js и Python вам не нужно импортировать ссылки с другого пути, вы можете просто использовать тот же путь тестируемого целевого файла.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...