Библиотека Composer с дополнительными атрибутами для улучшения тестирования с помощью PHPUnit.
композитору требуется --dev eliashaeussler/phpunit-attributes
Библиотека поставляется с готовым к использованию расширением PHPUnit. Он должен быть зарегистрирован в вашем файле конфигурации PHPUnit:
<?xml версия="1.0" кодировка="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php" >+ <extensions>+ <bootstrap class="EliasHaeusslerPHPUnitAttributesPHPUnitAttributesExtension" />+ </extensions> <testsuites> <testsuite name="unit"> <каталог>тесты</каталог> </testsuite> </testsuites> <источник> <включить> <каталог>источник</каталог> </включить> </источник> </phpunit>
Некоторые атрибуты можно настроить с помощью пользовательских параметров расширения. Их необходимо добавить в раздел регистрации расширений следующим образом:
<extensions>- <bootstrap class="EliasHaeusslerPHPUnitAttributesPHPUnitAttributesExtension" />+ <bootstrap class="EliasHaeusslerPHPUnitAttributesPHPUnitAttributesExtension">+ <parameter name="fancyParameterName" value="fancyParameterValue" />+ </bootstrap> </extensions>
Следующие атрибуты поставляются с этой библиотекой:
#[RequiresClass]
#[RequiresPackage]
#[RequiresClass]
Область применения: уровень класса и метода
С помощью этого атрибута тесты или тестовые примеры могут быть помечены как выполняемые только в том случае, если существует определенный класс. Данный класс должен быть доступен для загрузки текущим загрузчиком классов (который обычно является загрузчиком классов Composer по умолчанию).
По умолчанию тестовые случаи, требующие несуществующих классов, пропускаются. Однако это поведение можно настроить с помощью параметра расширения handleMissingClasses
. Если установлено значение fail
, тестовые случаи с отсутствующими классами завершится неудачно (по умолчанию skip
):
<расширения> <bootstrap class="EliasHaeusslerPHPUnitAttributesPHPUnitAttributesExtension"> <parameter name="handleMissingClasses" value="fail" /> </бутстрап> </расширения>
последний класс DummyTest расширяет TestCase { #[RequiresClass(AnImportantClass::class)]публичная функция testDummyAction(): void{// ...} }
Уровень класса:
#[RequiresClass(AnImportantClass::class)]финальный класс DummyTest расширяет TestCase {public function testDummyAction(): void{// Пропускается, если AnImportantClass отсутствует.}public function testOtherDummyAction(): void{// Пропускается, если AnImportantClass отсутствует.} }
Уровень метода:
последний класс DummyTest расширяет TestCase { #[RequiresClass(AnImportantClass::class)]public function testDummyAction(): void{// Пропускается, если AnImportantClass отсутствует.}public function testOtherDummyAction(): void{// Не пропускается.} }
Уровень класса:
#[RequiresClass(AnImportantClass::class, 'Для этого теста требуется класс `AnImportantClass`.')]final class DummyTest расширяет TestCase {public function testDummyAction(): void{// Пропускается, если AnImportantClass отсутствует вместе с пользовательским сообщением.}public function testOtherDummyAction(): void{// Пропускается, если AnImportantClass отсутствует вместе с пользовательским сообщением.} }
Уровень метода:
последний класс DummyTest расширяет TestCase { #[RequiresClass(AnImportantClass::class, 'Для этого теста требуется класс `AnImportantClass`.')]public function testDummyAction(): void{// Пропускается, если AnImportantClass отсутствует вместе с пользовательским сообщением.}public function testOtherDummyAction(): void{// Не пропускается.} }
Уровень класса:
#[RequiresClass(AnImportantClass::class, resultBehavior: OutcomeBehavior::Fail)]финальный класс DummyTest расширяет TestCase {public function testDummyAction(): void{// Сбой, если AnImportantClass отсутствует.}public function testOtherDummyAction(): void{// Сбой, если AnImportantClass отсутствует.} }
Уровень метода:
последний класс DummyTest расширяет TestCase { #[RequiresClass(AnImportantClass::class, resultBehavior: OutcomeBehavior::Fail)]public function testDummyAction(): void{// Выполняется неудачно, если AnImportantClass отсутствует.}public function testOtherDummyAction(): void{// Не завершается ошибкой.} }
Уровень класса:
#[RequiresClass(AnImportantClass::class)] #[RequiresClass(AnotherVeryImportantClass::class)]финальный класс DummyTest расширяет TestCase {public function testDummyAction(): void{// Пропускается, если AnImportantClass и/или AnotherVeryImportantClass отсутствуют.}public function testOtherDummyAction(): void{// Пропускается, если AnImportantClass и/или AnotherVeryImportantClass отсутствуют.} }
Уровень метода:
последний класс DummyTest расширяет TestCase { #[RequiresClass(AnImportantClass::class)] #[RequiresClass(AnotherVeryImportantClass::class)]public function testDummyAction(): void{// Пропускается, если AnImportantClass и/или AnotherVeryImportantClass отсутствуют.}public function testOtherDummyAction(): void{// Не пропускается.} }
#[RequiresPackage]
Область применения: уровень класса и метода
Этот атрибут можно использовать для определения конкретных требований к пакету для отдельных тестов, а также для полных классов тестов. Ожидается, что необходимый пакет будет установлен через Composer. При желании вы можете определить ограничение версии и собственное сообщение.
Важный
Атрибут определяет установленные пакеты Composer из созданного во время сборки класса InstalledVersions
созданного Composer. Чтобы правильно читать этот класс, необходимо включить сгенерированный Composer автозагрузчик в ваш загрузочный скрипт PHPUnit:
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php"><! -- ... --></phpunit>
Вы также можете передать скрипт как параметр команды: phpunit --bootstrap vendor/autoload.php
По умолчанию тестовые случаи с неудовлетворенными требованиями пропускаются. Однако это поведение можно настроить с помощью параметра расширения handleUnsatisfiedPackageRequirements
. Если установлено значение fail
, тестовые случаи с неудовлетворенными требованиями завершится неудачно (по умолчанию skip
):
<расширения> <bootstrap class="EliasHaeusslerPHPUnitAttributesPHPUnitAttributesExtension"> <parameter name="handleUnsatisfiedPackageRequirements" value="fail" /> </бутстрап> </расширения>
последний класс DummyTest расширяет TestCase { #[RequiresPackage('symfony/console')]публичная функция testDummyAction(): void{// ...} }
Уровень класса:
#[RequiresPackage('symfony/console')]финальный класс DummyTest расширяет TestCase {public function testDummyAction(): void{// Пропускается, если symfony/console не установлена.}public function testOtherDummyAction(): void{// Пропускается, если symfony/console не установлена.} }
Уровень метода:
последний класс DummyTest расширяет TestCase { #[RequiresPackage('symfony/console')]public function testDummyAction(): void{// Пропускается, если symfony/console не установлена.}public function testOtherDummyAction(): void{// Не пропускается.} }
Уровень класса:
#[RequiresPackage('symfony/*')]финальный класс DummyTest расширяет TestCase {public function testDummyAction(): void{// Пропускается, если не установлены пакеты symfony/*.}public function testOtherDummyAction(): void{// Пропускается, если не установлены пакеты symfony/*.} }
Уровень метода:
последний класс DummyTest расширяет TestCase { #[RequiresPackage('symfony/*')]public function testDummyAction(): void{// Пропускается, если не установлены пакеты symfony/*.}public function testOtherDummyAction(): void{// Не пропускается.} }
Уровень класса:
#[RequiresPackage('symfony/console', '>= 7')]финальный класс DummyTest расширяет TestCase {public function testDummyAction(): void{// Пропускается, если установленная версия symfony/console < 7.}public function testOtherDummyAction(): void{// Пропускается, если установленная версия symfony/console < 7.} }
Уровень метода:
последний класс DummyTest расширяет TestCase { #[RequiresPackage('symfony/console', '>= 7')]public function testDummyAction(): void{// Пропускается, если установленная версия symfony/console < 7.}public function testOtherDummyAction(): void{// Не пропущено.} }
Уровень класса:
#[RequiresPackage('symfony/console', сообщение: 'Для этого теста требуется консоль Symfony.')]финальный класс DummyTest расширяет TestCase {public function testDummyAction(): void{// Пропускается, если symfony/console не установлена вместе с пользовательским сообщением.}public function testOtherDummyAction(): void{// Пропускается, если symfony/console не установлена вместе с пользовательским сообщением. } }
Уровень метода:
последний класс DummyTest расширяет TestCase { #[RequiresPackage('symfony/console', message: 'Для этого теста требуется консоль Symfony.')]public function testDummyAction(): void{// Пропускается, если symfony/console не установлена вместе с пользовательским сообщением.}public function testOtherDummyAction(): void{// Не пропускается.} }
Уровень класса:
#[RequiresPackage('symfony/console', resultBehavior: OutcomeBehavior::Fail)]финальный класс DummyTest расширяет TestCase {public function testDummyAction(): void{// Ошибка, если symfony/console не установлена.}public function testOtherDummyAction(): void{// Ошибка, если symfony/console не установлена.} }
Уровень метода:
последний класс DummyTest расширяет TestCase { #[RequiresPackage('symfony/console', resultBehavior: OutcomeBehavior::Fail)]public function testDummyAction(): void{// Ошибка, если symfony/console не установлена.}public function testOtherDummyAction(): void{// Нет неудача.} }
Уровень класса:
#[RequiresPackage('symfony/console')] #[RequiresPackage('guzzlehttp/guzzle')]финальный класс DummyTest расширяет TestCase {public function testDummyAction(): void{// Пропускается, если symfony/console и/или guzzlehttp/guzzle не установлены.}public function testOtherDummyAction(): void{// Пропускается, если symfony/console и/или guzzlehttp/guzzle не установлены. установлено.} }
Уровень метода:
последний класс DummyTest расширяет TestCase { #[RequiresPackage('symfony/console')] #[RequiresPackage('guzzlehttp/guzzle')]public function testDummyAction(): void{// Пропускается, если symfony/console и/или guzzlehttp/guzzle не установлены.}public function testOtherDummyAction(): void{// Не пропускается. } }
Пожалуйста, посмотрите CONTRIBUTING.md
.
Этот проект распространяется под лицензией GNU General Public License 3.0 (или более поздней версии).