PHP Machinist Presentation


Published on

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.

Published in: Technology
1 Like
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

PHP Machinist Presentation

  1. 1. PHP Machinist Testing Object Factory
  2. 2. Primary ContributorsStephan Soileau Adam Englander● Former Employee ● Selling Source Employee● Current lead developer on ● Current lead developer for CMG Cassandra 3.0 ● Famously rode on the shirt tails● Testing evangelist and BDD guru of Stephan to BDD fame and glory
  3. 3. 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
  4. 4. Connecting to Your DataPHP Machinist provides a standard interfacewith the following provided implementations:● PDO ○ SQLite ○ MySQL● Doctrine ORM● Experimental NoSQL available in doctrine- mongodb branch ● Doctrine MongoDB ● MongoDB
  5. 5. Connection Example: PDO SQLiteEasy way:$pdo = new PDO("sqlite::memory:");machinistMachinist::Store(SqlStore::fromPdo($pdo));Hard way:$pdo = new PDO("sqlite::memory:");$store = new machinistdriverSqlite($pdo);machinistMachinist::Store($store);
  6. 6. Blueprints Define Data StructuresBlueprints define the data structure by:● Defining tables with aliases● Define default values● Define relationships● Useable in PHPUnit tests and Behat context
  7. 7. 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" columnin the "stuff" table. If foreign method is not called, the primary key for theforeign key is assumed.Machinist::Blueprint("crayon", "stuff" array( "name" => "crayon", "box" => Machinist::Relationship($cbBox)->local("box_id"), ));
  8. 8. 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.
  9. 9. 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");
  10. 10. 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")));
  11. 11. find() Retrieves Data dataFind finds all rows by criteria.FindOne finds one row by criteriaFindOrCreate finds one row by criteria orcreates a row using the criteria as data.Find retrieves data by:● Primary key● Column/Value array● Foreign key relationship dataFind populates relationship data if relationaldata exists.Machine objects are returned by Find*
  12. 12. 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",...),...))
  13. 13. 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
  14. 14. wipe() ExamplesTruncate the "crayon" blueprints tablemachinistMachinist::wipe("crayon", true);machinistMachinist::Blueprint("crayon", true);Truncate all blueprints tables but the "cbBox" blueprintstablemachinistMachinist::wipe(null, true, array("cbBox"));machinistMachinist::instance()->wipe(true, array("cbBox"));
  15. 15. Behat UsagePHP Machinist is designed to be utilized withinBehat 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
  16. 16. 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 machinistbehatMachinistContext($config); $this->useContext(machinist, $this->getMachinistContext()); }
  17. 17. Behat ExampleFeature: Cardboard Box As a crayon I should be able to have a cardboard boxBackground: 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