Installation
Requirements
- PHP 8.1 or higher
- Pest PHP 2.x or 3.x
- Composer
Installing Pest BDD
Install Pest BDD via Composer as a development dependency:
composer require testflowlabs/pest-plugin-bdd --devThat's it! The plugin automatically integrates with Pest.
Laravel Integration
Pest BDD is designed to work seamlessly with Laravel. Step attributes can be placed on any Laravel class - Models, Services, Actions, Controllers, Jobs, and more.
Supported Laravel Class Types
| Class Type | Step Type | Features |
|---|---|---|
| Factories | Given | Lazy creation, state chaining |
| Models | Given/When | Static methods, Model::find() fallback |
| Actions | When | Constructor DI, invokable support |
| Services | When | Full dependency injection |
| Controllers | When/Then | Request injection |
| Assertions | Then | Test-specific assertions |
Service Container Support
Pest BDD uses Laravel's Service Container (app()) to resolve step classes:
class OrderService
{
// Dependencies are automatically injected
public function __construct(
private PaymentGateway $gateway,
private InventoryService $inventory,
) {}
#[When('order is processed')]
public function process(Order $order): void
{
$this->gateway->charge($order);
$this->inventory->reserve($order->items);
}
}Static Method Support
Static methods on Models work as step definitions:
class User extends Model
{
#[Given('an admin user {name} exists')]
public static function createAdmin(string $name): self
{
return self::create(['name' => $name, 'role' => 'admin']);
}
}Model Query Fallback
When a step parameter is a Model type and the value is numeric, Pest BDD automatically queries the database:
#[When('order {id} is shipped')]
public function ship(Order $order): void // Order::find($id) if not in context
{
$order->update(['status' => 'shipped']);
}Learn More
See the Laravel Integration section for complete documentation on Factory integration, Service Container, and static methods.
Attributes Package
Pest BDD encourages placing step definitions in production code. To avoid requiring a test framework as a production dependency, step attributes are provided separately:
composer require testflowlabs/pest-test-attributes| Package | Type | Purpose |
|---|---|---|
pest-plugin-bdd | Dev dependency | Test runner, Gherkin parser, step discovery |
pest-test-attributes | Production dependency | Only the attribute classes (~4 files) |
Example: Action with Step Attribute
// app/Actions/User/CreateUser.php
namespace App\Actions\User;
use TestFlowLabs\PestTestAttributes\When;
class CreateUser
{
public function __construct(private UserRepository $users) {}
#[When('I create a user with email {email}')]
public function __invoke(string $email): User
{
return $this->users->create(['email' => $email]);
}
}This Action class works both in production (attribute ignored) and in BDD tests (attribute maps the step).
Optimizing Auto-Discovery
For complete step discovery, generate an optimized classmap:
composer dump-autoload --optimizeThis ensures Pest BDD can find all your step definition classes, especially in larger projects.
Why is this needed?
Pest BDD scans Composer's classmap to find classes with step attributes. By default, Composer only maps classes it has encountered. The --optimize flag generates a complete map of all classes in your project.
Project Structure
After installation, organize your BDD tests following the Given/When/Then pattern:
database/
└── factories/ # Given steps - Factory class'ları
├── UserFactory.php
└── OrderFactory.php
app/
└── Actions/ # When steps - Production Actions
└── User/
└── CreateUser.php
tests/
├── Behaviors/ # Feature files
│ ├── user-registration.feature
│ ├── shopping-cart.feature
│ └── checkout.feature
├── Assertions/ # Then steps - Assertion class'ları
│ ├── User/
│ │ └── UserAssertions.php
│ └── Shared/
│ └── CommonAssertions.php
└── Unit/ # Regular Pest tests
└── ...Step Location Summary
| Step Type | TDD | Location | Description |
|---|---|---|---|
| Given | Arrange | database/factories/ | Laravel Factory'ler |
| When | Act | app/Actions/ | Production Actions |
| Then | Assert | tests/Assertions/ | Test assertions |
Feature Files Location
Place your .feature files in tests/Behaviors/. Pest BDD automatically discovers all feature files in this directory and its subdirectories.
Step Definitions Location
Step definition classes can live anywhere in your project that Composer's autoloader can find:
database/factories/- Given steps (Factory class'ları)app/Actions/- When steps (Production Actions)tests/Assertions/- Then steps (Assertion class'ları)
Laravel-Specific Setup
Autoload Configuration
For Pest BDD to discover step definitions in all locations, ensure your composer.json includes:
{
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}
}Then run:
composer dump-autoload --optimizeTestbench for Package Development
If you're developing a Laravel package and using Orchestra Testbench:
// tests/TestCase.php
abstract class TestCase extends \Orchestra\Testbench\TestCase
{
// Your test case configuration
}Pest BDD works seamlessly with Testbench for package testing.
Recommended Reading
For detailed Laravel integration documentation:
- Service Container - Dependency injection in step classes
- Factory Integration - Using factories as Given steps
- Static Methods - Model static methods as steps
- Step Execution - How steps are resolved and executed
Verifying Installation
Create a simple feature to verify everything works:
tests/Behaviors/hello.feature:
Feature: Hello World
Scenario: Greeting
Given I say hello
Then I should feel welcomedtests/Assertions/HelloAssertions.php:
<?php
namespace Tests\Assertions;
use TestFlowLabs\PestTestAttributes\Given;
use TestFlowLabs\PestTestAttributes\Then;
class HelloAssertions
{
#[Given('I say hello')]
public function sayHello(): void
{
// Setup step
}
#[Then('I should feel welcomed')]
public function shouldFeelWelcomed(): void
{
expect(true)->toBeTrue();
}
}Run the BDD tests:
./vendor/bin/pest --bddYou should see:
PASS Feature: Hello World
✓ Scenario: Greeting
Tests: 1 passed
Duration: 0.02sTroubleshooting
Steps Not Found
If Pest BDD can't find your step definitions:
- Run
composer dump-autoload --optimize - Ensure your step classes are in a PSR-4 autoloaded directory
- Verify the namespace matches your autoload configuration
Feature Files Not Found
If feature files aren't discovered:
- Ensure files have the
.featureextension - Place files in
tests/Behaviors/directory - Check file permissions