Где должны жить юнит-тесты? - PullRequest
20 голосов
/ 04 августа 2010

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

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

Есть ли приличный способ организации модульных тестов, чтобы вы могли легко автоматизировать процесс сборки и при этом получать доступ ко всему, что нужно тестировать?

РЕДАКТИРОВАТЬ: Для тех, кто интересуется конкретным языком, я в основном работаю на Java. Тем не менее, я хотел бы найти решение, относительно независимое от языка, чтобы я мог применить его независимо от того, на какой платформе я работаю.

Ответы [ 6 ]

5 голосов
/ 04 августа 2010

Вы не указываете платформу и инструменты, которые вы используете, и это влияет на параметры. Я отвечаю с точки зрения .NET и Visual Studio:

Моя команда (работающая над довольно крупным проектом) успешно использовала подход размещения кода и тестов вместе . Для данного (под) пространства имен в решении есть папка "_Test" внутри этого (под) пространства имен ("_" - взлом, чтобы Visual Studio отобразил его над всем остальным в этом пространство имен в браузере решений).

Я представлял TDD в команде и чувствовал, что минимальное трение при переходе между тестами и кодом имеет решающее значение для успеха в освоении практики. Следовательно, тесты всегда "физически близки" к коду, который он тестирует; Вы не хотите искать и продвигаться вперед в огромном решении для перехода между кодом и тестами.

Что имеет смысл, когда вы думаете об этом. Код и тест принадлежат друг другу как Инь и Ян. Это также означает, что при изменении типов в 1 сборке необходимо перестроить только 1 сборку (в нашем решении более 30 проектов, поэтому это позволяет нам безопасно обходиться без Build Current Project только при развитии класса через TDD, way быстрее, чем полная сборка решения).

Совместное использование кода и тестов также решает проблему тестирования внутренних классов. Однако на платформе .NET вы также можете использовать атрибут уровня сборки InternalsVisibleTo, чтобы предоставить доступ к отдельной тестовой сборке, если вы хотите сохранить отдельные элементы.

Единственная причина, по которой я вижу тесты в отдельной сборке, - это не отправлять этот код. Однако этот аспект тривиально решается по-другому, если вы используете автоматизацию сборки. Поскольку файлы проекта Visual Studio представляют собой XML, у нас просто есть сервер сборки, который предварительно обрабатывает файлы проекта, используя небольшой XSLT, для удаления всех данных в папке * / _ Test / * из компиляции в сборках выпуска.

5 голосов
/ 04 августа 2010

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

4 голосов
/ 04 августа 2010

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

Вы всегда можете фильтровать классы на основе некоторых соглашений об именах, таких как специальный суффикс или префикс при упаковке (например, не включайте **/*Test.class с Java). Мне не очень нравится такой подход, я нахожу его грязным и хрупким.

для второго, как бы вы протестировали функциональность, которая видна только на уровне пакета?

Если я что-то упустил, я не вижу проблемы. Вы МОЖЕТЕ иметь классы в том же пакете , и они могут жить в разных деревьях , например ::

  • src/main/java для источников приложений
    • src/main/java/foo/Bar.java
  • src/test/java для тестовых источников
    • src/test/java/foo/BarTest.java

И Bar.java, и BarTest.java находятся в одном пакете foo, но в разных каталогах. Этот подход я использую.

Есть ли приличный способ организации модульных тестов, чтобы вы могли легко автоматизировать процесс сборки и при этом получать доступ ко всему, что нужно проверить?

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

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

1 голос
/ 26 ноября 2014

Что такое тест, а что такое приложение?

Давайте подумаем о том, как тест вписывается в картину ...

  • Тест не имеет прямого отношения ко всему, о чем беспокоится публика - он просто хочет, чтобы он работал
  • Тест для разработчиков и, как правило, для бизнеса
  • Тесты могут быть в том же масштабе, что и модули, но в дихотомическом расположении
  • Если тестовые файлы могут существовать рядом с его модулем в заданной инкапсулирующей структуре, то логически - в фрактальной архитектуре - часть теста также должна быть распределена в масштаб объекта в данном модуле. (Подумайте, directory | _file | _module | _object - где system == component && component == system && (system == system || system == subsystem ))

Последний из них должен показать, что тесты по своей сути дискретны от модулей и логически не дополняют друг друга в каждом масштабе. Чтобы действительно это понять, я призываю вас изучить fractals & self -симметрия , Теория типов и Теория категорий .

Тем не менее, специфика приложения может кардинально изменить имеющиеся у вас опции ...

Исходя из перспективы JavaScript, независимой и даже с использованием продвинутой архитектурной схемы - кажется, что включение ваших тестов в /src может усложнить процесс сборки. Более того, вы создаете менее читабельное с логической привязкой для других разработчиков, когда в вашем каталоге src есть несколько, гораздо меньше тестов. Вы действительно хотите защитить и инкапсулировать своих тестов, приватизируя их для членов вашей команды, а не для того, чтобы кто-либо публично взаимодействовал с вашим приложением.

Тем не менее, возможно, стоит пойти по этому пути на основе специфики приложения - ЕСЛИ - вы можете убедиться, что оно безопасно и не создает ненужных сложностей, или душить автоматизацию .

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

Как правило, используйте стандартные строительные леса:

/app
    |-lib
    |-src
    |-test

.. вы, вероятно, не можете пойти не так с этим.

1 голос
/ 04 августа 2010

Вероятно, это зависит от того, что вы сейчас используете.С Visual Studio / .net обычная практика - это тестирование dll для каждой производственной dll и расплывчатое отражение классов и тестовых классов внутри dll.Для ruby ​​/ python и т. Д. - отдельный каталог тестов и внутри этой иерархии, которая отражает тестируемые объекты.

Что вы подразумеваете под «извлечением» этих тестов?Для вас полная сборка предполагает компиляцию и запуск тестов или нет?

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

1 голос
/ 04 августа 2010

Я предлагаю вам иметь отдельный проект (или проекты) для ваших юнит-тестов.

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

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

...