mblarsen / fFixture

Provides an easy way of creating sample data (fixtures) for unit testing using Flourish.
http://mblarsen.github.com/fFixture
2 stars 0 forks source link

fFixture Introduction Build Status

fFixture provides an easy way of creating sample data (fixtures) for unit testing using Flourish.

It recursively creates records based on JSON fixture files that you provide. By default it will create records for all fixture files it finds, but you can specify to use only selected fixtures.

Usage

Create JSON fixture files like this users.json:

[
    {
        user_id: 1,
        name: "Will Bond",
        contribution: "Creator of Flourish"
    }
]

Create a fixture instance:

fFixture::setDatabase($db);
$fixture = fFixture::create('/path/to/fixtures/');

$fixture->build();

Use your newly created objects:

$user = new User(1);
echo $user->getName() // outputs: Will Bond

Bring everything down again:

$fixture->tearDown();

That's pretty much it. Check the unit tests in /tests for a working example.

Fixture files

The fixture files contains an array of JSON literals. Like this members.json:

[
    {
        "name":"Michael",
        "country":"Nepal",
        "member_since":"2009-05-23"
    }
]

Though JSON, the files will first be evaluated as PHP scripts, so you can included <?php echo data('Y-m-d H:i:s); ?> into you JSON files.

[
    {
        "name":"Michael",
        "country":"Nepal",
        "member_since":"<?php echo data('Y-m-d); ?>"
    }
]

You could also go crazy building all the objects from PHP.

Named keys

Some times you want to build more complex fixtures for you tests. In these cases named keys can be helpful. This example shows the relationship between Shop and Product. First the shops.json

[
    {
        "name": "Amazon",
        "shop_id": <?php echo $fixture->key('amazon', 1); ?>
        "url": "http://amazon.com"
    }
]

and the products.json:

[
    {
        "name": "The Dick Van Dyke Show",
        "shop_id": <?php echo $fixture->key('amazon'); ?>,
        "price": 66.99
    }
]

In this way you don't have to bother getting with getting the IDs right.

Unit tests

The whole idea of this class was to ease the creating an maintanance of unit tests. Here is a simple example of how to setup and tear down the fixtures.

The setup, in this case run after each test:

public function setUp()
{
    $db = fORMDatabase::retrieve();
    fFixture::setDatabase($db);
    $this->fixture = fFixture::create('/path/to/fixtures/', array("users", "marketplaces"));
    $this->fixture->build();
}

.. and the tear down:

public function tearDown()
{
    $this->fixture->tearDown();
}

The fixtures root will typically contain lots of fixtures that can be or is need for several tests. But sometimes you cannot rely on this random data. Maybe you need to know that you have exactly three products or an record with a specific value. In this case you can specify a third parameter - replacments root. Basically when loading the fixtures the fixtures of the replacments root will be used in favor of those in the root directory.

In this case these special user objects are placed along with the unit test itself:

public function setUp()
{
    $db = fORMDatabase::retrieve();
    fFixture::setDatabase($db);
    $this->fixture = fFixture::create('/path/to/fixtures/', array("users", "marketplaces"), '/path/to/unittest/fixtures/');
    $this->fixture->build();
}

Assume that /path/to/fixtures/ contains the following:

./users.json
./shops.json
./marketplaces.json

and that /path/to/unittest/fixtures/ contains the following:

./users.json

Then the build order of the fixtures will be:

  1. /path/to/fixtures/shops - as Users has dependencies on Shops
  2. /path/to/unittest/fixtures/users.json - as the unit test has specific User fixtures.
  3. /path/to/fixtures/marketplaces.json - these are specifed as well but there are no unit test specific versions of these fixtures.

This allows for some flexibility. But note the possibility of failure in case the root fixtures are dependent on a type of fixture that has been overwritten by the unit test fixtures or vice versa.

Namespaces

If you use namespaces, either make sure that you have included the name spaced classes before running fFixture::create(). Alternativly you can use the fORM::mapClassToTable() method:

fORM::mapClassToTable('My\Namespaced\Class', 'classes');

Limitations

Future

Some ideas for the futre in no particular order: