Behat Extension
Run Gherkin scenarios in a real browser: extension wiring, configuration, and custom step contexts.
The playwright-php/playwright-behat package is a Behat extension that runs scenarios in a Playwright-controlled browser. Feature files stay in Gherkin; the steps drive Chromium, Firefox, or WebKit.
composer require --dev playwright-php/playwright-behat
vendor/bin/playwright-install --browsers
Wiring
Enable the extension by its class name, then add a context to the suite that should use a browser.
default:
extensions:
Playwright\Behat\ServiceContainer\PlaywrightExtension:
base_url: 'http://localhost:8000'
suites:
web:
paths: ['%paths.base%/features']
contexts:
- Playwright\Behat\Context\PlaywrightContext
Behat 4 removed YAML configuration. The PHP form below is read by Behat 3 and 4 alike, so it is the safer file to write today:
<?php
// behat.php
use Behat\Config\Config;
use Behat\Config\Extension;
use Behat\Config\Profile;
use Behat\Config\Suite;
use Playwright\Behat\Context\PlaywrightContext;
use Playwright\Behat\ServiceContainer\PlaywrightExtension;
return (new Config())
->withProfile((new Profile('default'))
->withExtension(new Extension(PlaywrightExtension::class, [
'base_url' => 'http://localhost:8000',
]))
->withSuite((new Suite('web'))
->withPaths('%paths.base%/features')
->withContexts(PlaywrightContext::class)));
One browser, one page per scenario
The extension launches a single browser for the whole run and opens a fresh BrowserContext and page for each scenario. Scenario isolation comes from the context, not from a relaunch, so a suite pays the browser startup cost once.
Nothing in a feature file starts or stops the browser. The page opens the first time a step asks for it and closes when the scenario ends.
Configuration
| Option | Default | Effect |
|---|---|---|
browser |
chromium |
Engine to launch: chromium, firefox, or webkit |
headless |
true |
Run without a visible window |
base_url |
null |
Prefix for relative URLs in navigation steps |
timeout |
30000 |
Default timeout for actions and navigations, in milliseconds |
slow_mo |
0 |
Delay between browser operations, in milliseconds |
viewport |
1280x720 |
Viewport of every scenario page |
screenshot_dir |
%paths.base%/var/screenshots |
Where screenshots are written |
auto_screenshot_on_failure |
true |
Write failed-<scenario>-<line>.png when a scenario fails |
Built-in steps
Five patterns ship with PlaywrightContext. Selectors are Playwright selectors, so CSS works alongside text= and role=.
Given I am on "/login"
When I go to "/dashboard"
When I click on "button[type=submit]"
When I fill "#email" with "user@example.com"
Then I should see "Welcome back"
When I take a screenshot named "after login"
Then I should see matches the page HTML, so text broken across markup does not match. When a step fails, the exception is Playwright\Behat\Exception\ExpectationFailedException, or a Playwright PHP timeout when the element never became actionable.
Custom steps
Anything beyond those five patterns belongs in a project context. Extend RawPlaywrightContext and use the Page directly:
use Behat\Step\When;
use Playwright\Behat\Context\RawPlaywrightContext;
final class AdminContext extends RawPlaywrightContext
{
#[When('I sign in as an administrator')]
public function signInAsAdministrator(): void
{
$page = $this->getPage();
$page->goto('/admin/login');
$page->locator('#username')->fill('admin');
$page->locator('#password')->fill('secret');
$page->locator('[type="submit"]')->click();
}
}
getPage() returns the page of the current scenario, opening it on first call. A context that already extends another class can implement PlaywrightAwareContext instead and receive the shared PlaywrightManager.
In CI
Install browsers before running Behat, then upload the failure screenshots as artifacts. The GitHub Actions setup page covers the install step; point the artifact path at the screenshot_dir you configured.
Choosing this over Mink
Both run Behat suites on Playwright browsers. The difference is what your suite already depends on.
| You have | Use |
|---|---|
| Hundreds of Mink steps and page objects | Mink driver, which keeps the Session API |
| Feature files but no Mink, or a new suite | This extension, which exposes Playwright directly |
| Browser tests owned by developers, no Gherkin readers | PHPUnit with Playwright PHP, no bridge at all |
Go next
- Package metadata and versions: Playwright Behat
- Browser and context model: Browser and contexts
- Selector strategy: Locators