rmb32 / scenario-runner
A small, generic Given/When/Then scenario execution engine โ Act/Arrange/Assert/Authenticate ports, no framework or transport opinions
Requires
- php: ^8.5
- ext-dom: *
- ext-ds: ^2.0
- php-ds/php-ds: ^2.0
Requires (Dev)
- deptrac/deptrac: ^4.7
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^12.0
- squizlabs/php_codesniffer: ^4.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-07 18:34:49 UTC
README
Part of BarnSuite.
A small, generic Given/When/Then execution engine. Describe your acceptance scenarios as plain data โ areas of business, roles, stories, scenarios that arrange some facts, perform one action and assert some facts โ and Scenario Runner runs them and reports exactly what passed and failed. It has no framework, storage or transport opinions and knows nothing about Barnspec: you supply the domain logic by implementing a few interfaces.
To run scenarios you captured in Barnspec, use Scenario Bridge.
Requirements
- PHP 8.5+,
ext-dom
Installation
composer require rmb32/scenario-runner
The ports you implement
| Port | Does |
|---|---|
Arrange | sets up one given fact's state |
Assert | answers whether one then fact now holds |
Act | performs the action, returns the actual outcome (Accepted / Rejected) |
Authenticate | establishes a role as the one performing a story |
ReadStorage / WriteStorage | the one piece of state Scenario Runner itself touches |
Each fact, action and role in your data names its own handler class. By default
it is built with new $className(). Give the builder a PortFactory to build
them any other way, such as from your application's container:
$tester = new AreaOfBusinessTesterBuilder(
ports: new ContainerPorts(), // implements PortFactory
storages: new MyStorageFactory(), // implements StorageFactory
)->build();
- With a
StorageFactory, every Scenario runs in a storage of its own, so the order Scenarios run in never matters. - A role is authenticated at the start of every Scenario it performs.
- A
PortFactorythat also implementsBeforeEachScenariois told before each Scenario begins: the place to empty a test database. - A Port that throws fails only its own Scenario. It is reported as crashed, with
where and why (
๐ฅ โฆ the Scenario crashed in Given: RuntimeException: โฆ), and every other Scenario still runs. - A Given or Then may use the same fact more than once, with different arguments; each use runs, in order.
Port Generator writes stubs for all of these from your captured Barnspec vocabulary.
Running scenarios
use Rmb32\ScenarioRunner\Api\Factory\AreaOfBusinessTesterBuilder;
use Rmb32\ScenarioRunner\Api\ValueObject\CliTestMessageFormatter;
$tester = new AreaOfBusinessTesterBuilder()->build();
$result = $tester->test($areaOfBusinessData, $storage, $storage);
$result->passed(); // bool
$formatter = new CliTestMessageFormatter();
echo $result->message($formatter); // coloured pass/fail report
$areaOfBusinessData is built from the AreaOfBusinessData /
RoleData / StoryData / ScenarioData value objects; $storage implements
both ReadStorage and WriteStorage.
Reporting
CliTestMessageFormatterโ ANSI-coloured terminal output.XmlTestReportโ a JUnit-style XML report most CI systems display natively.- Observer targets (
CliPrintTarget,SummaryTarget,XmlExportTarget,NdjsonExportTarget,CsvExportTarget) with filters (FailuresOnlyFilter,PassesOnlyFilter,RoleFilter,StoryFilter,ScenarioFilter) let you send the same result to several places, each with its own view. ImplementOutputSinkto send output somewhere new.
Scaffolding unit tests
The optional scenario-runner command creates an empty PHPUnit test for a Work
ticket. It lives in scenario-runner-cli.
Related packages
- Scenario Bridge โ feeds it Scenarios captured in Barnspec.
- Port Generator โ generates the ports.
- Scenario Runner CLI โ unit-test scaffolding wizard.
- Barnspec โ where stories are captured.
More docs
License
Proprietary. See LICENSE. Copyright (c) Roger Barnfather.