Pest is the preferred test interface to evaluate for new PHP projects in this setup. PHPUnit remains the underlying engine and compatibility layer.
Install Pest per project with Composer. Do not install Pest globally.
For a new project:
composer require --dev pestphp/pest
vendor/bin/pest --initFor Symfony projects, add the Symfony plugin when useful:
composer require --dev pestphp/pest-plugin-symfonyAdd scripts to the project composer.json:
{
"scripts": {
"test": "pest",
"test:unit": "pest tests/Unit",
"test:integration": "pest tests/Integration",
"test:functional": "pest tests/Functional",
"test:coverage": "XDEBUG_MODE=off php -d pcov.enabled=1 vendor/bin/pest --coverage"
}
}Run them with:
composer test
composer test:coverageUse a clear test layout:
tests/Unitfor isolated domain logic;tests/Integrationfor database, filesystem, queue, mailer, and service wiring checks;tests/Functionalfor HTTP and end-to-end application flows.
Use datasets for repeated input/output examples:
it('normalizes email addresses', function (string $input, string $expected) {
expect(normalize_email($input))->toBe($expected);
})->with([
['USER@example.com', 'user@example.com'],
[' user@example.com ', 'user@example.com'],
]);Prefer real services for unit-level value objects and pure domain code. Use mocks for boundaries that are slow, remote, nondeterministic, or already covered elsewhere.
Use PCOV for fast coverage when the project adopts coverage. Use Xdebug for debugging. Do not run both coverage drivers at the same time.
