PHP Unit
Filtering Tests
The filter flag can be used to specify specific tests in a file or even particular runs in a data provider.
phpunit --filter methodName path/to/file.php
This will run the test methodName
in the test file.php
Martin Hujer has some excellent advice for filtering tests using data providers
phpunit --filter "methodName#2" path/to/file.php
phpunit --filter "methodName#0-2" path/to/file.php
phpunit --filter "method@providerName" path/to/file.php
These examples all execute the test methodName
in file.php
, but in each case
they also filter by the data provider case. The first will data provider with
index 2, the second will run tests with indexes 0-2, the last will run the
named test "providerName"
Delayed Data Provider Execution
One issue that plagues PHPUnit is that the data provider methods must be called before the set up method in order to determine the total number of tests. If we are using set up to initialize an object under test, we do not have access to that object in the data provider. We can fix this issue by using closures to lazy-execute the returns from the providers:
class DateTimeTest extends TestCase
{
private $DateTime;
public function setUp(): void
{
$this->DateTime = DateTime::createFromFormat(
'Y-m-d H:i:s',
'2020-08-12 00:00:00',
new \DateTimezone('UTC')
);
}
/**
* @dataProvider timeZoneProvider
*/
public function testAdjustTimeZone(
string $expected,
\Closure $dateTime
): void {
$this->assertEquals(
$expected,
$dateTime()->format('Y-m-d H:i:s')
);
}
public function timeZoneProvider(): array
{
return [
'utc' => [
'expected' => '2020-08-12 00:00:00',
'dateTime => function() {
return $this->DateTime;
}
],
'chicago' => [
'expected' => '2020-08-11 18:00:00',
'dateTime' => function() {
return $this->DateTime->setTimezone('America/Chicago')
}
]
];
}
}
This is a contrived example, but it isn't uncommon to need to set up a complex object in the set up method only to want to mutate it in the provider and then test if the new state of the object matches an expected state.
In this case, if we passed $this::DateTime
back directly in the array we would
get null
since $this::DateTime
has not been set yet on the test object. But
if we pass a closure which fetches $this::DateTime
at the time of the test, we
will actually get the object we set up in setUp()
.
External References
- Hujer, Martin. How to Use Data Providers in PHPUnit, Martin Hujer blog. Retrieved 2020-10-14.
Linked References
- php-best-practices
- Test Driven Development with [[Unit testing]] using [[PHP Unit]]