Fixture
A framework agnostic, simple (yet elegant) fixture library for php.
Install / Use
/learn @CodeSleeve/FixtureREADME
A framework agnostic, simple (yet elegant) fixture library for php.
Fixture was created by Travis Bennett.
Requirements
- php >= 5.3
- A PDO object instance for database connections.
- Database table primary keys should have a column name of 'id'.
- Database table foreign keys should be composed of the singularized name of the associated table along with an appended '_id' suffix (e.g blog_id would be the foreign key name for a table named blogs).
Installation
Fixture is distributed as a composer package, which is how it should be used in your app.
Install the package using Composer. Edit your project's composer.json file to require codesleeve/fixture.
"require": {
"codesleeve/fixture": "dev-master"
}
Overview
In order to create good tests for database specific application logic, it's often necessary to seed a test database with dummy data before tests are ran. This package allows you to achieve this through the use of database fixtures (fixtures are just another way of saying 'test data'). Fixtures can be created using native php array syntax and are not dependendent on any specific relational DBMS. In a nutshell, this package allows you to turn this:
class fooTest extends PHPUnit_Framework_TestCase
{
/**
* A PDO connection instance.
*
* @var PDO
*/
protected $db;
/**
* Initialize our test state.
*
* @return void
*/
public function setUp()
{
// create a pdo instance
if (!$this->db) {
$this->db = new PDO('sqlite::memory:');
}
// populate the users table
$sql = 'INSERT INTO users (email, password, status, created_at, updated_at) values (?, ?, ?, ?, ?)';
$sth = $this->prepare($sql);
$sth->execute(array('john@doe.com', 'abc12345$%^', 1, date('Y-m-d'), date('Y-m-d')));
$sql = 'INSERT INTO users (email, password, status, created_at, updated_at) values (?, ?, ?, ?, ?)';
$sth = $this->prepare($sql);
$sth->execute(array('Jane', 'Doe', 'jane@doe.com', 1, 'abc12345$%^', date('Y-m-d'), date('Y-m-d')));
$sql = 'INSERT INTO users (email, password, status, created_at, updated_at) values (?, ?, ?, ?, ?)';
$sth = $this->prepare($sql);
$sth->execute(array('Jim', 'Doe', 'jim@doe.com', 0, 'abc12345$%^', date('Y-m-d'), date('Y-m-d')));
// populate the roles table
$sql = 'INSERT INTO roles (name, created_at, updated_at) values (?, ?, ?)';
$sth = $this->prepare($sql);
$sth->execute(array('admin', date('Y-m-d'), date('Y-m-d')));
$sql = 'INSERT INTO roles (name, created_at, updated_at) values (?, ?, ?)';
$sth = $this->prepare($sql);
$sth->execute(array('user', date('Y-m-d'), date('Y-m-d')));
// populate the roles_users table
$sql = 'INSERT INTO roles_users (role_id, user_id) values (?, ?)';
$sth = $this->prepare($sql);
$sth->execute(array(1, 1));
$sql = 'INSERT INTO roles_users (role_id, user_id) values (?, ?)';
$sth = $this->prepare($sql);
$sth->execute(array(1, 2));
$sql = 'INSERT INTO roles_users (role_id, user_id) values (?, ?)';
$sth = $this->prepare($sql);
$sth->execute(array(2, 3));
}
/**
* Reset our test state.
*
* @return void
*/
public function tearDown
{
$this->db->query("TRUNCATE TABLE users");
$this->db->query("TRUNCATE TABLE roles");
$this->db->query("TRUNCATE TABLE roles_users");
}
/**
* A database integration test of some sort.
*
* @test
* @return void
*/
public function it_should_be_able_to_do_some_query()
{
// Test that some query is working correctly.
}
}
into this:
class fooTest extends PHPUnit_Framework_TestCase
{
use Codesleeve\Fixture\Fixture;
/**
* The fixture instance.
*
* @var Fixture
*/
protected $fixture;
/**
* Initialize our test state.
*
* @return void
*/
public function setUp()
{
// set the fixture instance
$this->fixture = Fixture::getInstance();
// populate our tables
$this->fixture->up();
}
/**
* Reset our test state.
*
* @return void
*/
public function tearDown
{
$this->fixture->down();
}
/**
* A database integration test of some sort.
*
* @test
* @return void
*/
public function it_should_be_able_to_do_some_query()
{
// Test that some query is working correctly.
}
}
Drivers
Fixture currently supports two drivers:
- Standard Driver - This is the most basic driver avaialble for this package. It requires no ORM and has no concept of relationships.
- Eloquent Driver - This driver allows full usage of the Eloquent ORM. When creating fixture data, eloquent relationships can be used in order to easily manage foreign keys among fixture data.
Setup
In order to use fixture, you're going to first need to initialize it. A good place to do this is inside your bootstrap file (configured via your phpunit.xml), but you're certainly welcome to do this where it makes the most sense for you:
// Create a pdo instance (this may already exist in your app)
$db = new \PDO('sqlite::memory:');
// Use the pdo instance to create a new driver instance
$driver = new Codesleeve\Fixture\Drivers\Standard($db);
// Create a configuration array.
$config = array(
'location' => 'path/to/your/fixtures.php' // The directory you wish to load fixture files from.
);
// Fixture implements a singleton pattern.
// Get an instance of Fixture and set the config and driver.
$fixture = Fixture::getInstance();
$fixture->setConfig($config);
$fixture->setDriver($driver);
// Alternatively, you could do this in one swoop.
$fixture = Fixture::getInstance($config, $driver);
Examples
For our examples, let's assume that we have the following bleach-themed system:
- Tables:
- soul_reapers
- zanpakutos
- ranks
- ranks_soul_reapers (columns: integer rank_id, integer soul_reaper_id, integer status).
- Relationships:
- A soul reaper has one zanpakuto, belongs to many ranks (many to many).
- A zanpakuto belongs to one soul reaper only.
- A rank belongs to many soul reapers.
Standard Driver
Step 1 - Fixture setup
Inside your application test folder, create a folder named fixtures. Next, create a couple of fixture files inside this folder. Fixture files are written using native php array syntax. To create one, simply create a new file named after the table that the fixture corresponds to and have it return an array of data. As an example of this, let's create some fixture data for our 'soul_reapers' table:
in tests/fixtures/soul_reapers.php
return array (
'Ichigo' => array (
'first_name' => 'Ichigo',
'last_name' => 'Kurosaki'
),
'Renji' => array (
'first_name' => 'Renji',
'last_name' => 'Abarai'
),
'Genryusai' => array(
'first_name' => 'Genryusai',
'last_name' => 'Yammamoto'
)
);
Here we're simple returning a nested array containing our fixture data. Notice that there are two fixtures and that they each have a unique name (this is very important as you'll see shortly we can easily reference loaded fixture data from within our tests). Now, we can't have soul reapers without zanpakutos, so let's seed our zanpakutos table with the following fixture:
in tests/fixtures/zanpakutos.php
return array (
'Zangetsu' => array (
'soul_reaper_id' => 'Ichigo',
'name' => 'Zangetsu',
),
'Zabimaru' => array (
'soul_reaper_id' => 'Renji',
'name' => 'Zabimaru',
),
'Ryujin Jakka' => array(
'soul_reaper_id' => 'Genryusai',
'name' => 'Ryujin Jakka',
)
);
Because a zanpakuto must belong to a soul reaper (it's part of their soul after all) we know that our 'zanpakutos' table will contain a column named 'soul_reaper_id'. In order to tie a zanpakuto to it's owner, we can simply set this foreign key to the name of the corresponding soul reaper it belongs to. There's no need to worry about specific id's, insertion order, etc. It's pretty simple. Moving forward, we've so far been able to easily express our parent/child (1 to 1) relationship between 'soul_reapers' and 'zanpakutos', but what about many to many (join table) relationships? As an example of how this might work, let's look at two more tables; 'ranks' and 'ranks_soul_reapers'. Our ranks table fixture will look like this:
in tests/fixtures/ranks.php
return array (
'Commander' => array (
'title' => 'Commander'
),
'Captain' => array (
'title' => 'Captain',
),
'Lieutenant' => array (
'title' => 'Lieutenant',
),
'Substitute' => array (
'title' => 'Substitute Shinigami',
),
);
The 'ranks_soul_reapers' (many to many) join table fixture will look like this:
in tests/fixtures/ranks_soul_reapers.php
return array (
'CommanderYammamoto' => array (
'soul_reaper_id' => 'Yammamoto',
'rank_id' => 'Commander'
),
'CaptainYammamoto' => array (
'soul_reaper_id' => 'Yammamoto',
'rank_id' => 'Captain'
),
'LieutenantAbari' => array (
'soul_reaper_id' => 'Renji',
'rank_id' => 'Lieutenant'
),
'SubstituteKurosaki' => array (
'soul_reaper_id' => 'Ichigo',
'rank_i
Related Skills
node-connect
347.6kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
108.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
347.6kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
347.6kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。





