innmind/black-box-symfony

Extension to test Symfony apps via BlackBox

1.2.0 2023-12-02 10:53 UTC

This package is auto-updated.

Last update: 2024-03-31 11:43:15 UTC


README

Build Status Type Coverage

This package is an extension of innmind/black-box to help test Symfony applications.

Installation

composer require innmind/black-box-symfony

Usage

use Innmind\BlackBox\{
    Runner\Assert,
    Symfony\Application,
};

return static function() {
    yield test(
        'Login',
        function(Assert $assert) {
            $app = Application::new($assert); // This assumes the kernel class is 'App\Kernel'
            $response = $app
                ->json()
                ->post('/login', [
                    'username' => 'john',
                    'password' => 'doe',
                ]);
            $response
                ->statusCode()
                ->is(200);

            $content = $response->body()->json();
            $assert
                ->array($content)
                ->hasKey('token');
            $token = $content['token'];

            $app
                ->get('/me')
                ->statusCode()
                ->is(200);
        },
    );
};

Model Based Testing

By representing the application as a standalone object we can consider it as a system to test and so test it via properties.

use Innmind\BlackBox\{
    Set,
    Property,
    Runner\Assert,
    Symfony\Application,
};

/**
 * @implements Property<Application>
 */
final class Login implements Property
{
    public static function any(): Set
    {
        return Set\Elements::of(new self);
    }

    public function applicableTo(object $app): bool
    {
        return true;
    }

    public function ensureHeldBy(Assert $assert, object $app): object
    {
        response = $app
            ->json()
            ->post('/login', [
                'username' => 'john',
                'password' => 'doe',
            ]);
        $response
            ->statusCode()
            ->is(200);

        $content = $response->body()->json();
        $assert
            ->array($content)
            ->hasKey('token');
        $token = $content['token'];

        $app
            ->get('/me')
            ->statusCode()
            ->is(200);

        return $app;
    }
}

And you would run it via:

use Innmind\BlackBox\{
    Set,
    Properties,
    Runner\Assert,
    Symfony\Application,
};

return static function() {
    yield proof(
        'Login',
        given(Login::any()),
        function(Assert $assert, Login $login) {
            $app = Application::new($assert);

            $login->ensureHeldBy($assert, $app);
        },
    );
    // and you can even test a sequence of properties to simulate a user actions
    yield proof(
        'No user interaction should crash the app',
        given(Set\Properties::any(
            Login::any(),
            AnotherProperty::any(),
            // etc...
        )),
        function(Assert $assert, Properties $properties) {
            $app = Application::new($assert);

            $properties->ensureHeldBy($assert, $app);
        },
    );
}

PHPUnit emulation

BlackBox is able to run PHPUnit tests and this extension allows to run functional tests. For this to work you only need to prefix the Symfony\Bundle\FrameworkBundle\Test\WebTestCase by Innmind\BlackBox\.

And the file to run BlackBox would look like:

<?php
declare(strict_types = 1);

require 'vendor/autoload.php';

use Innmind\BlackBox\Application;
use Innmind\BlackBox\PHPUnit\Load;
use Symfony\Component\Dotenv\Dotenv;

(new Dotenv())->bootEnv('.env', 'test');

Application::new($argv)
    ->disableMemoryLimit()
    ->scenariiPerProof(1)
    ->tryToProve(Load::directory('tests/'))
    ->exit();

Warning: custom assertions provided by Symfony are not supported.