Как вы обычно относитесь к разделение вашей кодовой базы и связанных модульных тестов? Я знаю людей, которые создают отдельный проект для модульных тестов, который лично меня сбивает с толку и который трудно поддерживать. С другой стороны, если вы смешиваете код и его тесты в одном проекте, вы получите двоичные файлы, связанные с вашей средой модульного тестирования (будь то NUnit, MbUnit или что-то еще), и ваши собственные двоичные файлы бок о бок.
Это хорошо для отладки, но как только я создаю версия выпуска, я действительно больше не хочу, чтобы мой код был ссылка на фреймворк модульного тестирования.
Одно решение, которое я нашел, - заключить все ваши модульные тесты в директивы #if DEBUG - #endif: когда код не ссылается на сборку модульного тестирования, компилятор достаточно умен, чтобы опустить ссылку в скомпилированном коде.
Есть ли другие (возможно, более удобные) варианты достижения подобной цели?





Я определенно рекомендую выделить ваши тесты в отдельный проект. На мой взгляд, это единственный выход.
Да, как говорит Гэри, он также заставляет вас тестировать поведение с помощью общедоступных методов, а не играть с внутренностями ваших классов.
Я бы также порекомендовал другую структуру папок. ProjName \ Code \ SubPackage и ProjName \ Tests \ SubPackage.
Что делать, если вам нужен whitebox-тест?
Вы можете использовать атрибут [InternalsVisibleTo], чтобы ваш тестовый проект мог просматривать внутренние методы.
Я всегда храню свои модульные тесты в отдельном проекте, поэтому он компилируется в свою собственную сборку.
Для каждого проекта существует соответствующий тестовый проект, содержащий тесты.
Например. для сборки с именем, скажем, «Acme.BillingSystem.Utils», должна быть тестовая сборка с именем «Acme.BillingSystem.Utils.Test».
Исключите ее из поставляемой версии продукта, не отправляя эту dll.
Я бы порекомендовал отдельный проект для модульных тестов (и еще больше проектов для интеграционных тестов, функциональных тестов и т. д.). Я пробовал смешивать код и тесты в одном проекте и обнаружил, что его гораздо труднее поддерживать, чем разделять их на отдельные проекты.
Поддержание параллельных пространств имен и использование разумного соглашения об именах для тестов (например, MyClass и MyClassTest) поможет вам сохранить кодовую базу поддерживаемой.
Инфраструктура .Net после версии 2 имеет полезную функцию, позволяющую пометить сборку атрибутом InternalsVisibleTo, который позволяет другой сборке получить доступ к ней. Этакая сборочная функция туннелирования.
Как отмечают другие, отдельный тестовый проект (для каждого нормального проекта) - хороший способ сделать это. Обычно я зеркалирую пространства имен и создаю тестовый класс для каждого нормального класса с добавлением «test» к имени. Это поддерживается непосредственно в IDE, если у вас есть Visual Studio Team System, которая может автоматически создавать тестовые классы и методы в другом проекте.
Одна вещь, которую следует запомнить, если вы хотите протестировать классы и методы с «внутренним» аксессором, - это добавить следующую строку в файл AssemblyInfo.cs для каждого проекта, который нужно протестировать:
[assembly: InternalsVisibleTo("UnitTestProjectName")]
Спасибо также! Это значит, что мы можем перестать публиковать информацию ради ура тестов! : D
Если вы присваиваете своим сборкам строгое имя (как и следовало бы), вам также необходимо добавить в объявление длинную строку открытого ключа. Примечание: строгое именование не является защитой от сторонней связи с внутренними компонентами, поскольку к ним по-прежнему можно получить доступ через отражение.
Я определенно согласен со всеми, что вы должны отделить тесты от своего производственного кода. Однако, если вы настаиваете на этом, вам следует определить условную константу компиляции под названием TEST и обернуть все ваши классы модульного тестирования с помощью
#if TEST
#endif
сначала, чтобы убедиться, что тестовый код не компилируется в производственном сценарии. Как только это будет сделано, вы сможете либо исключить тестовые библиотеки DLL из своего производственного развертывания, либо, что еще лучше (но с более высоким уровнем обслуживания), создать NAnt или MSBuild для производства, который компилируется без ссылок на тестовые библиотеки DLL.
Пока ваши тесты находятся в отдельном проекте, тесты могут ссылаться на кодовую базу, но кодовая база никогда не должна ссылаться на тесты. Я должен спросить, что сбивает с толку в сопровождении двух проектов? Вы можете оставить их в одном решении для организации.
Сложность, конечно, возникает, когда у бизнеса в решении 55 проектов и 60% из них тестовые. Считай, что тебе повезло.
Я всегда создаю отдельный проект Acme.Stuff.Test, который компилируется отдельно.
Обратный аргумент: почему вы хотите сдать тесты? Почему бы не сдать тест? Если вы доставляете тесты вместе с исполнителем тестов, у вас есть некоторый уровень приемочного тестирования и самотестирования, поставляемых вместе с продуктом.
Я слышал этот аргумент несколько раз и думал об этом, но лично я все еще веду тесты в отдельном проекте.
Я поместил тесты в отдельный проект, но в том же решении. Конечно, в больших решениях может быть много проектов, но обозреватель решений достаточно хорош для их разделения, и если вы дадите всему разумные имена, я не думаю, что это проблема.
Еще одна альтернатива использованию директив компилятора в файле или созданию отдельного проекта - это просто создание дополнительных файлов .cs в вашем проекте.
С помощью магии в самом файле проекта вы можете продиктовать следующее:
Пример отрывка из .csproj:
<Project DefaultTargets = "Build" xmlns = "http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion = "3.5">
...
<Reference Include = "nunit.framework" Condition = " '$(Configuration)'=='Debug' ">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\debug\nunit.framework.dll</HintPath>
</Reference>
...
<Compile Include = "Test\ClassTest.cs" Condition = " '$(Configuration)'=='Debug' " />
...
</Project>
Еще предстоит принять во внимание одну вещь: в версиях VisualStudio до 2005 года нельзя было ссылаться на проекты сборки EXE из других проектов. Итак, если вы работаете над унаследованным проектом в VS.NET, ваши варианты будут следующими:
Из трех условная компиляция наименее подвержена ошибкам.
Если тег #if (ОТЛАДКА) допускает чистую «релизную» версию, зачем вам нужен отдельный проект для тестов. Пример nunit LibarryA / B (да, я знаю его пример) делает это. В настоящее время борюсь со сценарием. Использовал отдельный проект, но, похоже, это, возможно, позволит улучшить производительность. По-прежнему хуммин и хавин.
Это также заставляет вас тестировать поведение с помощью общедоступных методов, а не возиться с внутренностями ваших классов. Двойной бонус имо.