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.
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.
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.
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.
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:
/path/to/fixtures/shops
- as User
s has dependencies on Shop
s/path/to/unittest/fixtures/users.json
- as the unit test has specific User
fixtures./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.
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');
Some ideas for the futre in no particular order: