2. Attributes
Prior to PHPUnit 10, annotations in special PHP comments, so-called “DocBlocks” or “doc-comments”, were the only means of attaching metadata to code units. These annotations are documented in another appendix.
PHP 8 introduced attributes as “a form of structured, syntactic metadata to declarations of classes, properties, functions, methods, parameters and constants. Attributes allow to define configuration directives directly embedded with the declaration of that code.”
PHPUnit will first look for metadata in attributes before it looks for annotations in comments. When metadata is found in attributes, metadata in comments is ignored.
The attributes supported by PHPUnit are all declared in the PHPUnit\Framework\Attributes
namespace. They are documented in this appendix.
Test
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
no |
As an alternative to prefixing your test method names with test
,
you can use the Test
attribute to mark it as a test method.
<?php declare(strict_types=1);
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
final class ExampleTest extends TestCase
{
#[Test]
public function it_does_something(): void
{
// ...
}
}
TestDox
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
no |
The TestDox(string $text)
attribute can be used to customize the text that is printed for
a test when TestDox output is enabled.
<?php declare(strict_types=1);
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\TestCase;
final class ExampleTest extends TestCase
{
#[TestDox('It does something')]
public function testOne(): void
{
// ...
}
}
Running the test shown above with TestDox output enabled yields the output shown below:
$ ./tools/phpunit --no-progress --testdox tests/ExampleTest.php PHPUnit 11.5.0 by Sebastian Bergmann and contributors. Runtime: PHP 8.2.2 Time: 00:00.057, Memory: 6.00 MB Example ✔ It does something OK (1 test, 1 assertion)
When you use the TestDox
attribute for a test method that uses a
data provider then you
may use the method parameters as placeholders in your alternative description.
<?php declare(strict_types=1);
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\TestCase;
final class ExampleTest extends TestCase
{
#[DataProvider('additionProvider')]
#[TestDox('Adding $a to $b results in $expected')]
public function testAdd(int $expected, int $a, int $b)
{
$this->assertSame($expected, $a + $b);
}
public static function additionProvider()
{
return [
'data set 1' => [0, 0, 0],
'data set 2' => [1, 0, 1],
'data set 3' => [1, 1, 0],
'data set 4' => [3, 1, 1]
];
}
}
Running the test shown above with TestDox output enabled yields the output shown below:
$ ./tools/phpunit --no-progress --testdox tests/ExampleTest.php PHPUnit 11.5.0 by Sebastian Bergmann and contributors. Runtime: PHP 8.2.2 Time: 00:00.116, Memory: 8.00 MB Example ✔ Adding 0 to 0 results in 0 ✔ Adding 1 to 0 results in 1 ✔ Adding 0 to 1 results in 1 ✘ Adding 1 to 1 results in 3 │ │ Failed asserting that 2 is identical to 3. │ │ /path/to/ExampleTest.php:12 │ FAILURES! Tests: 4, Assertions: 4, Failures: 1.
Additionally, $_dataName
is available and holds the name of the current data.
That would be data set 1
through data set 4
in the example shown above.
DisableReturnValueGenerationForTestDoubles
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
no |
The DisableReturnValueGenerationForTestDoubles
attribute can be used to disable the return value generation
for test doubles created using createMock()
, createMockForIntersectionOfInterfaces()
, createPartialMock()
,
createStub()
, and createStubForIntersectionOfInterfaces()
for all tests of a test case class.
DoesNotPerformAssertions
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
no |
By default, PHPUnit considers a test that does not perform assertions and does not configure
expectations on mock objects as risky. The
DoesNotPerformAssertions
attribute can be used to prevent this.
IgnoreDeprecations
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
no |
The IgnoreDeprecations
attribute can be used to configure PHPUnit’s error handler to
not emit events for E_DEPRECATED
and E_USER_DEPRECATED
errors.
WithoutErrorHandler
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
no |
The WithoutErrorHandler
attribute can be used to disable PHPUnit’s error handler for
a test method.
Warning
Features of PHPUnit that rely on PHPUnit’s error handler to be active while a test method
is executed will not work when PHPUnit’s error handler is disabled. No E_(USER_)*
errors
triggered by PHP will be processed by PHPUnit when its error handler is disabled.
You should only disable PHPUnit’s error handler when it interferes with the code you are testing,
for instance when it uses error_get_last()
to react to E_(USER_)*
errors triggered by PHP.
Code Coverage
CoversClass
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
yes |
The CoversClass(string $className)
attribute can be used to specify
that a test intends to cover the given class.
CoversTrait
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
yes |
The CoversTrait(string $traitName)
attribute can be used to specify
that a test intends to cover the given trait.
Deprecation: CoversTrait
is deprecated
As of PHPUnit 11.4, the CoversTrait
attribute is deprecated. It will be removed in PHPUnit 12.
The CoversClass
attribute also targets traits used by the targeted class.
CoversMethod
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
yes |
The CoversMethod(string $className, string $methodName)
attribute can be used to specify
that a test intends to cover the given method.
CoversFunction
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
yes |
The CoversFunction(string $functionName)
attribute can be used to specify
that a test intends to cover the given function.
CoversNothing
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
no |
The CoversNothing()
attribute can be used to specify
that a test does not intend to contribute to code coverage.
UsesClass
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
yes |
The UsesClass(string $className)
attribute can be used to specify
that a test allows the execution of code in the given class, but does not intend to cover it. This is relevant
in the context of preventing unintentionally covered code.
UsesTrait
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
yes |
The UsesTrait(string $traitName)
attribute can be used to specify
that a test allows the execution of code in the given trait, but does not intend to cover it. This is relevant
in the context of preventing unintentionally covered code.
Deprecation: UsesTrait
is deprecated
As of PHPUnit 11.4, the UsesTrait
attribute is deprecated. It will be removed in PHPUnit 12.
The UsesClass
attribute also targets traits used by the targeted class.
UsesMethod
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
yes |
The UsesMethod(string $className)
attribute can be used to specify
that a test allows the execution of code in the given method, but does not intend to cover it. This is relevant
in the context of preventing unintentionally covered code.
UsesFunction
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
yes |
The UsesFunction(string $functionName)
attribute can be used to specify
that a test allows the execution of code in the given global function, but does not intend to cover it. This is relevant
in the context of preventing unintentionally covered code.
Data Provider
DataProvider
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The DataProvider(string $methodName)
attribute can be used on a test method
to specify a static method that is declared in the same class as the test method
as a data provider.
DataProviderExternal
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The DataProviderExternal(string $className, string $methodName)
attribute can be used
on a test method to specify a static method that is declared in another class as a
data provider.
TestWith
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The TestWith(array $data)
attribute can be used to define a
data provider for a
test method without having to implement a static data provider method.
<?php declare(strict_types=1);
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
final class DataTest extends TestCase
{
#[TestWith([0, 0, 0])]
#[TestWith([0, 1, 1])]
#[TestWith([1, 0, 1])]
#[TestWith([1, 1, 3])]
public function testAdd(int $a, int $b, int $expected): void
{
$this->assertSame($expected, $a + $b);
}
}
Running the test shown above yields the output shown below:
./tools/phpunit tests/DataTest.php PHPUnit 11.5.0 by Sebastian Bergmann and contributors. Runtime: PHP 8.2.2 ...F 4 / 4 (100%) Time: 00:00.058, Memory: 8.00 MB There was 1 failure: 1) DataTest::testAdd with data set #3 Failed asserting that 2 is identical to 3. /path/to/DataTest.php:10 FAILURES! Tests: 4, Assertions: 4, Failures: 1.
TestWithJson
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The TestWithJson(string $json)
attribute can be used to define a
data provider for a
test method without having to implement a static data provider method.
<?php declare(strict_types=1);
use PHPUnit\Framework\Attributes\TestWithJson;
use PHPUnit\Framework\TestCase;
final class DataTest extends TestCase
{
#[TestWithJson('[0, 0, 0]')]
#[TestWithJson('[0, 1, 1]')]
#[TestWithJson('[1, 0, 1]')]
#[TestWithJson('[1, 1, 3]')]
public function testAdd(int $a, int $b, int $expected): void
{
$this->assertSame($expected, $a + $b);
}
}
Running the test shown above yields the output shown below:
./tools/phpunit tests/DataTest.php PHPUnit 11.5.0 by Sebastian Bergmann and contributors. Runtime: PHP 8.2.2 ...F 4 / 4 (100%) Time: 00:00.058, Memory: 8.00 MB There was 1 failure: 1) DataTest::testAdd with data set #3 Failed asserting that 2 is identical to 3. /path/to/DataTest.php:10 FAILURES! Tests: 4, Assertions: 4, Failures: 1.
Test Dependencies
Depends
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The Depends(string $methodName)
attribute can be used to specify that a test
depends
on another test that is declared in the same test case class.
Any value that is passed from a producer (a depended-upon test) to a consumer (the depending test) is passed without cloning it.
DependsUsingDeepClone
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The DependsUsingDeepClone(string $methodName)
attribute can be used to specify that a test
depends
on another test that is declared in the same test case class.
Any value that is passed from a producer (a depended-upon test) to a consumer (the depending test) is passed after deep-cloning it.
DependsUsingShallowClone
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The DependsUsingShallowClone(string $methodName)
attribute can be used to specify that a test
depends
on another test that is declared in the same test case class.
Any value that is passed from a producer (a depended-upon test) to a consumer (the depending test) is passed after shallow-cloning it.
DependsExternal
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The DependsExternal(string $className, string $methodName)
attribute can be used
to specify that a test depends
on another test that is declared in another test case class.
Any value that is passed from a producer (a depended-upon test) to a consumer (the depending test) is passed without cloning it.
DependsExternalUsingDeepClone
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The DependsExternalUsingDeepClone(string $className, string $methodName)
attribute can be used
to specify that a test depends
on another test that is declared in another test case class.
Any value that is passed from a producer (a depended-upon test) to a consumer (the depending test) is passed after deep-cloning it.
DependsExternalUsingShallowClone
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The DependsExternalUsingShallowClone(string $className, string $methodName)
attribute can be used
to specify that a test depends
on another test that is declared in another test case class.
Any value that is passed from a producer (a depended-upon test) to a consumer (the depending test) is passed after shallow-cloning it.
DependsOnClass
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The DependsOnClass(string $className)
attribute can be used to specify that a test
depends
on all tests of another test case class.
Any value that is passed from a producer (a depended-upon test) to a consumer (the depending test) is passed without cloning it.
DependsOnClassUsingDeepClone
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The DependsOnClassUsingDeepClone(string $className)
attribute can be used to specify that a test
depends
on all tests of another test case class.
Any value that is passed from a producer (a depended-upon test) to a consumer (the depending test) is passed after deep-cloning it.
DependsOnClassUsingShallowClone
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
yes |
The DependsOnClassUsingShallowClone(string $className)
attribute can be used to specify that a test
depends
on all tests of another test case class.
Any value that is passed from a producer (a depended-upon test) to a consumer (the depending test) is passed after shallow-cloning it.
Test Groups
Group
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
yes |
The Group(string $name)
attribute can be used to assign tests to test groups.
Groups can be used, for instance, to select which tests should be run.
The strings small
, medium
, and large
may not be used as group names.
Small
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
no |
The Small
attribute marks the tests of a test case class as small. These tests are
added to a special test group named small
that has special semantics.
The size of a test is relevant in the context of test execution timeouts, for instance.
Tests that are marked as small cause the lines of code that they cover to be highlighted by a darker shade of green in the HTML code coverage report compared to tests that are marked medium or large.
Medium
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
no |
The Medium
attribute marks the tests of a test case class as medium. These tests are
added to a special test group named medium
that has special semantics.
The size of a test is relevant in the context of test execution timeouts, for instance.
Tests that are marked as medium cause the lines of code that they cover to be highlighted by a darker shade of green in the HTML code coverage report compared to tests that are marked large and by a lighter shade of green compared to test that are marked small small.
Large
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
no |
The Large
attribute marks the tests of a test case class as large. These tests are
added to a special test group named large
that has special semantics.
The size of a test is relevant in the context of test execution timeouts, for instance.
Tests that are marked as large cause the lines of code that they cover to be highlighted by a lighter shade of green in the HTML code coverage report compared to tests that are marked medium or small.
Ticket
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
yes |
The Ticket(string $text)
attribute is an alias for Group(string $text)
.
Template Methods
BeforeClass
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
no |
The BeforeClass(int $priority = 0)
attribute can be used to specify that a public static method should
be invoked before the first test method of a test case class is run. This is the same
phase where a method named setUpBeforeClass()
would be invoked. We refer to such
methods as “before test class” methods.
When a test case class has more than one methods with the BeforeClass
attribute then,
by default, the test runner assumes that the order in which these methods are invoked
does not matter. If this assumption is wrong and the order in which these methods are
invoked does matter then the attribute’s optional $priority
argument (non-negative
integer) can be used to define the desired invocation order: a method with a higher
$priority
value is invoked before a method with a lower $priority
value.
Before
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
no |
The Before(int $priority = 0)
attribute can be used to specify that a protected non-static method should
be invoked before each test method of a test case class is run. This is the same phase
where a method named setUp()
would be invoked. We refer to such methods as “before test”
methods.
When a test case class has more than one methods with the Before
attribute then,
by default, the test runner assumes that the order in which these methods are invoked
does not matter. If this assumption is wrong and the order in which these methods are
invoked does matter then the attribute’s optional $priority
argument (non-negative
integer) can be used to define the desired invocation order: a method with a higher
$priority
value is invoked before a method with a lower $priority
value.
PreCondition
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
no |
The PreCondition(int $priority = 0)
attribute can be used to specify that a protected non-static method should
be invoked before each test method (but after any “before test” methods) of a test case class is run.
This is the same phase where a method named assertPreConditions()
would be invoked.
We refer to such methods as “pre-condition” methods.
When a test case class has more than one methods with the PreCondition
attribute then,
by default, the test runner assumes that the order in which these methods are invoked
does not matter. If this assumption is wrong and the order in which these methods are
invoked does matter then the attribute’s optional $priority
argument (non-negative
integer) can be used to define the desired invocation order: a method with a higher
$priority
value is invoked before a method with a lower $priority
value.
PostCondition
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
no |
The PostCondition(int $priority = 0)
attribute can be used to specify that a protected non-static method should
be invoked after each test method (but before any “after test” methods) of a test case class is run.
This is the same phase where a method named assertPostConditions()
would be invoked.
We refer to such methods as “post-condition” methods.
When a test case class has more than one methods with the PostCondition
attribute then,
by default, the test runner assumes that the order in which these methods are invoked
does not matter. If this assumption is wrong and the order in which these methods are
invoked does matter then the attribute’s optional $priority
argument (non-negative
integer) can be used to define the desired invocation order: a method with a higher
$priority
value is invoked before a method with a lower $priority
value.
After
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
no |
The After(int $priority = 0)
attribute can be used to specify that a protected non-static method should
be invoked after each test method of a test case class is run. This is the same phase where
a method named tearDown()
would be invoked. We refer to such methods as “after test” methods.
When a test case class has more than one methods with the After
attribute then,
by default, the test runner assumes that the order in which these methods are invoked
does not matter. If this assumption is wrong and the order in which these methods are
invoked does matter then the attribute’s optional $priority
argument (non-negative
integer) can be used to define the desired invocation order: a method with a higher
$priority
value is invoked before a method with a lower $priority
value.
AfterClass
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
no |
The AfterClass(int $priority = 0)
attribute can be used to specify that a public static method should
be invoked after the last test method of a test case class is run. This is the same phase
where a method named tearDownAfterClass()
would be invoked. We refer to such methods
as “after test class” methods.
When a test case class has more than one methods with the AfterClass
attribute then,
by default, the test runner assumes that the order in which these methods are invoked
does not matter. If this assumption is wrong and the order in which these methods are
invoked does matter then the attribute’s optional $priority
argument (non-negative
integer) can be used to define the desired invocation order: a method with a higher
$priority
value is invoked before a method with a lower $priority
value.
Test Isolation
BackupGlobals
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
no |
The BackupGlobals
attribute can be used to specify that global and super-global variables
should be backed up before a test and then restored after the test has been run.
ExcludeGlobalVariableFromBackup
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
yes |
The ExcludeGlobalVariableFromBackup($globalVariableName)
attribute can be used to exclude
the specified global variable from the backup and restore operations for global and super-global
variables.
BackupStaticProperties
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
no |
The BackupStaticProperties
attribute can be used to specify that static properties of classes
should be backed up before a test and then restored after the test has been run.
ExcludeStaticPropertyFromBackup
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
yes |
The ExcludeStaticPropertyFromBackup(string $className, string $propertyName)
attribute can be
used to exclude the specified static property from the backup and restore operations for static
properties of classes.
RunInSeparateProcess
Class Level |
Method Level |
Repeatable |
---|---|---|
no |
yes |
no |
The RunInSeparateProcess
attribute can be used to specify that a test should
be run in a separate process.
RunTestsInSeparateProcesses
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
no |
The RunTestsInSeparateProcesses
attribute can be used to specify that all tests
of a test case class should be run in separate processes (one separate process per test).
RunClassInSeparateProcess
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
no |
no |
The RunClassInSeparateProcess
attribute can be used to specify that all tests
of a test case class should be run in a (single) separate process.
PreserveGlobalState
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
no |
The PreserveGlobalState(bool $enabled)
attribute can be used to specify whether
the global state of the main PHPUnit test runner process should be made available in
the child process when a test is run in a separate process.
Skipping Tests
RequiresPhp
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
no |
The RequiresPhp(string $versionRequirement)
attribute can be used to
skip the execution of a test
when the PHP version used to run PHPUnit does not match the specified version requirement.
$versionRequirement
can either be a version number string
that is optionally preceded by an operator supported by PHP’s version_compare()
function or a version constraint
in the syntax that is supported by Composer.
Here are some examples:
#[RequiresPhp('8.3.0')]
#[RequiresPhp('>= 8.3.0')]
#[RequiresPhp('^8.3')]
RequiresPhpExtension
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
yes |
The RequiresPhpExtension(string $extension[, string $versionRequirement])
attribute can be used to
skip the execution of a test
when the specified PHP extension is not available. The optional $versionRequirement
argument can be used
to specify a version requirement for this PHP extension and follows the same format that is described
here.
Here are some examples:
#[RequiresPhpExtension('mysqli')]
#[RequiresPhpExtension('mysqli', '>= 8.3.0')]
#[RequiresPhpExtension('mysqli', '^8.3')]
RequiresSetting
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
yes |
The RequiresSetting(string $setting, string $value)
attribute can be used to
skip the execution of a test
when the specified PHP configuration setting is not set to the expected value.
RequiresPhpunit
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
no |
The RequiresPhpunit(string $versionRequirement)
attribute can be used to
skip the execution of a test
when the PHPUnit version does not match the specified version requirement.
$versionRequirement
can either be a version number string
that is optionally preceded by an operator supported by PHP’s version_compare()
function or a version constraint
in the syntax that is supported by Composer.
Here are some examples:
#[RequiresPhpunit('10.1.0')]
#[RequiresPhpunit('>= 10.1.0')]
#[RequiresPhpunit('^10.1')]
RequiresPhpunitExtension
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
yes |
The RequiresPhpunitExtension(string $extensionClass)
attribute can be used to
skip the execution of a test
when the PHPUnit extension identified by its bootstrap class is not available.
RequiresFunction
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
yes |
The RequiresFunction(string $functionName)
attribute can be used to
skip the execution of a test
when the specified global function is not declared.
RequiresMethod
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
yes |
The RequiresMethod(string $className, string $methodName)
attribute can be used to
skip the execution of a test
when the specified method is not declared.
RequiresOperatingSystem
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
no |
The RequiresOperatingSystem(string $regularExpression)
attribute can be used to
skip the execution of a test
when the specified regular expression does not match the value of the PHP_OS
constant provided by PHP.
RequiresOperatingSystemFamily
Class Level |
Method Level |
Repeatable |
---|---|---|
yes |
yes |
no |
The RequiresOperatingSystemFamily(string $operatingSystemFamily)
attribute can be used to
skip the execution of a test
when the specified string is not identical to the value of the PHP_OS_FAMILY
constant provided by PHP.