Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Phactory

2,014 views

Published on

Published in: Technology
  • Be the first to comment

Phactory

  1. 1. A Database Factory for PHP http://phactory.org Chris Kite Sr. Web Engineer at Offers.com© 2009 Vertive, Inc.Proprietary and Confidential @chriskite
  2. 2. Who are we? Chris Kite » B.S. in Computer Science from UT Austin » Senior Web Engineer at Offers.com » Creator of Phactory » Likes martial arts, sushi Josh Butts » B.A. in Computer Science from UT Austin » Director of Web Development at Offers.com » Likes fast cars, plain burgers © 2009 Vertive, Inc. Proprietary and Confidential
  3. 3. Phactory: What is it?Alternative to database fixtures for unit testsDefine and create objects in codeProvides a lightweight ORMWorks with MySQL, SQLite, and MongoDB © 2009 Vertive, Inc. Proprietary and Confidential
  4. 4. Phactory is developed and used at Offers.com
  5. 5. Databases in Unit Testing © 2009 Vertive, Inc. Proprietary and Confidential
  6. 6. Database FixturesA fixture is a statically defined set of dataEach test can have its own datasetPHPUnit provides support for loading fixtures: class DatabaseTest extends PHPUnit_Extensions_Database_TestCase { protected function getConnection() { $pdo = new PDO(mysql:host=localhost;dbname=testdb, root, ); return $this->createDefaultDBConnection($pdo, testdb); } protected function getDataSet() { return $this->createFlatXMLDataSet(dirname(__FILE__)./_files/bank-account-seed.xml); } } © 2009 Vertive, Inc. Proprietary and Confidential
  7. 7. Database Fixtures<?xml version="1.0" encoding="UTF-8" ?><dataset> <post post_id="1" title="My First Post" date_created="2008-12-01 12:30:29" contents="This is my first post" rating="5" /> <post post_id="2" title="My Second Post" date_created="2008-12-04 15:35:25" contents="This is my second post" /></dataset> Vertive, Inc. © 2009 Proprietary and Confidential Example from http://www.phpunit.de/manual/current/en/database.html
  8. 8. Database FixturesDrawbacks: » Typically in an unfriendly format like XML » You are left to your own devices to retrieve and manipulate data in your test » Can’t dynamically create objects » No concept of associations © 2009 Vertive, Inc. Proprietary and Confidential
  9. 9. Database FactoriesDefine database test data in code, not flat filesCreate objects dynamically, rather than loading them all at onceDefine associations between objectsCan integrate with or provide ORM functionality © 2009 Vertive, Inc. Proprietary and Confidential
  10. 10. Database FactoriesPhactory Example<?Phactory::setConnection(new PDO(sqlite:test.db));Phactory::define(user, array(name => Test User, email => user@example.com));$user = Phactory::create(user); // creates a row in the users tableprint("Hello, {$user->name}!"); // prints "Hello, Test User!" © 2009 Vertive, Inc. Proprietary and Confidential
  11. 11. Using Phactory © 2009 Vertive, Inc. Proprietary and Confidential
  12. 12. Connecting to the DatabasePhactory supports MySQL, SQLite, and MongoDBUses PDO for SQL databases<?require_once Phactory/lib/Phactory.php;$pdo = new PDO(mysql:host=127.0.0.1; dbname=testdb, user, password);Phactory::setConnection($pdo); © 2009 Vertive, Inc. Proprietary and Confidential
  13. 13. Defining Table BlueprintsA blueprint defines default values for objects created in a particular table<?Phactory::define(user, array(name => test_user, age => 20));Phactory::define(post, array(text => This is a post, created_at => 1296663323)); © 2009 Vertive, Inc. Proprietary and Confidential
  14. 14. Creating ObjectsWhen creating an object with Phactory, you can: » Specify values for fields that weren’t in the blueprint definition » Override any of the default values » Associate with other objects © 2009 Vertive, Inc. Proprietary and Confidential
  15. 15. Creating ObjectsPhactory::define(user, array(name => test_user, age => 20));$john = Phactory::create(user, array(name => John Doe));$joe = Phactory::create(user, array(name => Joe Smith, activated => 1));$anon = Phactory::create(user);// $john looks like this:$john->id == 1;$john->name == John Doe;$john->activated == 0;// $joe looks like this:$joe->id == 2;$joe->name == Joe Smith;$joe->activated == 1;// $anon looks like this:$anon->id == 3;$anon->name == test_user;$anon->activated == 0; © 2009 Vertive, Inc. Proprietary and Confidential
  16. 16. Retrieving ObjectsBasic ORM functionality allows you to retrieve Phactory objects from the databaseUses a simple get() method which takes an array of columns to match$joe = Phactory::get(user, array(id => 2));$joe = Phactory::get(user, array(age => 20, activated => 1)); © 2009 Vertive, Inc. Proprietary and Confidential
  17. 17. AssociationsFor SQL databases, Phactory provides many-to-one and many-to-many associationsForeign key columns and join tables are filled in automatically when creating an object with associations © 2009 Vertive, Inc. Proprietary and Confidential
  18. 18. AssociationsPhactory::define(author);Phactory::define(book, array(name => Test Book), array(primary_author => Phactory::manyToOne(author)));$twain = Phactory::create(author, array(name => Mark Twain));$book = Phactory::createWithAssociations(book, array(primary_author=> $twain));$book->author_id == $twain->getId(); © 2009 Vertive, Inc. Proprietary and Confidential
  19. 19. SequencesDefine blueprints with automatically incrementing values » Include ‘$n’ in the definition » Sequence starts at 0, and is incremented each time an object is createdPhactory::define(user, array(name => user$n, age => $n));$user0 = Phactory::create(user); // name == user0, age == 0$user1 = Phactory::create(user); // name == user1, age == 1$user2 = Phactory::create(user); // name == user2, age == 2 © 2009 Vertive, Inc. Proprietary and Confidential
  20. 20. Phactory and PHPUnit © 2009 Vertive, Inc. Proprietary and Confidential
  21. 21. Basic Test Setuprequire_once Phactory/lib/Phactory.php;class ExampleTest extends PHPUnit_Framework_TestCase{ public static function setUpBeforeClass() { // create a db connection and tell Phactory to use it $pdo = new PDO("sqlite:test.db"); Phactory::setConnection($pdo); // reset any existing blueprints and empty any tables Phactory has used Phactory::reset(); // define default values for each user we will create Phactory::define(user, array(name => Test User $n, age => 18)); } public static function tearDownAfterClass() { Phactory::reset(); } public function tearDown() { // delete all objects from defined tables, but do not erase blueprints Phactory::recall(); } © 2009 Vertive, Inc. Proprietary and Confidential
  22. 22. Structuring Shared DefinitionsUsually many of the test classes in your suite will need to use the same tablesDefine blueprints in one place, share them among many tests » Can include() a file of definitions, put definitions in a static class, etc. © 2009 Vertive, Inc. Proprietary and Confidential
  23. 23. Structuring Shared DefinitionsSharedDefinitions.php<?Phactory::define(tag, array(name => Tag $n));Phactory::define(post, array(name => Test Blog Post, content => Test Content), array(tag => Phactory::manyToMany(tag, posts_tags)));ExampleTest.phpclass ExampleTest extends PHPUnit_Framework_TestCase{ public static function setUpBeforeClass() { $pdo = new PDO("sqlite:test.db"); Phactory::setConnection($pdo); Phactory::reset(); // include definitions common to several tests include(SharedDefinitions.php); }} © 2009 Vertive, Inc. Proprietary and Confidential
  24. 24. Dynamic ObjectsRecall that with fixtures, your test data is all loaded at the start of the testWith Phactory, you can create or change test data during a test © 2009 Vertive, Inc. Proprietary and Confidential
  25. 25. Dynamic Objectsclass MyPostClass { public static function countTagsForPost($post_id) { $stmt = $pdo->prepare("SELECT COUNT(*) AS num_tags FROM `posts_tags` WHERE `post_id` = ?"); $stmt->execute(array($post_id)); $result = $stmt->fetch(); return $result[num_tags]; }}Phactory::define(tag, array(name => Tag $n), array(post => Phactory::manyToMany(post, posts_tags)));Phactory::define(post, array(name => Test Blog Post, content => Test Content), array(tag => Phactory::manyToMany(tag, posts_tags)));$post = Phactory::create(post);$this->assertEquals(0, MyPostClass::countTagsForPost($post->getId()));$tag = Phactory::createWithAssociations(tag, array(post => $post)); © 2009 Vertive, Inc.$this->assertEquals(1, MyPostClass::countTagsForPost($post->getId())); Proprietary and Confidential
  26. 26. Using Phactory with MongoDB require_once Phactory/lib/PhactoryMongo.php; Uses the Mongo PHP driver Almost exactly the same as regular SQL Phactory, except: » Documents returned as arrays rather than Phactory_Row objects » Phactory::get() supports all Mongo queries » Associations: embedsOne and embedsMany http://phactory.org/mongodb-guide/ © 2009 Vertive, Inc. Proprietary and Confidential
  27. 27. QUESTIONS © 2009 Vertive, Inc. Proprietary and Confidential
  28. 28. Were Hiring!Offers.com is hiring PHP Developers and Software Engineers in Austin, TXhttp://www.vertive.com/careers © 2009 Vertive, Inc. Proprietary and Confidential
  29. 29. Thank You!These slides are online at http://slidesha.re/phactoryContact us on Twitter: @chriskite and @jimbojsbVisit http://phactory.org to download and for more information © 2009 Vertive, Inc. Proprietary and Confidential

×