Аннотации
Аннотация — это специальная форма синтаксической метаданных, которую можно добавить к исходному коду некоторых языков программирования. Хотя PHP не имеет специальной языковой функции для аннотирования исходного кода, в сообществе PHP используется использование тегов, таких как @annotation arguments, в блоке документации для аннотирования исходного кода. В блоках документации PHP отражаются: к ним можно получить доступ через метод getDocComment() API Reflection на уровне функции, класса, метода и атрибута. Такие приложения, как PHPUnit, используют эту информацию во время выполнения для настройки своего поведения.
Примечание
Блок документации в PHP должен начинаться с /** и заканчиваться */. Аннотации в любом другом стиле комментариев будут проигнорированы.
В этом приложении показаны все разновидности аннотаций, поддерживаемых PHPUnit.
@author
Аннотация @author является псевдонимом для аннотации @group (см. @group) и позволяет фильтровать тесты на основе их авторов.
@after
Аннотация @after может использоваться для указания методов, которые должны вызываться после каждого метода теста в классе теста.
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class MyTest extends TestCase
{
/**
* @after
*/
public function tearDownSomeFixtures(): void
{
// ...
}
/**
* @after
*/
public function tearDownSomeOtherFixtures(): void
{
// ...
}
}
@afterClass
Аннотация @afterClass может использоваться для указания статических методов, которые должны вызываться после выполнения всех методов теста в классе теста для очистки общих фикстур.
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class MyTest extends TestCase
{
/**
* @afterClass
*/
public static function tearDownSomeSharedFixtures(): void
{
// ...
}
/**
* @afterClass
*/
public static function tearDownSomeOtherSharedFixtures(): void
{
// ...
}
}
@backupGlobals
PHPUnit может при необходимости резервировать все глобальные и суперглобальные переменные перед каждым тестом и восстанавливать эту резервную копию после каждого теста.
Аннотация @backupGlobals enabled может использоваться на уровне класса для включения этой операции для всех тестов класса тестового случая:
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
/**
* @backupGlobals enabled
*/
final class MyTest extends TestCase
{
// ...
}
Аннотация @backupGlobals также может использоваться на уровне метода теста. Это позволяет более точно настроить операции резервного копирования и восстановления:
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
/**
* @backupGlobals enabled
*/
final class MyTest extends TestCase
{
public function testThatInteractsWithGlobalVariables()
{
// ...
}
/**
* @backupGlobals disabled
*/
public function testThatDoesNotInteractWithGlobalVariables(): void
{
// ...
}
}
@backupStaticAttributes
PHPUnit может при необходимости резервировать все статические атрибуты во всех объявленных классах перед каждым тестом и восстанавливать эту резервную копию после каждого теста.
Аннотация @backupStaticAttributes enabled может использоваться на уровне класса для включения этой операции для всех тестов класса тестового случая:
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
/**
* @backupStaticAttributes enabled
*/
final class MyTest extends TestCase
{
// ...
}
Аннотация @backupStaticAttributes также может использоваться на уровне метода теста. Это позволяет более точно настроить операции резервного копирования и восстановления:
use PHPUnit\Framework\TestCase;
/**
* @backupStaticAttributes enabled
*/
class MyTest extends TestCase
{
public function testThatInteractsWithStaticAttributes(): void
{
// ...
}
/**
* @backupStaticAttributes disabled
*/
public function testThatDoesNotInteractWithStaticAttributes(): void
{
// ...
}
}
Примечание
@backupStaticAttributes ограничена внутренними возможностями PHP и в некоторых случаях может привести к непреднамеренному сохранению статических значений и утечке их в последующие тесты.
Подробности см. в разделе Глобальное состояние.
@before
Аннотация @before может использоваться для указания методов, которые должны вызываться перед каждым методом теста в классе тестового случая.
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class MyTest extends TestCase
{
/**
* @before
*/
public function setupSomeFixtures(): void
{
// ...
}
/**
* @before
*/
public function setupSomeOtherFixtures(): void
{
// ...
}
}
@beforeClass
Аннотация @beforeClass может использоваться для указания статических методов, которые должны вызываться перед запуском любых методов теста в классе теста для настройки общих фикстур.
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class MyTest extends TestCase
{
/**
* @beforeClass
*/
public static function setUpSomeSharedFixtures(): void
{
// ...
}
/**
* @beforeClass
*/
public static function setUpSomeOtherSharedFixtures(): void
{
// ...
}
}
@codeCoverageIgnore*
Аннотации @codeCoverageIgnore, @codeCoverageIgnoreStart и @codeCoverageIgnoreEnd могут использоваться для исключения строк кода из анализа покрытия.
Для использования см. Игнорирование блоков кода.
@covers
Аннотация @covers может использоваться в тестовом коде для указания, какие части кода предполагается протестировать:
/**
* @covers \BankAccount
*/
public function testBalanceIsInitiallyZero(): void
{
$this->assertSame(0, $this->ba->getBalance());
}
При наличии она эффективно фильтрует отчет о покрытии кода, включая исполненный код только из указанных частей кода. Это гарантирует, что код будет помечен как покрытый только в случае наличия посвященных ему тестов, но не в случае косвенного использования тестами для другого класса, тем самым избегая ложных срабатываний по покрытию кода.
Эта аннотация может быть добавлена в блок документации класса теста или отдельных методов теста. Рекомендуется добавлять аннотацию в блок документации класса теста, а не в блок документации методов теста.
Когда опция конфигурации forceCoversAnnotation в файле конфигурации установлена в true, каждый метод теста должен иметь связанную аннотацию @covers (либо в классе теста, либо в отдельном методе теста).
Таблица 2.2 демонстрирует синтаксис аннотации @covers. Раздел Указание охватываемых частей кода содержит более подробные примеры использования этой аннотации.
Обратите внимание, что для этой аннотации требуется полное имя класса (FQCN). Для большей ясности для читателя рекомендуется использовать ведущий обратный слэш (даже если это не требуется для корректной работы аннотации).
| Аннотация | Описание |
|---|---|
@covers ClassName::methodName (не рекомендуется) | Указывает, что отмеченный метод теста охватывает указанный метод. |
@covers ClassName (рекомендуется) | Указывает, что отмеченный метод теста охватывает все методы данного класса. |
@covers ClassName<extended> (не рекомендуется) | Указывает, что отмеченный метод теста охватывает все методы данного класса и его родительских классов. |
@covers ClassName::<public> (не рекомендуется) | Указывает, что отмеченный метод теста охватывает все публичные методы данного класса. |
@covers ClassName::<protected> (не рекомендуется) | Указывает, что отмеченный метод теста охватывает все защищенные методы данного класса. |
@covers ClassName::<private> (не рекомендуется) | Указывает, что отмеченный метод теста охватывает все частные методы данного класса. |
@covers ClassName::<!public> (не рекомендуется) | Указывает, что отмеченный метод теста охватывает все методы данного класса, которые не являются публичными. |
@covers ClassName::<!protected> (не рекомендуется) | Указывает, что отмеченный метод теста охватывает все методы данного класса, которые не являются защищенными. |
@covers ClassName::<!private> (не рекомендуется) | Указывает, что отмеченный метод теста охватывает все методы данного класса, которые не являются частными. |
@covers ::functionName (рекомендуется) | Указывает, что отмеченный метод теста охватывает указанную глобальную функцию. |
@coversDefaultClass
Аннотация @coversDefaultClass может использоваться для указания имени пространства имен или класса по умолчанию. Таким образом, длинные имена не нужно повторять для каждой аннотации @covers. См. Пример 2.18.
Обратите внимание, что для этой аннотации требуется полное имя класса (FQCN). Для большей ясности для читателя рекомендуется использовать ведущий обратный слэш (даже если это не требуется для корректной работы аннотации).
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
/**
* @coversDefaultClass \Foo\CoveredClass
*/
final class CoversDefaultClassTest extends TestCase
{
/**
* @covers ::publicMethod
*/
public function testSomething(): void
{
$o = new Foo\CoveredClass;
$o->publicMethod();
}
}
@coversNothing
Аннотация @coversNothing может использоваться в тестовом коде для указания того, что для отмеченного тестового случая не будет регистрироваться информация о покрытии кода.
Это может использоваться для интеграционных тестов. См. Тест, который указывает, что ни один метод не должен быть покрыт для примера.
Аннотация может использоваться на уровне класса и метода и переопределяет любые теги @covers.
@dataProvider
Метод теста может принимать произвольные аргументы. Эти аргументы должны предоставляться одним или несколькими методами поставщиков данных (provider() в Использование поставщика данных, возвращающего массив массивов). Метод поставщика данных, который будет использоваться, указывается с помощью аннотации @dataProvider.
См. Поставщики данных для получения дополнительных сведений.
@depends
PHPUnit поддерживает объявление явных зависимостей между методами тестов. Такие зависимости не определяют порядок выполнения методов тестов, но они позволяют производителю вернуть экземпляр фикстуры теста и передать его зависимым потребителям. Использование аннотации @depends для выражения зависимостей демонстрирует, как использовать аннотацию @depends для выражения зависимостей между методами тестов.
Дополнительные сведения см. в разделе Зависимости тестов.
@doesNotPerformAssertions
Препятствует тому, чтобы тест, не выполняющий утверждения, считался рискованным.
@group
Тест можно пометить как принадлежащий к одной или нескольким группам, используя аннотацию @group следующим образом
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class MyTest extends TestCase
{
/**
* @group specification
*/
public function testSomething(): void
{
}
/**
* @group regression
* @group bug2204
*/
public function testSomethingElse(): void
{
}
}
Аннотация @group также может быть предоставлена для класса теста. Она затем «унаследуется» всеми методами тестирования этого класса.
Тесты можно выбирать для выполнения на основе групп, используя параметры --group и --exclude-group командного запуска тестов или соответствующие директивы файла конфигурации XML.
@large
Аннотация @large является псевдонимом для @group large.
Если пакет PHP_Invoker установлен и включен строгий режим, большой тест завершится неудачей, если его выполнение займет более 60 секунд. Этот таймаут настраивается через атрибут timeoutForLargeTests в файле конфигурации XML.
@medium
Аннотация @medium является псевдонимом для @group medium. Средний тест не должен зависеть от теста, помеченного как @large.
Если пакет PHP_Invoker установлен и включен строгий режим, средний тест завершится неудачей, если его выполнение займет более 10 секунд. Этот таймаут настраивается через атрибут timeoutForMediumTests в файле конфигурации XML.
@preserveGlobalState
Когда тест выполняется в отдельном процессе, PHPUnit попытается сохранить глобальное состояние из родительского процесса, сериализуя все глобальные переменные в родительском процессе и десериализуя их в дочернем процессе. Это может вызвать проблемы, если родительский процесс содержит глобальные переменные, которые не могут быть сериализованы. Чтобы исправить это, можно предотвратить сохранение глобального состояния PHPUnit с помощью аннотации @preserveGlobalState.
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class MyTest extends TestCase
{
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testInSeparateProcess(): void
{
// ...
}
}
@requires
Аннотация @requires может использоваться для пропуска тестов, когда общие предварительные условия, такие как версия PHP или установленные расширения, не выполнены.
Полный список возможностей и примеров можно найти в разделе Возможные применения @requires
@runTestsInSeparateProcesses
Указывает, что все тесты в классе тестов должны выполняться в отдельном процессе PHP.
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
/**
* @runTestsInSeparateProcesses
*/
final class MyTest extends TestCase
{
// ...
}
Примечание: По умолчанию PHPUnit попытается сохранить глобальное состояние из родительского процесса, сериализуя все глобальные переменные в родительском процессе и десериализуя их в дочернем процессе. Это может вызвать проблемы, если родительский процесс содержит глобальные переменные, которые не могут быть сериализованы. См. @preserveGlobalState для получения информации о том, как это исправить.
@runInSeparateProcess
Указывает, что тест должен выполняться в отдельном процессе PHP.
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class MyTest extends TestCase
{
/**
* @runInSeparateProcess
*/
public function testInSeparateProcess(): void
{
// ...
}
}
Примечание: По умолчанию PHPUnit попытается сохранить глобальное состояние из родительского процесса, сериализуя все глобальные переменные в родительском процессе и десериализуя их в дочернем процессе. Это может вызвать проблемы, если родительский процесс содержит глобальные переменные, которые не могут быть сериализованы. См. @preserveGlobalState для получения информации о том, как это исправить.
@small
Аннотация @small является псевдонимом для @group small. Малый тест не должен зависеть от теста, помеченного как @medium или @large.
Если пакет PHP_Invoker установлен и включен строгий режим, малый тест завершится неудачей, если его выполнение займет более 1 секунды. Этот таймаут настраивается через атрибут timeoutForSmallTests в файле конфигурации XML.
Примечание
Тесты необходимо явно аннотировать с помощью @small, @medium, или @large, чтобы включить ограничения по времени выполнения.
@test
В качестве альтернативы префиксу вашей методам тестов test, вы можете использовать аннотацию @test в блоке документации метода, чтобы отметить его как метод теста.
/**
* @test
*/
public function initialBalanceShouldBe0(): void
{
$this->assertSame(0, $this->ba->getBalance());
}
@testdox
Указывает альтернативное описание, используемое при генерации предложений для документации гибкой методологии.
Аннотация @testdox может применяться как к классам, так и к методам тестов.
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
/**
* @testdox A bank account
*/
final class BankAccountTest extends TestCase
{
/**
* @testdox has an initial balance of zero
*/
public function balanceIsInitiallyZero(): void
{
$this->assertSame(0, $this->ba->getBalance());
}
}
Примечание
До PHPUnit 7.0 (из-за ошибки в парсинге аннотаций) использование аннотации @testdox также активировало поведение аннотации @test.
При использовании аннотации @testdox на уровне метода с @dataProvider, вы можете использовать параметры метода в качестве заглушек в своем альтернативном описании.
/**
* @dataProvider additionProvider
* @testdox Adding $a to $b results in $expected
*/
public function testAdd($a, $b, $expected)
{
$this->assertSame($expected, $a + $b);
}
public function additionProvider()
{
return [
[0, 0, 0],
[0, 1, 1],
[1, 0, 1],
[1, 1, 3]
];
}
@testWith
Вместо реализации метода для использования с @dataProvider, вы можете определить набор данных, используя аннотацию @testWith.
Набор данных состоит из одного или нескольких элементов. Для определения набора данных с несколькими элементами, определите каждый элемент в отдельной строке. Каждый элемент набора данных должен быть массивом, определенным в JSON.
См. Поставщики данных для получения дополнительной информации о передаче набора данных в тест.
/**
* @testWith ["test", 4]
* ["longer-string", 13]
*/
public function testStringLength(string $input, int $expectedLength): void
{
$this->assertSame($expectedLength, strlen($input));
}
Представление объекта в JSON будет преобразовано в ассоциативный массив.
/**
* @testWith [{"day": "monday", "conditions": "sunny"}, ["day", "conditions"]]
*/
public function testArrayKeys(array $array, array $keys): void
{
$this->assertSame($keys, array_keys($array));
}
@ticket
Аннотация @ticket является псевдонимом для аннотации @group (см. @group) и позволяет фильтровать тесты на основе их идентификатора задачи.
@uses
Аннотация @uses указывает код, который будет выполнен тестом, но не предназначен для охвата тестом. Хорошим примером является объект значения, необходимый для тестирования блока кода.
/**
* @covers \BankAccount
* @uses \Money
*/
public function testMoneyCanBeDepositedInAccount(): void
{
// ...
}
Пример 9.2 демонстрирует другой пример.
Помимо полезности для чтения кода, эта аннотация полезна в режиме строгого охвата кода, где непреднамеренно охваченный код заставит тест завершиться неудачей. См. Непреднамеренно охваченный код для получения дополнительной информации о режиме строгого охвата кода.
Обратите внимание, что для этой аннотации требуется полностью квалифицированное имя класса (FQCN). Чтобы это было более очевидно для читателя, рекомендуется использовать ведущую обратную косую черту (даже если это не требуется для правильной работы аннотации).
© 2005–2020 Sebastian Bergmann
Licensed under the Creative Commons Attribution 3.0 Unported License.
https://phpunit.readthedocs.io/en/8.5/annotations.html