bex/behat-extension-driver-locator
Dynamic driver/service loader for Behat extensions. Locates drivers by key in a namespace, enforces interfaces, builds and validates per-driver config trees, and loads services via DI container. Includes a DriverNodeBuilder to generate driver config nodes.
ServiceProvider or Console extensions).Config\Definition for schema validation, which is compatible with Laravel’s config() system and Behat’s YAML-based configuration. This reduces boilerplate for validating custom driver configs.DriverInterface (or custom interfaces), ensuring type safety and loose coupling—a best practice in Laravel’s ecosystem (e.g., Illuminate\Contracts\* interfaces).Extension in a Laravel ServiceProvider to integrate with Laravel’s DI container.DriverLocator to dynamically load test drivers (e.g., database connectors, API clients) without coupling them to the core app.mysql, pgsql) based on config/testing.php.stripe, paypal) via behat.yml or Laravel’s config().Artisan commands or Http\Client with driver-based behaviors (e.g., S3Uploader, LocalStorage).ContainerBuilder changes).ContainerBuilder to Laravel’s Container).DriverInterface, DriverNodeBuilder, and config nodes—may not justify use for simple cases.App\Behat\Drivers), which could clutter the codebase if overused.Extension lifecycle (configure()/load()). Laravel’s testing stack (e.g., Pest) may need wrappers.ContainerBuilder differs from Laravel’s Container; may need a bridge service to pass configs.Is Behat the Right Tool?
ServiceProvider + bind() for dynamic drivers.Symfony/Behat Version Support
Driver Lifecycle Management
Illuminate\Contracts\Queue\Queue) alongside DriverInterface?Configuration Merge Strategy
config() and Behat’s behat.yml configs merge (e.g., priority, defaults)?active_my_awesome_drivers via config('behat.drivers.active').Performance Impact
Alternatives
config() + bind() for dynamic services.Illuminate\Support\Manager (e.g., FilesystemManager) for driver-like patterns.spatie/laravel-test-factories (for test data drivers).laravel-zero/framework (for CLI-driven dynamic services).Config and DependencyInjection components already used in Laravel.Extension interface).ContainerBuilder.Phase 1: Proof of Concept
php artisan behat) to avoid Laravel container conflicts.// app/Providers/BehatServiceProvider.php
public function register()
{
$this->app->singleton('behat.driver_locator', function () {
return DriverLocator::getInstance(
namespace: 'App\Behat\Drivers',
driverParent: App\Behat\Drivers\DriverInterface::class
);
});
}
// behat.yml
default:
extensions:
My\BehatExtension:
active_my_drivers: s3_uploader
my_drivers:
s3_uploader:
bucket: my-bucket
region: us-east-1
Phase 2: Laravel-Behat Bridge
Container to Behat’s ContainerBuilder:
class LaravelContainerBuilderAdapter implements ContainerBuilderInterface
{
public function __construct(private Container $laravelContainer) {}
public function get($id) { return $this->laravelContainer->make($id); }
// ... implement other ContainerBuilder methods
}
Config to override Behat’s YAML:
// config/behat.php
'drivers' => [
'active' => env('BEHAT_DRIVER', 'default'),
'config' => [
's3_uploader' => [
'bucket' => env('AWS_BUCKET'),
],
],
];
Phase 3: Full Integration
load():
$driverLocator->findDrivers(
container: new LaravelContainerBuilderAdapter(app()),
activeDrivers: $config['active_my_drivers'],
driverConfigs: $config['my_drivers']
);
// app/Console/Commands/BehatDriverList.php
public function handle()
{
$drivers = DriverLocator::getInstance(...)->getAvailableDrivers();
dd($drivers);
}
| Component | Compatibility Notes |
|---|---|
| Laravel | Works with Laravel 8+ (Symfony 5+). For Laravel 9/10, test ContainerBuilder compatibility. |
| Behat | Tested with Behat 3.x. May need updates for Behat 4+ (if released). |
| PHP | Requires PHP 7.4+ (for Symfony 5+). |
| Symfony | Uses symfony/config and symfony/dependency-injection. Check for breaking changes in Symfony 6+. |
| Composer | Install as --dev dependency to avoid bloating production. |
DriverInterface and concrete drivers (e.g., S3Driver, LocalDriver).namespace App\Behat\Drivers;
interface DriverInterface {
public function configure(): array;
public function load(ContainerBuilder $container, array $config);
}
DriverNodeBuilder in configure() to add driver nodes to Behat’s config schema.load():
DriverLocator to instantiate drivers with validated configs.How can I help you explore Laravel packages today?