Вы добавляете модульные тесты в один проект или другой проект?

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

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

Ответ 1

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

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

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

Изменить: Дополнительная информация о сборке и доставке

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

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

  • Выполняется сборка сборки, помещая производственные файлы в определенный "производственный" каталог.
    • Создавайте только производственные проекты.
    • Скопируйте скомпилированные биты и другие файлы в каталог "production".
    • Копирование битов и других файлов в каталог-кандидат на выпуск, который является каталогом рождественских выпусков, будет "Release20081225".
  • Если производственная сборка завершается успешно, unit test выполняется сборка.
    • Скопируйте производственный код в каталог "tests".
    • Постройте модульные тесты в каталог "tests".
    • Пробные тесты.
  • Отправлять уведомления о сборке и результаты модульных тестов разработчикам.
  • Когда кандидат на выпуск (например, Release20081225) принимается, отправляйте эти биты.

Ответ 2

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

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

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

Ответ 3

Я не понимаю частое возражение против развертывания тестов с производственным кодом. Я привел команду на небольшой микрокап (вырос с 14 до 130 человек). У нас было полдюжины или около того Java-приложений, и мы убедились, что EXTREMELY value можно развернуть тесты в поле для их выполнения на конкретной машине, которая демонстрирует необычное поведение. Случайные проблемы возникают в поле, и возможность опрокидывания нескольких тысяч тестов в тайне с нулевыми затратами неоценима и часто диагностируется проблемы в минутах... включая проблемы с установкой, проблемы с помехоустойчивостью ОЗУ, проблемы, связанные с машиной, проблемы с плохой сетью, и т.д. и т.д. Я считаю, что невероятно ценно проводить тесты в поле. Кроме того, случайные проблемы появляются в произвольные моменты времени, и хорошо, что силовые тесты, которые сидят там, уже ждут, чтобы их можно было выполнить в момент уведомления. Место на жестком диске дешево. Точно так же, как мы пытаемся сохранить данные и функции вместе (дизайн OO), я думаю, что есть что-то принципиально ценное в сохранении кода и тестов вместе (функция + тесты, которые проверяют функции).

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

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

Ответ 4

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

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

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

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

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

Ответ 5

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

Ответ 6

Если используется 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 задумали, но почему бы и нет?

Ответ 7

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

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

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

Ответ 8

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

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

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

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

Ответ 9

Проведя некоторое время в проектах TypeScript, где тесты часто помещаются в файл вместе с кодом, который они тестируют, я стал предпочитать этот подход, а не разделять их:

  • Перейти к тестовому файлу быстрее.
  • Проще помнить, что нужно переименовывать тесты, когда вы переименовываете тестируемый класс.
  • При перемещении тестируемого класса легче запомнить перемещение.
  • Сразу видно, что в классе отсутствуют тесты.
  • Вам не нужно управлять двумя дублирующимися файловыми структурами, одна для тестов, а другая для кода.

Поэтому, когда я недавно запустил новый проект .NET Core, я хотел узнать, можно ли имитировать эту структуру в проекте С# без отправки тестов или сборок с окончательным выпуском.

Кажется, что размещение следующих строк в файле проекта работает хорошо:

  <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, чтобы тесты (и другие вещи) выделялись на панели обозревателя немного больше:

VS Code Screenshot

Для этого воспользуйтесь расширением Theme Icon Icon и добавьте что-то вроде следующего в ваши настройки VS Code JSON:

"material-icon-theme.files.associations": {
  "*.Tests.cs": "test-jsx",
  "*.Mocks.cs": "merlin",
  "*.Interface.cs": "yaml",
}

Ответ 10

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

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

Ответ 11

Я действительно вдохновлен рамкой модульного тестирования Flood NN library от Роберта Лопеса. Он использует другой проект для каждого тестируемого класса, и имеет одно решение, содержащее все эти проекты, а также основной проект, который компилирует и запускает все тесты.

Оптимальная вещь - также макет проекта. Исходные файлы находятся в папке, но затем папка для проекта VS ниже. Это позволяет создавать разные подпапки для разных компиляторов. Все проекты VS поставляются вместе с кодом, поэтому для любого пользователя или всех модульных тестов очень легко.

Ответ 12

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

Зачем?

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

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

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

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

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

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

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

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

Ответ 13

Раздельные проекты, хотя я спорю с самим собой, должны ли они делиться одним и тем же svn. На данный момент я предоставляю им отдельные репозитории svn, один из которых называется

"MyProject" - для самого проекта

и один, называемый

"MyProjectTests" - для тестов, связанных с MyProject.

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

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

MyProject
|\Trunk
| |\Code
|  \Tests
|\Tags
| |\0.1
| | |\Code
| |  \Tests
|  \0.2
|   |\Code
|    \Tests
\Branches
  \MyFork
   |\Code
    \Test

Мне было бы интересно узнать, что другие люди думают об этом решении.