Skip to content
Pest Flow
Esc
↑↓navigate↵open⌘Jpreview
On this page

Quickstart

Install Pest Flow and run your first behaviour scenario with Pest.

This guide installs Pest Flow from Packagist, adds one feature test, and runs it with Pest. It assumes you already have a PHP project with Composer and Pest 5 installed.

Requirements

  • PHP 8.4 or newer
  • Pest 5
  • Composer

Install

Run this command from your application directory:

composer require --dev maxiviper117/pest-flow

Composer installs Pest Flow as a development dependency and loads its DSL functions automatically. You do not need to add a Pest plugin bootstrap file.

Write your first scenario

Create tests/Feature/CheckoutFlowTest.php:

<?php

use function Pest\Flow\{feature, rule, scenario, given, when, then};

feature('Checkout', function (): void {
    rule('Discounts reduce the order total', function (): void {
        scenario('Applies a fixed discount', function (): void {
            given('an order worth 120 dollars', function (): void {
                $this->subtotal = 120;
            });

            when('a discount of 12 dollars is applied', function (): void {
                $this->total = $this->subtotal - 12;
            });

            then('the total is 108 dollars', function (): void {
                expect($this->total)->toBe(108);
            });
        });
    });
});

The nesting gives the test a clear business context:

  • feature() groups tests for a capability.
  • rule() groups scenarios that express a business rule.
  • scenario() registers a normal Pest test.
  • given(), when(), and then() run their closures in declaration order inside that test.

The closures share Pest’s test object. In this example, $this->subtotal set in Given is available in the later steps. Use non-static closures when accessing $this.

Run the test

vendor/bin/pest tests/Feature/CheckoutFlowTest.php

Pest reports the scenario like any other test. Assertions, lifecycle hooks, and test failures continue to use Pest’s normal behavior.

To print the Feature, Rule, Scenario, and step hierarchy after the normal Pest output, add --flow:

vendor/bin/pest --flow tests/Feature/CheckoutFlowTest.php

Status symbols are colored when the terminal supports it. Color is disabled automatically when output is redirected.

Export behavior as JSON

To send a JSON document to stdout, add --flow-json. Pest suppresses its normal output in this mode so stdout contains only JSON:

vendor/bin/pest --flow-json tests/Feature/CheckoutFlowTest.php

To save the document to a file and keep Pest’s normal output, pass a file name:

vendor/bin/pest --flow-json=flow.json tests/Feature/CheckoutFlowTest.php

The document includes a schema version, the feature and rule hierarchy, standalone scenarios, source locations, execution statuses, durations, and tags declared on each node. See the JSON export reference for the complete schema.

Tag and filter behaviours

Add tags directly to features, rules, or scenarios:

feature('Checkout', function (): void {
    rule('Payment', function (): void {
        scenario('charges a customer', function (): void {
            // Given / When / Then steps...
        })->tags('payments', 'critical');
    })->tags('billing');
})->tags('checkout');

Feature and rule tags are inherited by descendant scenarios for filtering. Pest Flow uses Pest groups, so select tagged scenarios with the existing --group option:

vendor/bin/pest --group=payments

Each node’s JSON tags array contains only tags declared directly on that node. See tags and filtering for validation rules and more examples.

Generate living documentation

After a Pest run, generate a static HTML behaviour catalogue with:

vendor/bin/pest --flow-report

Pest writes build/pest-flow/index.html. Pass a directory to use another output location:

vendor/bin/pest --flow-report=docs/behaviour

The report includes navigation, counts, direct tags, source locations, and execution metadata. Unselected scenarios in a filtered run remain listed as pending. Their steps may be absent because Pest Flow records steps when a scenario runs. See living documentation for output details and the parallel execution limitation.

If something does not work

  • A DSL function is undefined: check the use function Pest\Flow\... import and run composer install after adding the dependency.
  • Composer cannot find the package: check that the VCS repository was added to the application root and that PHP and Pest meet the requirements.
  • A rule() call is rejected: place it inside feature().
  • A step is rejected: call it inside a scenario() definition, not directly in the test file or a feature callback.

See troubleshooting for the complete list of placement rules and errors. Continue with the first scenario walkthrough for a full example, or the DSL reference for every function.

Was this page helpful?