Модульное тестирование кода проекта веб-сайта ASP.net, хранящегося в App_Code

У меня есть проект веб-сайта ASP.net (.net 3.5). В настоящее время все файлы кода, не связанные с кодом (включая материал Linq2Sql, контексты данных, бизнес-логику, методы расширения и т. Д.), Находятся в папке App_Code.

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

  • Это будет невозможно, учитывая мою текущую настройку
  • Модульное тестирование требует ссылки на классы, которые являются частью скомпилированной библиотеки DLL, а проект веб-сайта по определению компилируется только во время выполнения.
  • Чтобы продолжить, мне нужно будет либо преобразовать весь мой проект в веб-приложение, либо переместить весь код, который я хотел бы протестировать (т.е. все содержимое App_Code), в проект библиотеки классов и сослаться на библиотеку классов. проект в проекте веб-сайта. Любой из них предоставит доступ к нужным мне классам в формате скомпилированной dll, что позволит мне провести их модульное тестирование.

Это правильно? Или есть другой способ выполнить модульное тестирование без реструктуризации / рефакторинга всего моего проекта?


person Yaakov Ellis    schedule 29.07.2009    source источник


Ответы (8)


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

person Fredrik Mörk    schedule 29.07.2009

Мой магазин наконец-то нашел ответ на этот вопрос для нашего проекта MVC. И я хочу поделиться этим, поскольку я гнался за множеством тупиков здесь, в StackOverflow, слыша, как многие люди говорят, что это невозможно. Делаем это так:

  • Откройте папку MVC «как веб-сайт, из локального iis», который обеспечивает правильную работу intellisense и отладки.
  • Добавьте проект модульного теста, который находится в нашем каталоге с исходным кодом.
  • Добавьте этап предварительной сборки в проект TEST, поскольку мы не можем добавить его в проект, открытый как веб-сайт. Представьте, что веб-сайт - это \ FooSite, а наш тестовый проект - это \ FooSite.Tests. Скомпилированный код приложения окажется в FooSite.Tests \ FooSite_Precompiled \ bin.
  • *
<Target Name="BeforeBuild">
     <AspNetCompiler VirtualPath="FooSite" TargetPath="$(ProjectDir)\FooSite_Precompiled" Force="true"
 Debug="true" />   </Target>
  • Добавьте ссылку на FooSite_Precompiled / bin / App_Code.dll в свой тестовый проект.
  • Бум, вот и все. Вы можете съесть свой торт и съесть его. Каждый раз, когда вы нажимаете Build в своем решении, вы вызываете инструмент aspnet_compiler.ext на своем веб-сайте csproj (который все еще существует), который может, в отличие от MSBuild, компилировать app_code, а Debug = "true" позволяет вам перейти в app_code. dll при отладке модульного теста. И вам нужно только построить, когда вы запускаете обновленные модульные тесты. Когда вы смотрите на эффекты вашего изменения на странице, вы просто меняете код / ​​сохраняете / обновляете страницу, поскольку папка app_code динамически компилируется при вызове с вашего веб-сервера.
person Brian White    schedule 30.04.2012
comment
Это должен быть принятый ответ. Я добавлю, что запуск AspNetCompiler при сборке тестового проекта довольно медленный, поэтому я использую задачу Exec для запуска сборки только из файлов App_Code. - person Ian Newson; 05.07.2012
comment
Как именно вы это настроили? Задача exec для вызова определенной команды msbuild? Не могли бы вы привести пример? - person Brian White; 06.11.2012
comment
Мы используем проприетарный инструмент, который вызывается с задачей Exec, но это должно быть возможно либо путем прямого вызова CSC, либо с помощью отдельного файла проекта, который включает каждый исходный файл в папке App_Code. Забавно, что вы должны спросить об этом сейчас, так как я недавно столкнулся с проблемой с этой системой в Visual Studio 2012. Я опубликовал вопрос, чтобы узнать, может ли кто-нибудь помочь решить эту проблему, и включил пример проекта с аналогичной настройкой для тот, который я использую: stackoverflow.com/questions/13138820/ - person Ian Newson; 06.11.2012
comment
Просто хотел вернуться к этому и сказать, что мы удалили весь app_code, кроме глобальных помощников html, которые должны там запускаться. Этот подход был болезненным из-за отдельных решений, разработчикам не хватало даже того, чтобы тестовый проект существовал. - person Brian White; 18.01.2017

У нас есть эта проблема в моей компании (моему начальнику не нравятся библиотеки DLL, какая-то чушь про управление версиями ...)

У нас есть два способа обойти это, которые мы часто используем:

1) Получите инструмент CI для выполнения модульного тестирования: мы используем TeamCity, который имеет довольно тесную интеграцию с NUnit, и наше решение создается достаточно быстро (и имеет достаточно тестов), чтобы это было допустимым вариантом.

2) Выполните предварительную компиляцию и модульное тестирование полученных двоичных файлов вручную: вполне возможно запустить компилятор ASP.net / MSBuild из командной строки (как если бы вы выполняли сборку «Опубликовать») и просто выполнить модульное тестирование полученных двоичных файлов.

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

person Ed James    schedule 21.06.2010
comment
Версии dll до .Net были кошмаром. Я считаю, что это прозвали адом dll. С .Net это больше не проблема. - person TheLukeMcCarthy; 28.11.2011

Если кто-то обнаружит, что внедряет решение Брайана, вот файл Website.targets, который вы можете включить в решение для модульного тестирования. Он (повторно) компилирует веб-сайт только при изменении App_Code. Просто добавьте что-нибудь вроде

  <PropertyGroup>
    <WebsiteName>MyWebsite</WebsiteName>
    <WebsitePath>..</WebsitePath>
  </PropertyGroup>
  <Import Project="$(ProjectDir)\Website.targets" />
  <Target Name="BeforeBuild" DependsOnTargets="CompileWebsite">
  </Target>

в ваш .csproj, настроив WebsiteName и WebsitePath, и вы должны быть готовы к работе. Website.targets:

<?xml version="1.0" encoding="utf-8"?>
<!--
    Target that compiles Website's App_Code to be used for testing
  -->
<Project DefaultTargets="CompileWebsite" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <AppCodeFiles Include="$(WebsitePath)\$(WebsiteName)\App_Code\**\*.*" />
  </ItemGroup>
  <Target Name="CompileWebsite" Inputs="@(AppCodeFiles)" Outputs="$(ProjectDir)\PrecompiledWeb\bin\App_Code.dll">
    <AspNetCompiler VirtualPath="$(WebsiteName)" PhysicalPath="$(WebsitePath)\$(WebsiteName)" TargetPath="$(ProjectDir)\PrecompiledWeb" Force="true" Debug="true" />
  </Target>
  <Target Name="CleanWebsite">
    <RemoveDir Directories="$(WebsitePath)\$(WebsiteName)\PrecompiledWeb" />
  </Target>  
</Project>
person blazee    schedule 04.06.2013
comment
Это отлично сработало для меня, единственное, что я хотел бы добавить, это то, что если вы хотите, чтобы все было построено в сборке TFS, я то, что я делаю, это проверяю сгенерированную DLL, и поскольку я не хочу проверять весь PrecompiledWeb папку, я копирую ее в отдельную папку в процессе сборки: ‹PropertyGroup› ‹PreBuildEvent› копия $ (ProjectDir) \ PrecompiledWeb \ bin \ App_SubCode_CSCode.dll $ (ProjectDir) \ Library \ App_SubCode_CSCode.dll ‹/PreBuildEvent› ‹ / PropertyGroup › - person David Rogers; 20.04.2018

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

Я всегда создаю свои собственные проекты ASP.NET как проекты веб-приложений, а не как сайты.

person RichardOD    schedule 29.07.2009
comment
Спасибо за ссылку. Определенно выглядит уродливым решением. - person Yaakov Ellis; 29.07.2009
comment
Да, безусловно, поэтому лучше пойти по одному из наиболее разумных маршрутов. - person RichardOD; 29.07.2009

И, как указано в OP, также можно перейти в проект веб-приложения, который, я бы сказал, тоже чище, ваши страницы могут оставаться в проекте приложения wep, у вас они будут в 1 DLL (тестируемой). Вся ваша бизнес-логика и т. Д. Находится в отдельной библиотеке / библиотеках классов.

person Colin    schedule 29.07.2009
comment
Хотя это знание полезно, я не думаю, что это хороший ответ, потому что в вопросе указано, что OP знает, как это сделать. Кроме того, я считаю, что этот вопрос адресован людям, которые это уже знают. - person Jared Beach; 31.05.2016

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

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

Теперь, когда вы ссылаетесь на проект своего веб-сайта из проекта модульного теста, классы в папке app_code будут видны.

ЗАМЕТКА:

Установка Build Action в Compile файлов .cs приведет к тому, что ваш веб-сайт будет генерировать файл .dll при отладке и модульном тестировании. Файл .dll вызовет проблемы при отладке веб-сайта, потому что теперь IIS найдет ваш код в двух местах, в корзине и в папке App_Code, и не будет знать, какое из них использовать. В настоящее время я просто удаляю файл .dll, когда хочу отладить.

person Jared Beach    schedule 26.05.2016
comment
Я не понимаю, почему мой ответ был отклонен. ОП ошибся, полагая, что единственный способ провести модульное тестирование - это переместить код в проект библиотеки классов или преобразовать решение в веб-приложение, и мой ответ показывает, как выполнить модульное тестирование, сохранив код в папке app_code. Если мой ответ в плохом формате, я надеюсь, что проголосовавший вниз объяснит, что им в этом не нравится. - person Jared Beach; 31.05.2016

Мне пришлось изменить решение Брайана Уайта, добавив атрибут PhysicalPath. Кроме того, я не использую Default Web Site, и мне пришлось изменить свойство VirtualPath на имя моего веб-сайта.

<Target Name="BeforeBuild">
    <AspNetCompiler VirtualPath="myIISsitename.com" PhysicalPath="$(SolutionDir)MySiteFolder" TargetPath="$(ProjectDir)\MySite_Precompiled" Force="true" Debug="true" />
</Target>

Полученная dll будет по адресу MySite_Precompiled\App_Code.dll

person Jason    schedule 19.07.2016