Extensions
Extend phpspec with custom matchers, formatters, commands, and event listeners.
Extensions are Composer packages registered in phpspec.yaml.
Quick start
- Install the package:
composer require --dev acme/phpspec-nyan-formatter - Register in
phpspec.yaml:
extensions: formatters: - Acme\NyanFormatter
- Use it:
bin/phpspec run --format nyan
Configuration
extensions: matchers: - App\ValidJsonMatcher formatters: - App\MinimalFormatter commands: - App\GreetCommand listeners: - App\SlowTestReporter
Matcher extensions
Custom matchers extend MatcherExtension:
use PhpSpec\Extensions\MatcherExtension; class ValidJsonMatcher extends MatcherExtension { public function getName(): string { return 'toBeValidJson'; } public function match(mixed $actual, mixed ...$args): bool { if (!is_string($actual)) { return false; } json_decode($actual); return json_last_error() === JSON_ERROR_NONE; } public function failureMessage(mixed $actual): string { return 'Expected valid JSON'; } }
Use in specs:
expect('{"name": "phpspec"}')->toBeValidJson(); expect('not json')->not()->toBeValidJson();
Formatter extensions
class MinimalFormatter extends FormatterExtension { public function getName(): string { return 'minimal'; } public function formatPass(string $title): string { return "OK: $title"; } public function formatFail(string $title, string $message): string { return "FAIL: $title - $message"; } }
Use with --format minimal or set as default in config.
Command extensions
use PhpSpec\Extensions\CommandExtension; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class GreetCommand extends CommandExtension { public function getName(): string { return 'greet'; } public function getDescription(): string { return 'Say hello'; } public function execute(InputInterface $input, OutputInterface $output): int { $output->writeln('Hello from extension!'); return 0; } }
Run with: bin/phpspec greet
Listener extensions
React to lifecycle events:
class SlowTestReporter extends ListenerExtension { private array $slow = []; public function afterExample(string $title, float $duration): void { if ($duration > 0.5) { $this->slow[] = [$title, $duration]; } } public function afterSuite(): void { foreach ($this->slow as [$title, $duration]) { printf(" %.3fs %s\n", $duration, $title); } } }
Available events
| Event | Arguments |
|---|---|
beforeSuite() | — |
afterSuite() | — |
beforeSpec(string $title) | Spec file title |
afterSpec(string $title) | Spec file title |
beforeExample(string $title) | Example title |
afterExample(string $title, float $duration) | Title + duration |
onPass(string $title) | Passed example |
onFail(string $title, string $message) | Failed example |
onError(string $title, string $message) | Errored example |
onPending(string $title) | Pending example |
onSkipped(string $title) | Skipped example |
Auto-discovery
Extensions can opt into auto-discovery via composer.json:
{
"extra": {
"phpspec": {
"formatters": ["Acme\\NyanFormatter"]
}
}
}
Disable auto-discovery for a specific package:
extensions: disabled: - acme/phpspec-nyan-formatter
Extension interfaces
| Type | Base class | Required methods |
|---|---|---|
| Formatter | FormatterExtension | getName(), formatPass(), formatFail() |
| Matcher | MatcherExtension | getName(), match(), failureMessage() |
| Command | CommandExtension | getName(), execute() |
| Listener | ListenerExtension | At least one event method |
All base classes live in PhpSpec\Extensions\.