Phabric
A DB mockup / fixture creation library for Behat
Install / Use
/learn @woledzki/PhabricREADME
Phabric
A tool that translates Gherkin Tables into database inserts / updates.
It's for use with the BDD library Behat which can be found at: http://behat.org/
The aim of this project is to allow the user to define fixtures 'on the fly' using Gherkin tables without having to undergo the painful process of maintaining an SQL file used to drive Behat test suites.
Introduction
When adopting Behat at the company I work for we quickly found that in order to write clear tests we needed to set the state of the database in scenarios rather than in monolithic fixture files.
Problems with fixture files:
- They are difficult to maintain
- It's easy to wreck an existing test by modifying it's data in the fixture
- The semantics of the data are lost in the fixture file rather than being explicitly stated in a scenario.
The solution we settled on was to load an initial fixture containing just the basic DB structure and to define all the data in Gherkin tables within the scenarios of our test.
Enter Phabric...
Phabric
Phabric allows the user to mark up data for insertion into the database in a scenario. Like So:
Given The following events exist
| Name | Date | Venue | Desc |
| PHPNW | 08/10/2011 09:00 | Ramada Hotel | An awesome conf! |
| PHPUK | 27/02/2012 09:00 | London Business Center | Quite good conf. |
To make the data as readable as possible Phabric supports the following:
Column Name Transformations - You can map the name of a column in Gherkin to a database column name. EG Desc > conf_description
Column Data Transformations - You can translate the data in the column by registering functions. EG 08/10/2011 09:00 > 2011-10-08 09:00:00
Default Values - You can assign default values to columns so you do not have to explicitly include them in the gherkin.
Relational data is supported. EG An Event with many Attendees
The aim of these features is to assist the user in setting up a scenario in a readable and maintainable way. It should facilitate behaviour driven development as once the initial creator steps have been setup anyone will be able to mark up entities in your system (testers and BAs included!).
Preview
The documentation below outlines how to configure and use Phabric. Here is a quick preview of whats achievable when Phabric is installed, configured and running:
The scenario:
Scenario:
Given The following events exist
| Name | Date | Venue | Desc |
| PHPNW | 08/10/2011 09:00 | Ramada Hotel | An awesome conf! |
| PHPUK | 27/02/2012 09:00 | London Business Center | Quite good conf. |
Note: The example contains name and data transformations.
The step:
<?php
/**
* @Given /^The following events exist$/
*/
public function theFollowingEventsExist(TableNode $table) {
$this->phabric->insertFromTable('event', $table);
}
The database table after data creation:
<pre> | name | datetime | venue | description | | PHPNW | 2011-10-08 09:00:00 | Ramada Hotel | An awesome conf! | | PHPUK | 2012-02-27 09:00:00 | London Business Center | Quite good conf. | </pre>Note: Gherkin column names are mapped to database column names and some data (datetime) is transformed.
For those keen on doing rather than reading there are working examples in the 'examples' folder. See section below for instructions on setting up the examples.
DOCS
Install
Currently the only supported method of installing Phabric is via git.
Clone the git hub repository onto your local machine.
- git clone git@github.com:benwaine/Phabric.git
Change directory into the newley cloned repository.
- cd Phabric/
Phabric has a number of dependencies these can be met by initializing the following submodules:
- git submodule init lib/Vendor/mockery/
- git submodule init lib/Vendor/Doctrine/
- git submodule update --recursive
Then Doctrines submodules
-
cd lib/Vendor/Doctrine/
-
git submodule init lib/vendor/doctrine-common/
-
git submodule update --recursive
Setting Up Phabric
Phabric requires some setting up in the main feature context file of your behat tests folder.
Phabric requires a datasource to persist Gherkin tables to. Usually this is a relational database. Phabric ships with a Doctrine DBAL adapter. This allows support for many databases 'out of the box'. Most popular databases are supported including MySQL, Oracle and MSSQL.
If you wish to support non relational databases or databases that Donctrine does not support you can do so by writting an adapter and implementing Phabrics 'IDatasource' interface.
Autoloading Classes are loaded using the Doctrine Project autoloader.
Doctrine and Phabric Classes need to be registered with the auto loader in the Feature Context File:
<?php
require_once __DIR__ . '/PATH/TO/PHABRIC/lib/Vendor/Doctrine/lib/vendor/doctrine-common/lib/Doctrine/Common/ClassLoader.php';
$phaLoader = new \Doctrine\Common\ClassLoader('Phabric', realpath(__DIR__ . '/../../../lib/'));
$phaLoader->register();
$docLoader = new \Doctrine\Common\ClassLoader('Doctrine\DBAL', __DIR__ . '/../../../lib/Vendor/Doctrine/lib');
$docLoader->register();
$docComLoader = new \Doctrine\Common\ClassLoader('Doctrine\Common', __DIR__ . '/../../../lib/Vendor/Doctrine/lib/vendor/doctrine-common/lib');
$docComLoader->register();
/**
* Features context.
*/
class FeatureContext extends BehatContext {
public function __construct(array $parameters) {
}
// Rest of feature file....
A Doctrine DBAL connection (database connection class) needs to be created and injected into a Phabric datasource object, this class manages interactions with the datasource. Database connection parameters should be added to your behat.yml config file. Also some basic meta data is input about the 'entities' we wish to map. An entity is a Gherkin to DB table mapping, this is discussed further in later sections.
default:
context:
class: 'FeatureContext'
parameters:
database:
username: 'root'
password: ''
dbname: 'behat-demo'
host: '127.0.0.1'
driver: 'pdo_mysql'
Phabric:
entities:
event:
tableName: 'event'
primaryKey: 'id'
nameCol: 'name'
session:
tableName: 'session'
primaryKey: 'id'
nameCol: 'session_code'
attendee:
tableName: 'attendee'
primaryKey: 'id'
nameCol: 'name'
vote:
tableName: 'vote'
primaryKey: 'id'
nameCol: null
NB Note that some basic table meta data is required in the Phabric section of the behat.yml file. tableName, primaryKey and nameCol.
- tableName: The name of the table to be mapped e.g. 'event'
- primaryKey: the name of the primary key column e.g. 'id'
- nameCol: this is a column used to identify a piece of data inserted by phabric. It can be any column in the database but should be unique. eg 'PHPNW'
Creating the DBAL Connections and setting it as the database connection used by Phabric:
<?php
protected $phabric;
public function __construct(array $parameters) {
$config = new \Doctrine\DBAL\Configuration();
self::$db = \Doctrine\DBAL\DriverManager::getConnection(array(
'dbname' => $parameters['database']['dbname'],
'user' => $parameters['database']['username'],
'password' => $parameters['database']['password'],
'host' => $parameters['database']['host'],
'driver' => $parameters['database']['driver'],
));
$datasource = new \Phabric\Datasource\Doctrine(self::$db, $parameters['Phabric']['entities']);
$this->phabric = new Phabric\Phabric($datasource);
}
This should be all the setup required to use Phabric. We can now define Phabric entities, these represent the mapping between Gherkin tables of data and data in our database.
The Phabric Class
The Phabric object handles interaction with all the 'entities' (Gherkin table > db table mappings) created when using Phabric. It accepts a datasource as it's only argument. It should be created in the constructor of the FeatureContext class and saved to a member variable (as in the example above).
Phabric Entities
A Phabric entity encapsulates the mapping between a Gherkin table and a database table.
There are two ways to configure a Phabric entity: Programmatically and by using a Configuration file. This documentation will show both methods. Those who prefer cleaner feature files with less set up should consider using the configuration based approach.
Programmatically:
<?php
// Note: no second config parameter passed
$event = $this->phabric->createEntity('event');
$event->setTableName('event');
// @todo more entity config. @see The Docs bellow
And Using configuration:
<?php
// Note: The config array is pulled from the $parameters argument passed
// into the FeatureContext constructor method.
$this->phabric->createEntity('event', $parameters['Phabric']['entities']['event']);
General Principles
- The Phabric object is set up in the FeatureContext constructor.
- Phabric entities are created via the Phabric class and configured in the FeatureContext constructor.
- Entities are retrieved in step definitions and are used to insert and update data specified in Gherkin tables in the scenario.
