If you're starting a new project, we recommend to use Symfony 4 with Flex as it's the most straightforward way. If you're adding this extension to an existing project, pick the method that fits it the best.
- Require this extension using Composer and allow for using contrib recipes:
composer require --dev friends-of-behat/symfony-extension:^2.0- Require this extension using Composer:
composer require --dev friends-of-behat/symfony-extension:^2.0- Enable it within your Behat configuration:
# behat.yaml.dist / behat.yaml
default:
extensions:
FriendsOfBehat\SymfonyExtension: ~- Register a helper bundle in your kernel:
# config/bundles.php
return [
// ...
FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle::class => ['test' => true],
];- Create
tests/Behatdirectory for Behat-related classes:
mkdir -p tests/Behat- Set up autowiring and autoconfiguration for Behat-related services you'll create later:
# config/services_test.yaml
services:
_defaults:
autowire: true
autoconfigure: true
App\Tests\Behat\:
resource: '../tests/Behat/*'- Require this extension using Composer:
composer require --dev friends-of-behat/symfony-extension:^2.0- Enable it within your Behat configuration:
# behat.yml.dist / behat.yml
default:
extensions:
FriendsOfBehat\SymfonyExtension: ~- Register a helper bundle in your kernel:
# app/AppKernel.php
public function registerBundles()
{
$bundles = array(
// ...
);
if ('test' === $this->getEnvironment()) {
$bundles[] = new \FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle();
}
}- Create
tests/Behatdirectory for Behat-related classes:
mkdir -p tests/Behat- Set up autowiring and autoconfiguration for Behat-related services you'll create later:
# app/config/config_test.yml
# ...
services:
_defaults:
autowire: true
autoconfigure: true
Tests\Behat\:
resource: '../../tests/Behat/*'This tutorial assumes you're using the new directory structure with autowiring and autoconfiguration enabled. Let's first create a sample feature file (which is quite useless for demo purposes):
# features/using_symfony_extension.feature
Feature: Using SymfonyExtension
Scenario: Checking the application's kernel environment
Then the application's kernel should use "test" environmentThere are two methods to check the kernel's environment - either by calling getEnvironment() method on the kernel itself
or by injecting %kernel.environment% parameter.
We'll need also a dummy context implementation:
<?php
# tests/Behat/DemoContext.php
namespace App\Tests\Behat;
// If using Symfony 3, use namespace "Tests\Behat" instead
use Behat\Behat\Context\Context;
final class DemoContext implements Context
{
/**
* @Then the application's kernel should use :expected environment
*/
public function kernelEnvironmentShouldBe(string $expected): void
{
}
}And also a suite defined in Behat configuration:
# behat.yaml.dist / behat.yaml
default:
suites:
default:
contexts:
- App\Tests\Behat\DemoContext
After running Behat, the scenario should be passing.
Modify the existing DemoContext to be able to inject a kernel instance:
<?php
// ...
use Symfony\Component\HttpKernel\KernelInterface;
final class DemoContext implements Context
{
/** @var KernelInterface */
private $kernel;
public function __construct(KernelInterface $kernel)
{
$this->kernel = $kernel;
}
/**
* @Then the application's kernel should use :expected environment
*/
public function kernelEnvironmentShouldBe(string $expected): void
{
if ($this->kernel->getEnvironment() !== $expected) {
throw new \RuntimeException();
}
}
}If you're using autowiring and autoconfiguration, that's all you need! After running Behat, you should see a passing scenario.
If you're not, you need to register your context as a public service and define its dependencies:
# config/services_test.yaml (Symfony 4/5)
# app/config/config_test.yml (Symfony 3)
services:
App\Tests\Behat\DemoContext:
public: true
arguments:
- "@kernel"Modify the existing DemoContext to be able to inject a kernel environment as a parameter:
<?php
// ...
final class DemoContext implements Context
{
/** @var string */
private $environment;
public function __construct(string $environment)
{
$this->environment = $environment;
}
/**
* @Then the application's kernel should use :expected environment
*/
public function kernelEnvironmentShouldBe(string $expected): void
{
if ($this->environment !== $expected) {
throw new \RuntimeException();
}
}
}If you're using autowiring and autoconfiguration, that's all you need! After running Behat, you should see a passing scenario.
If you're not, you need to register your context as a public service and define its dependencies:
# config/services_test.yaml (Symfony 4/5)
# app/config/config_test.yml (Symfony 3)
services:
App\Tests\Behat\DemoContext:
public: true
arguments:
- "%kernel.environment%"SymfonyExtension provides an integration with Mink and defines a dedicated, isolated driver to use for Symfony application testing.
- Require the packages needed for the driver using Composer:
composer require --dev friends-of-behat/mink friends-of-behat/mink-extension friends-of-behat/mink-browserkit-driverThose friends-of-behat packages are forks of the original ones, adding support for Symfony 5 and dropping support for Symfony <4.4.
- Enable the bundled driver:
# behat.yaml.dist / behat.yaml
default:
extensions:
# ...
Behat\MinkExtension:
sessions:
symfony:
symfony: ~In order to use Mink, pass the Session to the constructor and call methods on it in the context.
use Behat\Behat\Context\Context;
use Behat\Mink\Session;
use Symfony\Component\Routing\RouterInterface;
final class DemoContext implements Context
{
/** @var Session */
private $session;
/** @var RouterInterface */
private $router;
public function __construct(Session $session, RouterInterface $router)
{
$this->session = $session;
$this->router = $router;
}
/**
* @Then I visit some page
*/
public function visitSomePage(): void
{
$this->session->visit($this->router->generate('some_route'));
}
}Calling any method on Mink-related services in the constructor is not permitted and will cause errors.
This integration provides the following services to use inside Symfony container:
-
behat.mink(autowired by\Behat\Mink\Mink) - the Mink service -
behat.mink.default_session(autowired by\Behat\Mink\Session) - the default Mink session for the current scenario -
behat.mink.parameters(autowired by\FriendsOfBehat\SymfonyExtension\Mink\MinkParameters) - an object containing the configuration parameters ofMinkExtension(implementing\ArrayAccessso that it can be treated as an array) -
behat.driver.service_container- service container used by thesymfonyMink driver, useful for assertions based on application state after a request has been handled
In Behat/Symfony2Extension the dependencies of a context are defined in the Behat configuration file. In this extension, contexts are defined as services - this makes reusing suites effortless, also allowing to support autowiring and autoconfiguration.
The Mink driver provided with this extension differs from the one provided with Behat/Symfony2Extension, as it uses an isolated application kernel instance, so that services state changes within your contexts does not affect the driver results. With that limitation, changing the driver to a different one is seamless. For more information, look at this issue.
By default, if no confguration is passed, SymfonyExtension will try its best to guess it. The full configuration tree looks like that:
# behat.yaml.dist / behat.yaml
default:
extensions:
FriendsOfBehat\SymfonyExtension:
bootstrap: ~
kernel:
class: ~
path: ~
environment: ~
debug: ~-
bootstrap:It is a path to the file requried once while the extension is loaded. You can use this file to set up your testing environment - set some enviornment variables or preload an external file. If you do not pass any, it would look for either
config/bootstrap.php(Symfony 4/5) orapp/autoload.php(Symfony 3). If none are found, no file would be loaded. -
kernel.class:It is a fully qualified class name of the application kernel class. If you do not pass any, it would look for either
App\Kernel(Symfony 4/5) orAppKernel(Symfony 3). If none are found, an exception would be thrown and you would be required to specify it explicitly. -
kernel.path:It is a path to the file containing the application kernel class. You might want to set it if your kernel is not autoloaded by Composer's autoloaded. If
kernel.classis not defined, it would automatically useapp/AppKernel.phpifAppKernelclass was autoconfigured. -
kernel.environment:It allows you to force using a given environment. If it is not set, it uses
APP_ENVenvironment variable if defined or falls back totest. -
kernel.debug:It allows you to force enabling or disabling debug mode. If it is not set, it uses
APP_DEBUGenvironment variable if defined or falls back totrue.