На мой взгляд, модульные тесты следует размещать в отдельной сборке от производственного кода. Вот лишь несколько минусов размещения модульных тестов в той же сборке или сборках, что и производственный код:
- Модульные тесты поставляются с производственным кодом. Единственное, что поставляется с кодом продукта, - это производственный код.
- Сборки будут излишне раздуты из-за модульных тестов.
- Модульные тесты могут влиять на процессы сборки, такие как автоматическая или непрерывная сборка.
Я действительно не знаю никаких плюсов. Наличие лишнего проекта (или 10) не является недостатком.
Изменить: дополнительная информация о сборке и доставке
Я бы также рекомендовал, чтобы любой автоматизированный процесс сборки размещал производственные и модульные тесты в разных местах. В идеале процесс сборки модульного теста запускается только в случае сборки производственного кода и копирует файлы продукта в каталог модульных тестов. Это приводит к тому, что фактические биты разделяются для доставки и т. Д. Кроме того, довольно просто запустить автоматическое модульное тестирование на этом этапе для всех тестов в определенном каталоге.
Подводя итог, вот общая идея ежедневной сборки, тестирования и доставки битов и других файлов:
- Производственная сборка запускается, производственные файлы помещаются в определенный «производственный» каталог.
- Только сборка производственных проектов.
- Скопируйте скомпилированные биты и другие файлы в "производственный" каталог.
- Скопируйте биты и другие файлы в каталог кандидатов на выпуск, также известный как каталог рождественских выпусков, который будет «Release20081225».
- Если производственная сборка завершается успешно, запускается сборка модульного теста.
- Скопируйте производственный код в каталог "tests".
- Сборка модульных тестов в каталог "tests".
- Запустите модульные тесты.
- Отправляйте разработчикам уведомления о сборках и результаты модульных тестов.
- Когда релиз-кандидат (например, Release20081225) принят, отправьте эти биты.
#if
. Этот настраиваемый символ можно переключать с помощью параметров командной строки компилятора в сценариях программного обеспечения CI. См. Msdn.microsoft.com/en-us/library/4y6tbswk.aspx .Отдельный проект, но в одном решении. (Я работал над продуктами с отдельными решениями для тестового и производственного кода - это ужасно. Вы всегда переключаетесь между ними.)
Причины для отдельных проектов указаны другими. Обратите внимание, что если вы используете тесты, управляемые данными, вы можете столкнуться с довольно значительным раздуванием, если включите тесты в производственную сборку.
Если вам нужен доступ к внутренним членам производственного кода, используйте InternalsVisibleTo .
источник
[assembly:InternalsVisibleTo("UnitTestProjectName")]
в свой проектAssemblyInfo.cs
.Я не понимаю частых возражений против развертывания тестов с производственным кодом. Возглавлял команду на небольшом микрокапитале (выросла с 14 до 130 человек). У нас было около полдюжины Java-приложений, и мы нашли ЧРЕЗВЫЧАЙНО полезным развернуть тесты в полевых условиях, чтобы выполнить их на определенноммашина, которая проявляла необычное поведение. Случайные проблемы возникают в полевых условиях, и возможность провести несколько тысяч модульных тестов с нулевыми затратами была бесценной и часто диагностировала проблемы за считанные минуты ... включая проблемы с установкой, нестабильные проблемы с ОЗУ, проблемы, связанные с машиной, нестабильные сетевые проблемы, и т. д. и т. д. Я считаю невероятно ценно проводить тесты в полевых условиях. Кроме того, случайные проблемы возникают в случайное время, и приятно, когда модульные тесты уже ждут выполнения в любой момент. Место на жестком диске дешевое. Точно так же, как мы пытаемся объединить данные и функции (объектно-ориентированный дизайн), я думаю, что есть что-то принципиально ценное в хранении кода и тестов вместе (функция + тесты, которые проверяют функции).
Я хотел бы провести свои тесты в том же проекте на C # /. NET / Visual Studio 2008, но я еще не изучил этого достаточно, чтобы достичь этого.
Одним из больших преимуществ хранения Foo.cs в том же проекте, что и FooTest.cs, является то, что разработчикам постоянно напоминают, когда в классе отсутствует тест-аналог! Это способствует более совершенным методам кодирования, основанным на тестировании ... дыры более очевидны.
источник
Поместите модульные тесты в тот же проект, что и код, чтобы добиться лучшей инкапсуляции.
Вы можете легко протестировать внутренние методы, а это значит, что вы не будете делать общедоступными методы, которые должны были быть внутренними.
Также приятно иметь модульные тесты, близкие к написанному вами коду. Когда вы пишете метод, вы можете легко найти соответствующие модульные тесты, потому что они находятся в том же проекте. Когда вы создаете сборку, которая включает unitTests, любые ошибки в unitTest выдадут вам ошибку compilereerror, поэтому вы должны поддерживать свой unittest в актуальном состоянии только для сборки. Наличие unittest в отдельном проекте может привести к тому, что некоторые разработчики забудут собрать проект unittest и на какое-то время пропустят неработающие тесты.
И вы можете удалить модульные тесты из производственного кода, используя теги компиляции (IF #Debug).
Тесты автоматической интеграции (сделанные в NUnit) должны быть в отдельном проекте, поскольку они не принадлежат ни одному проекту.
источник
Release
сборке, и некоторые «heisenbugs» могут провалиться.InternalsVisibleTo
позволяет вам тестировать внутренние методы из отдельного тестового проектаDebug
,Approval
иRelease
; и согласование компиляции со всеми оптимизациями выпуска. Кроме того, как правило, модульные тесты не очень хороши для обнаружения heisenbug (по моему опыту). Для них вам, как правило, требуются специальные интеграционные регрессионные тесты - и вы вполне можете разместить их рядом.Проведя некоторое время в проектах TypeScript, где тесты часто помещаются в файл вместе с кодом, который они тестируют, я предпочел этот подход разделению:
Поэтому, когда я недавно начал новый проект .NET Core, я хотел посмотреть, можно ли имитировать эту структуру в проекте C # без отправки тестов или тестовых сборок с окончательной версией.
Добавление следующих строк в файл проекта пока работает хорошо:
<ItemGroup Condition="'$(Configuration)' == 'Release'"> <Compile Remove="**\*.Tests.cs" /> </ItemGroup> <ItemGroup Condition="'$(Configuration)' != 'Release'"> <PackageReference Include="nunit" Version="3.11.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.12.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> </ItemGroup>
Вышеупомянутое гарантирует, что в
Release
конфигурации все указанные файлы*.Tests.cs
исключены из компиляции, а также что необходимые ссылки на пакеты модульного тестирования удалены.Если вы все еще хотите иметь возможность модульного тестирования классов в их конфигурации выпуска, вы можете просто создать новую конфигурацию, производную от
Release
чего-то вродеReleaseContainingTests
.Обновление: после использования этой техники в течение некоторого времени я также обнаружил, что полезно настроить ваши значки в VS Code, чтобы тесты (и другие вещи) немного выделялись на панели проводника:
Для этого используйте расширение Material Icon Theme и добавьте в настройки JSON VS Code что-то вроде следующего:
"material-icon-theme.files.associations": { "*.Tests.cs": "test-jsx", "*.Mocks.cs": "merlin", "*.Interface.cs": "yaml", }
источник
Мои модульные тесты всегда идут в отдельный проект. Фактически, для каждого проекта, который есть в моем решении, есть отдельный тестовый проект, который сопровождает его. Код тестирования не является кодом приложения и не должен смешиваться с ним. Одним из преимуществ их хранения в отдельных проектах - по крайней мере, с использованием TestDriven.Net - является то, что я могу щелкнуть правой кнопкой мыши тестовый проект и запустить все тесты в этом проекте, тестируя всю библиотеку кода приложения одним щелчком мыши.
источник
Если используется фреймворк 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, но почему бы и нет?источник
Я колеблюсь между одним и тем же проектом и разными проектами.
Если вы выпускаете библиотеку, выпуск тестового кода с производственным кодом представляет собой проблему, в противном случае я считаю, что это обычно не так (хотя есть сильный психологический барьер, прежде чем вы попробуете).
Помещая тесты в один и тот же проект, мне легче переключаться между тестами и кодом, который они тестируют, и легче реорганизовывать / перемещать их.
источник
Я помещаю их в отдельные проекты. Имя сборки отражает имя пространств имен, как правило для нас. Итак, если есть проект под названием Company.Product.Feature.sln, он имеет выход (имя сборки) Company.Product.Feature.dll. Тестовый проект - Company.Product.Feature.Tests.sln, в результате чего получается Company.Product.Feature.Tests.dll.
Лучше всего хранить их в одном решении и контролировать вывод через Configuration Manager. У нас есть именованная конфигурация для каждой из основных веток (Разработка, Интеграция, Производство) вместо использования отладки и выпуска по умолчанию. После настройки конфигураций вы можете включить или исключить их, установив флажок «Сборка» в диспетчере конфигураций. (Чтобы получить Configuration Manager, щелкните решение правой кнопкой мыши и перейдите в Configuration Manager.) Обратите внимание, что я считаю, что CM в Visual Studio иногда содержит ошибки. Пару раз мне приходилось заходить в файлы проекта и / или решения, чтобы очистить созданные им цели.
Кроме того, если вы используете Team Build (и я уверен, что другие инструменты сборки .NET такие же), вы можете связать сборку с именованной конфигурацией. Это означает, что если вы, например, не создаете свои модульные тесты для «производственной» сборки, проект сборки также может знать об этом параметре и не создавать их, поскольку они были отмечены как таковые.
Кроме того, мы использовали XCopy для удаления с машины сборки. Сценарий просто не будет копировать что-либо с именем * .Tests.Dll из развертывания. Это было просто, но работало.
источник
Я бы сказал, держите их отдельно.
Помимо других упомянутых причин, наличие кода и тестов вместе искажает числа тестового покрытия. Когда вы сообщаете о покрытии модульными тестами - сообщаемое покрытие выше, потому что тесты покрываются при запуске модульных тестов. Когда вы сообщаете о покрытии интеграционными тестами, сообщаемое покрытие ниже, потому что интеграционные тесты не запускают модульные тесты.
источник
Я действительно вдохновлен фреймворком модульного тестирования библиотеки Flood NN Роберта Лопеса. Он использует другой проект для каждого отдельного тестируемого класса и имеет одно решение, содержащее все эти проекты, а также основной проект, который компилирует и запускает все тесты.
Изящной вещью является еще и верстка проекта. Исходные файлы находятся в папке, но папка для проекта VS находится ниже. Это позволяет создавать разные подпапки для разных компиляторов. Все проекты VS поставляются с кодом, поэтому любой желающий может легко запустить любой или все модульные тесты.
источник
Я знаю, что это очень старый вопрос, но я хотел бы добавить туда свой опыт. Я недавно изменил привычку модульного тестирования с отдельных проектов на один и тот же.
Зачем?
Во-первых, я очень стараюсь сохранить структуру папок основного проекта такой же, как и в тестовом проекте. Итак, если у меня есть файл,
Providers > DataProvider > SqlDataProvider.cs
я создаю такую же структуру в своих проектах модульного тестирования, напримерProviders > DataProvider > SqlDataProvider.Tests.cs
Но после того, как проект становится все больше и больше, как только вы перемещаете файлы из одной папки в другую или из одного проекта в другой, синхронизация их с проектами модульного тестирования становится очень громоздкой.
Во-вторых, не всегда легко перейти от класса для тестирования к классу модульного тестирования. Это еще сложнее для JavaScript и Python.
Недавно я начал практиковать, что каждый созданный мной файл (например
SqlDataProvider.cs
) я создаю другой файл с суффиксом Test, напримерSqlDataProvider.Tests.cs
Вначале кажется, что файлы и ссылки на библиотеки будут раздуваться, но в долгосрочной перспективе вы избавитесь от синдрома перемещения файлов на первый взгляд, а также убедитесь, что каждый файл, который является кандидатом на тестирование, будет иметь парный файл. с
.Tests
суффиксом. Это позволяет легко перейти в тестовый файл (потому что он находится рядом) вместо просмотра отдельного проекта.Вы даже можете написать бизнес-правила для сканирования проекта и определения класса, у которого нет файла .Tests, и сообщить о них владельцу. Также вы можете легко указать своему тест-раннеру целевые
.Tests
классы.Специально для Js и Python вам не нужно будет импортировать ссылки с разных путей, вы можете просто использовать тот же путь к тестируемому целевому файлу.
Я использую эту практику некоторое время и считаю, что это очень разумный компромисс между размером проекта, удобством обслуживания и кривой обучения для новичков в проекте.
источник
Как ответили другие - ставьте тесты в отдельные проекты
Одна вещь, о которой не упоминалось, - это то, что вы не можете работать
nunit3-console.exe
ни с чем, кроме.dll
файлов.Если вы планируете запускать тесты через TeamCity, это создаст проблему.
Допустим, у вас есть проект консольного приложения. При компиляции он возвращает исполняемый файл
.exe
вbin
папку.Из этого
nunit3-console.exe
вы не сможете запускать какие-либо тесты, определенные в этом консольном приложении.Другими словами, консольное приложение возвращает
exe
файл, а библиотека классов возвращаетdll
файлы.Меня это только что укусило сегодня, и это отстой :(
источник
Недавно я разворачивался в докере. Я не вижу смысла иметь отдельный проект, когда Dockerfile может легко скопировать каталог / src и покинуть каталог / test. Но я новичок в dotnet и, возможно, что-то упускаю.
источник
Отдельные проекты, хотя я спорю сам с собой, должны ли они использовать один и тот же файл svn. На данный момент я даю им отдельные репозитории svn, один из которых называется
«MyProject» - для самого проекта
и один позвонил
«MyProjectTests» - для тестов, связанных с MyProject.
Это довольно чисто и имеет то преимущество, что фиксация в проекте и фиксация в тестах совершенно независимы. Это также означает, что вы можете передать svn проекта, если это необходимо, без необходимости выпускать тесты. Это также означает, что у вас могут быть каталоги веток / транков / тегов для ваших тестов и для вашего проекта.
Но я все больше склоняюсь к тому, чтобы в одном репозитории svn для каждого проекта было что-то вроде следующего.
Мне было бы интересно узнать, что другие люди думают об этом решении.
источник