lapaz/quick-brown-fox

ORM independent RDB fixture data generator

0.3.1 2023-12-20 14:40 UTC

This package is auto-updated.

Last update: 2024-04-20 15:21:20 UTC


README

PHP Composer

ORM independent RDB fixture data generator.

Usage

Define some common rules while building bootstrap environment for your tests:

// $container points some application scope service locator
$container->set(\Lapaz\QuickBrownFox\Database\SessionManager::class, function() use ($container) {
    $fixtures = new \Lapaz\QuickBrownFox\FixtureManager();
    
    $fixtures->table('authors', function ($td) {
        $td->fixture('GoF')->define([
            [ 'name' => "Erich Gamma" ],
            [ 'name' => "Richard Helm" ],
            [ 'name' => "Ralph Johnson" ],
            [ 'name' => "John Vlissides" ],
        ]);
    });
    
    $fixtures->table('books', function ($td) {
        $td->generator('DesignPattern-N')->define(function($i) {
            return [
                'title' => 'Design Pattern ' . ($i + 1),
                'code' => sprintf('000-000-%03d', $i),
                // not needed: 'author_id' => ?
            ];
        });
    });
    
    // 'database' must be DBAL connection or PDO
    return $fixtures->createSessionManager($container->get('database'));
});

Prepare new test session:

use PHPUnit\Framework\TestCase;

class BookRepositoryTest extends TestCase
{
    protected $session;
    
    protected function setUp()
    {
        /** @var ContainerInterface $container */
        $this->session = $container->get(\Lapaz\QuickBrownFox\Database\SessionManager::class)->newSession();
    }
}

Add tests using predefined fixtures and generators:

    public function testFindBook()
    {
        $this->session->into('authors')->load('GoF');
        $this->session->into('books')->with('DesignPattern-N')->generate(10);
        
        $books = (new BookRepository($this->connection))->findAll();
        $this->assertCount(10, $books);
        $this->assertEquals("Design Pattern 1", $book[0]->getTitle());
        
        $this->assertNotNull($book[0]->getAuthor());
    }

NOTE: Non-null foreign key constraints are randomly resolved if not present.

You can use inline fixture instead of predefined one:

        $this->session->into('authors')->load([
            [ 'name' => "Erich Gamma" ],
            [ 'name' => "Richard Helm" ],
            [ 'name' => "Ralph Johnson" ],
            [ 'name' => "John Vlissides" ],
        ]);

And inline generator:

        $this->session->into('books')->with(function($i) {
            return [
                'title' => 'Design Pattern ' . ($i + 1),
                'code' => sprintf('000-000-%03d', $i),
            ];
        })->generate(10);

Common attributes can be set for array form fixture data.

        $this->session->into('authors')->with([
            'specialist' => true,
            'rating' => function($i) { return 80 + $i * 5; },
        ])->load([
            [ 'name' => "Erich Gamma" ],
            [ 'name' => "Richard Helm" ],
            [ 'name' => "Ralph Johnson" ],
            [ 'name' => "John Vlissides" ],
        ]);

You can append extra data repeatedly within a session. These are deleted automatically when the next session would use the same table.

        $this->session->into('authors')->with([
            'specialist' => false,
            'rating' => function() { return mt_rand(30, 50); },
        ])->generate(6));

        $this->session->into('authors')->with([
            'specialist' => false,
            'rating' => function() { return mt_rand(30, 50); },
        ])->generate(6));

Attributes are overridden by right one over left one. Overridden function are not evaluated, so unnecessary slow calculations are not called.

        $this->session->into('books')->with('DesignPattern-N')->with([
            'title' => function($i) {
                return 'Design Pattern -2nd Edition- ' . ($i + 1);
            },
        ])->generate(10);

If you don't care each attributes, you can do simply:

        $this->session->into('books')->generate(100);

But when there might be some property constraint, you can define table level generator rule:

    $fixtures->table('books', function ($td) {
        $td->defaults([
            'type' => function() {
                return mt_rand(1, 3); // books.type must be 1, 2 or 3
            }
        ]);
    });