C # - исключение модульных тестов из релизной версии вашего проекта.

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

Это нормально для отладки, но как только я создам окончательную версию, я действительно не хочу, чтобы мой код больше ссылался на структуру модульного тестирования.

Я нашел одно решение - заключить все ваши модульные тесты в директивы #if DEBUG - #endif: когда код не ссылается на сборку модульного тестирования, компилятор достаточно умен, чтобы опустить ссылку в скомпилированном коде.

Есть ли другие (возможно, более удобные) варианты достижения подобной цели?


person petr k.    schedule 17.09.2008    source источник


Ответы (13)


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

Да, как говорит Гэри, это также заставляет вас проверять поведение общедоступными методами, а не играть с внутренностями ваши классы

person Galwegian    schedule 17.09.2008
comment
Это также заставляет вас тестировать поведение с помощью общедоступных методов, а не возиться с внутренностями ваших классов. Двойной бонус имо. - person Garry Shutler; 17.09.2008
comment
Я бы также порекомендовал другую структуру папок. ProjName \ Code \ SubPackage и ProjName \ Tests \ SubPackage. - person Gishu; 17.09.2008
comment
Что делать, если вам нужен whitebox-тест? - person Roman Plášil; 02.07.2010
comment
Вы можете использовать атрибут [InternalsVisibleTo], чтобы ваш тестовый проект мог просматривать внутренние методы. - person Joel in Gö; 15.02.2011

Как отмечают другие, отдельный тестовый проект (для каждого нормального проекта) - хороший способ сделать это. Я обычно зеркалирую пространства имен и создаю тестовый класс для каждого нормального класса с добавлением «test» к имени. Это поддерживается непосредственно в IDE, если у вас есть Visual Studio Team System, которая может автоматически создавать тестовые классы и методы в другом проекте.

Одна вещь, которую следует запомнить, если вы хотите протестировать классы и методы с «внутренним» аксессором, - это добавить следующую строку в файл AssemblyInfo.cs для каждого проекта, который нужно протестировать:

[assembly: InternalsVisibleTo("UnitTestProjectName")]
person Morten Christiansen    schedule 17.09.2008
comment
Спасибо также! Это значит, что мы можем перестать публиковать информацию ради ура тестов! : D - person Sam Wessel; 23.09.2008
comment
Если вы присваиваете своим сборкам строгое имя (как и следовало бы), вам также необходимо добавить в объявление длинную строку открытого ключа. Примечание. Строгие имена не являются защитой от сторонних ссылок на внутренние компоненты, поскольку к ним по-прежнему можно получить доступ через отражение. - person Steve Gilham; 12.08.2009

В .Net framework после v2 есть полезная функция, в которой вы можете пометить сборку атрибутом InternalsVisibleTo, который позволяет другой сборке получить доступ к ней.
Что-то вроде функции туннелирования сборок.

person Rikalous    schedule 17.09.2008

Еще одна альтернатива использованию директив компилятора в файле или созданию отдельного проекта - это просто создание дополнительных файлов .cs в вашем проекте.

С помощью магии в самом файле проекта вы можете продиктовать это:

  1. Библиотеки DLL nunit.framework упоминаются только в отладочной сборке, и
  2. ваши тестовые файлы включены только в отладочные сборки

Пример отрывка из .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>
person user21114    schedule 23.09.2008

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

Поддержание параллельных пространств имен и использование разумного соглашения об именах для тестов (например, MyClass и MyClassTest) поможет вам сохранить кодовую базу поддерживаемой.

person Rasmus Faber    schedule 17.09.2008

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

Сложность, конечно, возникает, когда у бизнеса в решении 55 проектов и 60% из них тестовые. Считай, что тебе повезло.

person tsilb    schedule 17.09.2008

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

person Niklas Winde    schedule 17.09.2008

Для каждого проекта существует соответствующий тестовый проект, содержащий тесты.

Например. для сборки с именем, скажем, «Acme.BillingSystem.Utils», будет тестовая сборка с именем «Acme.BillingSystem.Utils.Test».

Исключите ее из поставляемой версии продукта, не отправляя эту dll.

person Anthony    schedule 17.09.2008

Еще предстоит принять во внимание одну вещь: в версиях VisualStudio до 2005 года нельзя было ссылаться на проекты сборки EXE из других проектов. Итак, если вы работаете над унаследованным проектом в VS.NET, ваши варианты будут следующими:

  • Поместите модульные тесты в один и тот же проект и используйте условную компиляцию, чтобы исключить их из сборок выпуска.
  • Переместите все в сборки dll, чтобы ваш exe был просто точкой входа.
  • Обойти IDE, взломав файл проекта в текстовом редакторе.

Из трех условная компиляция наименее подвержена ошибкам.

person Kenneth Cochran    schedule 13.04.2009

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

person Chris Canal    schedule 17.09.2008

Если тег #if (DEBUG) допускает чистую «релизную» версию, зачем вам нужен отдельный проект для тестов. Пример nunit LibarryA / B (да, я знаю его пример) делает это. В настоящее время борюсь со сценарием. Использовал отдельный проект, но, похоже, это, возможно, позволит улучшить производительность. По-прежнему хуммин и хавин.

person mbowles    schedule 08.07.2009

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

#if TEST
#endif

сначала, чтобы убедиться, что тестовый код не компилируется в производственном сценарии. Как только это будет сделано, вы сможете либо исключить тестовые библиотеки DLL из своего производственного развертывания, либо, что еще лучше (но с более высоким уровнем обслуживания), создать NAnt или MSBuild для производства, который компилируется без ссылок на тестовые библиотеки DLL.

person Michael Meadows    schedule 17.09.2008

Я всегда создаю отдельный проект Acme.Stuff.Test, который компилируется отдельно.

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

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

person Hamish Smith    schedule 17.09.2008