Рекомендации PHPUnit по организации тестов


В настоящее время я собираюсь начать с нуля с тестов phpunit для проекта. Поэтому я изучал некоторые проекты (например, Zend), чтобы посмотреть, как они работают и как они организуют свои тесты.

Большинство вещей довольно ясны, единственное, с чем у меня есть некоторые проблемы, - это как правильно организовать наборы тестов. У Зенда есть AllTests.php из которого загружаются другие наборы тестов.
Сложно взглянуть на класс, который он использует PHPUnit_Framework_TestSuite для создания объекта suite, а затем добавить другой подходит для этого, но если я посмотрю в документах PHPUnit для организации тестов в версиях PHPUnit после 3.4, там есть только описание для XML или файловой иерархии. Тот, который использовал классы для организации тестов, был удален.
Я не нашел ничего, что указывало бы на то, что этот метод устарел, и такие проекты, как Zend, все еще используют его.

Но если он устарел, как я смогу организовать тесты в той же структуре с конфигурацией xml? Выполнение всех тестов не проблема, но как бы я организовал тесты (в xml), если бы я хотел выполнить только несколько тестов. Может быть, создать несколько XML-файлов, в которых я укажу только несколько тестов/наборов тестов для запуска?

Поэтому, если бы я хотел протестировать только module1 и module2 приложения, у меня был бы дополнительный xml для каждого и определяющий наборы тестов только для тех модулей (классов, используемых модулем) в нем. А также тот, который определяет набор тестов для всех тестов?

Или было бы лучше использовать аннотацию @group для конкретных тестов, чтобы отметить они должны быть для module1 или module2?

Заранее спасибо, что указали мне на некоторые лучшие практики.

 59
Author: Prof. Falken, 2011-11-29

2 answers

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

Организация наборов тестов phpunit

Организация папок модуля/теста в файловой системе

Мой рекомендуемый подход заключается в объединении файловой системы с конфигурацией xml.

tests/
 \ unit/
 | - module1
 | - module2
 - integration/
 - functional/

С помощью phpunit.xml с помощью простого:

<testsuites>
  <testsuite name="My whole project">
    <directory>tests</directory>
  </testsuite>
</testsuites>

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

Запуск phpunit затем выполнит ВСЕ тесты и запуск phpunit tests/unit/module1 запустит все тесты module1.

Организация папки "единица измерения"

Наиболее распространенный подход здесь заключается в том, чтобы отразить вашу структуру каталогов source/ в вашей структуре папок tests/unit/.

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

В организации файлов

  • По одному классу на файл.

Это все равно не сработает, если у вас будет более одного теста класс в одном файле, так что избегайте этой ловушки.

  • У вас нет тестового пространства имен

Это просто делает написание теста более подробным, так как вам нужна дополнительная инструкция use, поэтому я бы сказал, что тестовый класс должен находиться в том же пространстве имен, что и производственный класс, но PHPUnit ничего не заставляет вас делать. Я просто обнаружил, что это проще, без каких-либо недостатков.

Выполнение всего нескольких тестов

Напримерphpunit --filter Factory выполняет все заводские тесты, в то время как phpunit tests/unit/logger/ выполняет все связанные с ведением журнала.

Вы можете использовать теги @group для чего-то вроде номеров выпусков, историй или чего-то еще, но для "модулей" я бы использовал макет папки.

Несколько XML-файлов

Может быть полезно создать несколько XML-файлов, если вы хотите иметь:

  • один без покрытия кода
  • один только для модульных тестов (но не для функциональных, интеграционных или длительных тестов)
  • другие распространенные случаи "фильтрации"
  • Например, PHPBB3 делает это для their phpunit.xmls

Покрытие кода для ваших тестов

Как это связано с запуском нового проекта с тестами:

  • Я предлагаю использовать теги @covers , как описано в моем блоге (Только для модульных тестов, всегда охватывайте все непубличные функции, всегда используйте теги обложек.
  • Не создавайте покрытие для своих интеграционных тестов. Это дает вам ложное чувство безопасности.
  • Всегда используйте белый список, чтобы включить все ваши производственный код, чтобы цифры не лгали вам!

Автоматическая загрузка и начальная загрузка ваших тестов

Вам не нужна какая-либо автоматическая загрузка для ваших тестов. PHPUnit позаботится об этом.

Используйте атрибут <phpunit bootstrap="file">, чтобы указать начальную загрузку теста. tests/bootstrap.php хорошее место для этого. Там вы можете настроить автозагрузчик приложений и так далее (или, если на то пошло, назвать свои приложения начальной загрузкой).

Краткое описание

  • Используйте конфигурацию xml для почти всего
  • Отдельные модульные и интеграционные тесты
  • Папки модульных тестов должны отражать структуру папок приложений
  • Для выполнения только определенных тестов используйте phpunit --filter или phpunit tests/unit/module1
  • Используйте strict режим с самого начала и никогда не выключайте его.

Примеры проектов для просмотра

 97
Author: edorian, 2014-05-08 09:33:22

Базовая структура Каталогов:

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

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

Одним из недостатков является то, что это затрудняет выпуск вашего производственного кода без сопровождающих его тестов. Хотя, если вы используете строгое именование условности это все еще может быть возможно. Например, я использовал ClassName.php, ClassNameUnitTest.php, и ClassNameIntegrationTest.php . Когда я хочу запустить все модульные тесты, есть набор, который ищет файлы, заканчивающиеся на UnitTest.php . Набор интеграционных тестов работает аналогично. Если бы я захотел, я мог бы использовать аналогичную технику, чтобы предотвратить выпуск тестов в производство.

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

Один тестовый класс на класс:

Это далеко не экспериментально для большинства программистов, но для меня это так. Я экспериментирую только с одним тестовым классом на каждый тестируемый класс. В прошлом у меня был целый каталог для каждого тестируемого класса, а затем у меня было несколько классов внутри этого каталога. Каждый тестовый класс настраивает тестируемый класс определенным образом, а затем у каждого из них есть несколько методов с другим утверждением. Но затем я начал замечать, что определенные условия, в которые я помещал эти объекты, имели нечто общее с другими условиями, в которые они попадали из других тестовых классов. С дублированием стало слишком сложно справиться, поэтому я начал создавать абстракции, чтобы удалить его. Тестовый код стал очень сложным для понимания и поддержки. Я понимал это, но не видел альтернативы, которая имела бы для меня смысл. Просто имея один тестовый класс на класс, казалось, что он не сможет протестировать почти достаточно ситуаций, не становящихся непреодолимыми, чтобы иметь весь этот тестовый код внутри одного тестового класса. Теперь у меня другой взгляд на это. Даже если бы я был прав, это огромное препятствие для других программистов и для меня, желающих писать и поддерживать тесты. Теперь я экспериментирую с тем, чтобы заставить себя проводить по одному тестовому классу на каждый тестируемый класс. Если я столкнусь со слишком многими вещами для тестирования в этом одном тестовом классе, я экспериментирую, рассматривая это как признак того, что класс тестирование делает слишком много, и его следует разбить на несколько классов. Для устранения дублирования я стараюсь придерживаться как можно более простых абстракций, которые позволяют всему существовать в одном читаемом тестовом классе.

 0
Author: still_dreaming_1, 2017-03-24 22:44:06