PHP Machinist Presentation

17
PHP Machinist Testing Object Factory

description

Educational presentation on using PHP Machinist as a test object factory in PHUnit as well as a Gherkin table data fixture add-in to Behat.

Transcript of PHP Machinist Presentation

Page 1: PHP Machinist Presentation

PHP MachinistTesting Object Factory

Page 2: PHP Machinist Presentation

Primary Contributors

Stephan Soileau● Former Employee● Current lead developer on

Cassandra 3.0● Testing evangelist and BDD guru

Adam Englander● Selling Source Employee● Current lead developer for CMG● Famously rode on the shirt tails

of Stephan to BDD fame and glory

Page 3: PHP Machinist Presentation

Why PHP Machinist Was Created

● Behat, a Cucumber port is born.○ Factory Girl/Machinist port for handling relational

data as Gherkin tables is needed.● DBUnit, a PHP port of DBUnit is just as

terrible as DBUnit.○ XML data structure too verbose○ Large relational datasets are unmanageable

● Phactory is almost good enough but would not handle compound primary keys.○ Phactory blueprints are very similar but does not

handle compound keys.○ Only supports PDO data sources

Page 4: PHP Machinist Presentation

Connecting to Your Data

PHP Machinist provides a standard interface with the following provided implementations:● PDO

○ SQLite○ MySQL

● Doctrine ORM● Experimental NoSQL available in doctrine-

mongodb branch● Doctrine MongoDB● MongoDB

Page 5: PHP Machinist Presentation

Connection Example: PDO SQLite

Easy way:

$pdo = new PDO("sqlite::memory:");\machinist\Machinist::Store(SqlStore::fromPdo($pdo));

Hard way:

$pdo = new PDO("sqlite::memory:");$store = new \machinist\driver\Sqlite($pdo);\machinist\Machinist::Store($store);

Page 6: PHP Machinist Presentation

Blueprints Define Data Structures

Blueprints define the data structure by:● Defining tables with aliases● Define default values● Define relationships● Useable in PHPUnit tests and Behat context

Page 7: PHP Machinist Presentation

Blueprints ExampleCreate a blueprint called "cardboardbox" on table "box" and default the "type" to "cardboard"$cbBox = Machinist::Blueprint("cardboardbox", "box", array("type" => "cardboard"));

Create a blueprint called "plasticbox" on table "box" and default the "type" to "plastic"$plBox = Machinist::Blueprint("plasticbox", "box", array("type" => "plastic"));

Create a blueprint called "crayon" on table "stuff" with "name" defaulted to "crayon" and a relationship called box that references the the "box_id" column in the "stuff" table. If foreign method is not called, the primary key for the foreign key is assumed.Machinist::Blueprint("crayon", "stuff" array( "name" => "crayon", "box" => Machinist::Relationship($cbBox)->local("box_id"), ));

Page 8: PHP Machinist Presentation

make() Stores Data

● Make stores data in the tables.● It will use default data.● It will override the default data with data

provided in the make call.● Relationship data, if provided will be

associated or added if it does not exist.● Relationship data will use defaults for data

not provided in the make call.

Page 9: PHP Machinist Presentation

make() Example: Save Data$cbBox = Machinist::Blueprint("cardboardbox", "box", array("type" => "cardboard"));$plBox = Machinist::Blueprint("plasticbox", "box", array("type" => "plastic"));

Machinist::Blueprint("crayon", "stuff" array( "name" => "crayon" "box" => Machinist::Relationship($cbBox)->local("box_id"), ));

Make a crayon with the "name" defaulted to "crayon"Machinist::Blueprint("crayon")->make();

Make a crayon with the "name"of "red crayon" and "color" of "red"Machinist::Blueprint("crayon")->make(array(

"name" => "red crayon", "color" => "red"

);

Page 10: PHP Machinist Presentation

make() Example: Save Related Data$cbBox = Machinist::Blueprint("cardboardbox", "box", array("type" => "cardboard"));$plBox = Machinist::Blueprint("plasticbox", "box", array("type" => "plastic"));Machinist::Blueprint("crayon", "stuff" array( "name" => "crayon" "box" => Machinist::Relationship($cbBox)->local("box_id"), ));

Make a crayon with the no associated boxMachinist::Blueprint("crayon")->make();

Make a crayon with a box and create the box as none existsMachinist::Blueprint("crayon")->make(array("box" => array("type" => "new type")));

Make a new crayon with a box and use the same box as it existsMachinist::Blueprint("crayon")->make(array("box" => array("type" => "new type")));

Page 11: PHP Machinist Presentation

find() Retrieves Data dataFind finds all rows by criteria.FindOne finds one row by criteriaFindOrCreate finds one row by criteria or creates a row using the criteria as data.Find retrieves data by:● Primary key● Column/Value array● Foreign key relationship dataFind populates relationship data if relational data exists.Machine objects are returned by Find*

Page 12: PHP Machinist Presentation

find() Example$cbBox = Machinist::Blueprint("cardboardbox", "box", array("type" => "cardboard"));$plBox = Machinist::Blueprint("plasticbox", "box", array("type" => "plastic"));Machinist::Blueprint("crayon", "stuff" array( "name" => "crayon" "box" => Machinist::Relationship($cbBox)->local("box_id"), ));Machinist::Blueprint("crayon")->make();Machinist::Blueprint("crayon")->make(array("box" => array()));$boxes = Machinist::Blueprint("crayon")->find("name" => "crayon")->toArray();

Resultarray(

array("name" => "crayon", ...) ,array("name" => "crayon", "box" => array("type" => "cardboard",...),...)

)

Page 13: PHP Machinist Presentation

wipe() Cleans Up Test Data

● Wipe is available at two levels:○ Blueprints can perform a wipe to remove all data in

the related table.○ Machinist instance method can clean up data for

tables related to all defined machines.○ Machinst static method can clean up data for one or

more machines.● Wipe can delete data or truncate tables if the

Store implentation supports the feature.● Machinist level wipe can specify exclusions

as an array of blueprint names

Page 14: PHP Machinist Presentation

wipe() Examples

Truncate the "crayon" blueprint's table

machinist\Machinist::wipe("crayon", true);machinist\Machinist::Blueprint("crayon", true);

Truncate all blueprints tables but the "cbBox" blueprint's table

machinist\Machinist::wipe(null, true, array("cbBox"));machinist\Machinist::instance()->wipe(true, array("cbBox"));

Page 15: PHP Machinist Presentation

Behat Usage

PHP Machinist is designed to be utilized within Behat features with little to no additional work. It supplies:● Feature context that can be added to the

default feature context● Steps for populating data as well as

validating data● Easy Gherkin table interface

Page 16: PHP Machinist Presentation

Behat Example: Feature Contextclass FeatureContext extends BehatContext implements ClosuredContextInterface { public function __construct(array $parameters) { $config = array( "database" => array( "default" => array("dsn" => "sqlite::memory:") ) );

$context = new \machinist\behat\MachinistContext($config); $this->useContext('machinist', $this->getMachinistContext()); }

Page 17: PHP Machinist Presentation

Behat ExampleFeature: Cardboard Box As a crayon I should be able to have a cardboard box Background: Given there are no machines And the following crayons exists: | color | box | | red | type: plastic |

● Performed a wipe on all Blueprints● Performed a make on the "crayon" blueprint with the

"color" column set to red● Performed a findOrCreate on the blueprint in the "box"

association, "cbBox", with a type of plastic