Your SlideShare is downloading. ×
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Advanced PHPUnit Testing
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Advanced PHPUnit Testing

42,235

Published on

Utilizing some of the advanced features of PHPUnit testing. This presentation was given at the 2008 DC PHP conference.

Utilizing some of the advanced features of PHPUnit testing. This presentation was given at the 2008 DC PHP conference.

Published in: Business, Technology
6 Comments
40 Likes
Statistics
Notes
  • Thanks adding this to my blog post
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Good comprehensive overview. Thanks!
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here



  • <b>[Comment posted from</b> http://www.digitalsandwich.com/archives/74-2008-DC-PHP-Conference-Advanced-PHPUnit-Testing.html]
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Click on 'get file' above to download the ppt.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • can u send me the ppt for this. and it would be great if you send me the ppt of the api testing stuff.
    plz send me on sant.shinde@yahoo.com

    Thanks in advanced
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
42,235
On Slideshare
0
From Embeds
0
Number of Embeds
14
Actions
Shares
0
Downloads
604
Comments
6
Likes
40
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Advanced PHP Unit Testing The 2008 DC PHP Conference June 2nd, 2008
  • 2. Hello!
      • Mike Lively
      • Lead Developer Selling Source, Inc.
      • PHPUnit Contributor
      • PHPUnit Database Extension
      • A frequent inhabitant of #phpc
      • http://digitalsandwich.com
  • 3. PHPUnit
      • A widely used unit testing framework
      • Created by Sebastian Bergmann
      • Originally built as a port of Junit
      • Now incredibly feature rich
  • 4. PHPUnit - Advanced Features
      • Mock Objects - A way to further isolate code while testing.
      • Database Extension - A DBUnit port to allow creation of fixtures for database content.
      • Selenium Integration - A gateway to integration testing.
      • PHPUnderControl - Not really PHPUnit...but still very cool.
      • Much to cover and not much of time. Let's get started!
  • 5. PHPUnit - Mock Objects
      • Mock Objects - A way to further isolate code while testing.
      • Creates 'Fake' objects that mimic 'real' objects in controlled ways.
      • Used to ensure that expected methods are being called in expected ways.
      • Used to ensure that methods that are depended on by the unit you are testing do not 'pollute' your test with their behavior.
  • 6. PHPUnit - Mock Objects
      • How do I ensure a method is called properly?
  • 7. PHPUnit - Mock Objects
      • How do I ensure a method is called properly?
      • Create a mock object!
      • PHPUnit_Framework_TestCase::getMock(   string $className,   array $methods = array(),   array $constructParms = array(),   string $mockClassName = '',   bool $callOriginalConstruct = TRUE,   bool $callOriginalClone = TRUE,   bool $callAutoLoad = TRUE );
  • 8. PHPUnit - Mock Objects
      • Create the mock object
      • <?php require_once  'PHPUnit/Framework.php' ;   class  ObserverTest  extends  PHPUnit_Framework_TestCase {     public function  testUpdateIsCalledOnce ()     {         $observer  =  $this -> getMock ( 'Observer' , array( 'update' ));     } } ?>
  • 9. PHPUnit - Mock Objects
      • Setup the expectation
      • <?php require_once  'PHPUnit/Framework.php' ;   class  ObserverTest  extends  PHPUnit_Framework_TestCase {     public function  testUpdateIsCalledOnce ()     {         $observer  =  $this -> getMock ( 'Observer' , array( 'update' ));          $observer -> expects ( $this -> once ())                  -> method ( 'update' )                  -> with ( $this -> equalTo ( 'something' ));     } } ?>
  • 10. PHPUnit - Mock Objects
      • expects() - Sets how many times you expect a method to be called:
        • any()‏
        • never()‏
        • atLeastOnce()‏
        • once()‏
        • exactly($count)‏
        • at($index)
      • method() - The name of the method you are setting the expectation for
  • 11. PHPUnit - Mock Objects
      • with() - Each parameter is validated using PHPUnit Constraints:
        • anything()‏
        • contains($value)‏
        • arrayHasKey($key)‏
        • equalTo($value, $delta, $maxDepth)‏
        • classHasAttribute($attribute)‏
        • greaterThan($value)‏
        • isInstanceOf($className)‏
        • isType($type)‏
        • matchesRegularExpression($regex)‏
        • stringContains($string, $case)
      • withAnyParameters() - A quick way to say &quot;I don't care&quot;
  • 12. PHPUnit - Mock Objects
      • Call the tested code
      • <?php require_once  'PHPUnit/Framework.php' ;   class  ObserverTest  extends  PHPUnit_Framework_TestCase {     public function  testUpdateIsCalledOnce ()     {         $observer  =  $this -> getMock ( 'Observer' , array( 'update' ));          $observer -> expects ( $this -> once ())                  -> method ( 'update' )                  -> with ( $this -> equalTo ( 'something' ));         $subject  = new  Subject ;          $subject -> attach ( $observer );           $subject -> doSomething ();     } } ?>
  • 13. PHPUnit - Mock Objects
      • Force methods not being tested to return particular values.
      • will() - Force the current method to return a particular value
        • returnValue($value) - Returns the specified value
        • throwException($exception) - Throws the specified exception object
        • onConsecutiveCalls(...) - Performs each action (return or exception) consecutively.
  • 14. PHPUnit - Mock Objects
      • Forcing methods to return certain values
      • <?php require_once  'PHPUnit/Framework.php' ;   class  StubTest  extends  PHPUnit_Framework_TestCase {     public function  testStub ()     {          $stub  =  $this -> getMock ( 'SomeClass' , array( 'doSomething' ));          $stub -> expects ( $this -> any ())              -> method ( 'doSomething' )              -> will ( $this -> returnValue ( 'foo' ));            // Calling $stub->doSomething() will now return 'foo'.      } } ?>
  • 15. PHPUnit - Database Extension The PHPUnit Database Extension
  • 16. PHPUnit - Database Extension
      • PHPUnit Database Extension - DBUnit Port
      • Uses many of the same concepts
      • Dataset formats are essentially identical
      • Puts your database into a known state prior to testing
      • Allows for setting expectations of data in your database at the end of a test
  • 17. PHPUnit - Database Extension
      • PHPUnit_Extensions_Database_TestCase
      • Overloads setUp() and tearDown() and introduces four new overridable methods (2 MUST be overriden)
      • If implementing setUp or tearDown, please be sure to call parent::setUp() and parent::tearDown()‏
  • 18. PHPUnit - Database Extension
      • Must implement
        • getConnection() - Returns a database connection wrapper
        • getDataSet() - Returns the dataset to seed the test database with.
      • Can override
        • getSetUpOperation() - Returns the operation used to set up the database (defaults to CLEAN_INSERT)
        • getTearDownOperation() - Returns the operation to used to tear down the database (defaults to NONE)‏
  • 19. PHPUnit - Database Extension
      • getConnection() returns a customized wrapper around a database connection.
      • Current implementation uses PDO
      • This does not mean code you are testing has to use PDO
      • createDefaultDBConnection(   PDO $pdo,   string $schema ); // Convenience method
      • Very important to provide the schema name.
  • 20. PHPUnit - Database Extension
      • Setting up your database test case connection
      • <?php require_once  'PHPUnit/Extensions/Database/TestCase.php' ;   class  DatabaseTest  extends  PHPUnit_Extensions_Database_TestCase {     protected function  getConnection ()     {          $pdo  = new  PDO ( 'mysql:host=localhost;dbname=testdb' ,  'root' ,  '' );         return  $this -> createDefaultDBConnection ( $pdo ,  'testdb' );     } } ?>
  • 21. PHPUnit - Database Extension
      • Currently (known) supported databases:
        • MySQL
        • SQLite
        • Postgres
        • OCI8
      • Need another RDBMS supported? I NEED YOU!!!
  • 22. PHPUnit - Database Extension
      • getDataSet() returns one of the following types of data sets:
        • Flat XML
        • XML
        • Database
        • Default (php array basically)
      • Can be a pain to create
      • Working on utilities to make it...less painful
  • 23. PHPUnit - Database Extension
      • Convenience methods for datasets
        • $this->createFlatXMLDataSet($xmlFile);
        • $this->createXMLDataSet($xmlFile);
        • Use full paths
  • 24. PHPUnit - Database Extension
      • Setting up your database test case's common fixture
      • <?php require_once  'PHPUnit/Extensions/Database/TestCase.php' ;   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' );     } } ?>
  • 25. PHPUnit - Flat XML Data Set
      • Each element represents a row, each attribute represents a column.
      • All attributes must be present in the first element for a given table.
      • Specifying an element with no attributes represents an empty table.
      • If an attribute specified in the first element is missing in subsequent element, NULL is implied.
      • There is no explicit NULL
  • 26. PHPUnit - Database Extension
      • Flat XML
      • <dataset>      <TEST_TABLE COL0=&quot;row 0 col 0&quot;          COL1=&quot;row 0 col 1&quot;          COL2=&quot;row 0 col 2&quot;/>      <TEST_TABLE COL1=&quot;row 1 col 1&quot;/>      <SECOND_TABLE COL0=&quot;row 0 col 0&quot;          COL1=&quot;row 0 col 1&quot; />      <EMPTY_TABLE/> </dataset>
  • 27. PHPUnit - XML Data Set
      • A more robust and capable format
      • <table> element for each table
      • <column> element for each column
      • <row> element for each row
      • <row> will contain equal number of children as there are <column>s in the same order.
      • <value>val</value> is used to specify a value
      • <null/> used to explicitly specify NULL
  • 28. PHPUnit - Database Extension
      • XML (Not so flat)‏
      • <dataset>     <table name=&quot;TEST_TABLE&quot;>         <column>COL0</column>         <column>COL1</column>         <column>COL2</column>         <row>             <value>row 0 col 0</value>             <value>row 0 col 1</value>             <value>row 0 col 2</value>         </row>         <row>             <null/>             <value>row 1 col 1</value>             <null/>         </row>     </table>     <table name='EMPTY_TABLE'>         <column>COLUMN0</column>         <column>COLUMN1</column>     </table> </dataset>
  • 29. PHPUnit - Other Data Sets
      • Pull your data sets out of a database
        • Possible, and might be a good way to do it for smaller database test suites.
        • Wouldn't recommend it for large ones (yet)
      • What about the Default data set?
        • I haven't hated myself enough to bother with it yet :P
      • Future formats? CSV, Composite Data Sets, Query Sets
  • 30. PHPUnit - Other Data Sets
      • Pull your data sets out of a database
        • Possible, and might be a good way to do it for smaller database test suites.
        • Wouldn't recommend it for large ones (yet)
      • What about the Default data set?
        • I haven't hated myself enough to bother with it yet :P
      • Future formats? CSV, Composite Data Sets, Query Sets <- this is when you'll want to use database data sets for large suites
  • 31. PHPUnit - Operations
    • If you want to specify non-default operations override either getSetUpOperation() or getTearDownOperation() with a static method from the class: PHPUnit_Extensions_Database_Operation_Factory 
      • NONE
      • CLEAN_INSERT
      • INSERT
      • TRUNCATE
      • DELETE
      • DELETE_ALL
      • UPDATE
  • 32. PHPUnit - Operations
      • <?php require_once  'PHPUnit/Extensions/Database/TestCase.php' ;   class  DatabaseTest  extends  PHPUnit_Extensions_Database_TestCase {     protected function  getSetUpOperation ()     {         return  PHPUnit_Extensions_Database_Operation_Factory :: CLEAN_INSERT ();     }       protected function  getTearDownOperation ()     {         return  PHPUnit_Extensions_Database_Operation_Factory :: NONE ();     } } ?>
  • 33. PHPUnit - Database Extension
      • Setting up database expectations.
      • Retrieve database contents:
        • $this->getConnection()->createDataSet();
        • Creates a dataset with ALL data in your database.
        • Pass an array of table names if you only want to compare particular tables.
      • You can also use the data set filter if necessary
  • 34. PHPUnit - Database Extension
      • Why Filtered Data Sets? auto increment, time stamps
      • PHPUnit_Extensions_Database_DataSet_DataSetFilter decorator
        • Accepts existing dataset object as first parameter
        • Accepts associative array as second parameter
          • The array indexes are table names
          • The array values are arrays of column names to exclude from the data set or the string '*' if the whole table is to be excluded.
  • 35. PHPUnit - Database Extension
      • Refreshing our memory
      • <?php require_once  'PHPUnit/Extensions/Database/TestCase.php' ;   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' );     } } ?>
  • 36. PHPUnit - Database Extension
      • Writing a test
      • <?php require_once  'PHPUnit/Extensions/Database/TestCase.php' ;   class  DatabaseTest  extends  PHPUnit_Extensions_Database_TestCase {     // ...     public function  testAccountBalanceDeposits ()     {          $bank_account  = new  BankAccount ( '15934903649620486' ,  $this -> pdo );          $bank_account -> depositMoney ( 100 );               $bank_account  = new  BankAccount ( '15936487230215067' ,  $this -> pdo );          $bank_account -> depositMoney ( 230 );                   $bank_account  = new  BankAccount ( '12348612357236185' ,  $this -> pdo );          $bank_account -> depositMoney ( 24 );                    $xml_dataset  =  $this -> createFlatXMLDataSet ( dirname ( __FILE__ ). '/_files/bank-account-after-deposits.xml' );          $database_dataset = $this -> getConnection ()-> createDataSet ( array ( 'bank_account' ));     }     // ... } ?>
  • 37. PHPUnit - Database Extension
      • Filtering out date_created
      • <?php require_once  'PHPUnit/Extensions/Database/TestCase.php' ;   class  DatabaseTest  extends  PHPUnit_Extensions_Database_TestCase {     // ...     public function  testAccountBalanceDeposits ()     {         // ...                   $xml_dataset  =  $this -> createFlatXMLDataSet ( dirname ( __FILE__ ). '/_files/bank-account-after-deposits.xml' ); $database_dataset = new PHPUnit_Extensions_Database_DataSet_DataSetFilter ( $this -> getConnection ()-> createDataSet ( array ( 'bank_account' )), array ( 'bank_account' => array ( 'date_created' )) ); }     // ... } ?>
  • 38. PHPUnit - Database Extension
      • $this->assertDataSetsEqual($expected, $actual)
      • Compares all tables in the two data sets
      • Must have equal and matching tables with equal and matching data
      • Have I mentioned filters?
      • $this->assertTablesEqual($expected, $actual)
      • There is also a table filter!
  • 39. PHPUnit - Database Extension
      • Writing a test
      • <?php require_once  'PHPUnit/Extensions/Database/TestCase.php' ;   class  DatabaseTest  extends  PHPUnit_Extensions_Database_TestCase {     // ...     public function  testAccountBalanceDeposits ()     {          $bank_account  = new  BankAccount ( '15934903649620486' ,  $this -> pdo );          $bank_account -> depositMoney ( 100 );               $bank_account  = new  BankAccount ( '15936487230215067' ,  $this -> pdo );          $bank_account -> depositMoney ( 230 );                   $bank_account  = new  BankAccount ( '12348612357236185' ,  $this -> pdo );          $bank_account -> depositMoney ( 24 );                    $xml_dataset  =  $this -> createFlatXMLDataSet ( dirname ( __FILE__ ) . '/_files/bank-account-after-deposits.xml' ); $this -> assertDataSetsEqual ( $xml_dataset ,           $this -> getConnection ()-> createDataSet ( array ( 'bank_account' )) );     }     // ... } ?>
  • 40. PHPUnit - Selenium
      • Selenium is a testing framework for web applications.
      • Runs tests by controlling a remote browser session
      • Can inspect the dom, look for events, and much much more
      • Selenium tests can be made a part of your PHPUnit Test Suite
  • 41. PHPUnit - Selenium
      • Selenium is a testing framework for web applications.
      • Runs tests by controlling a remote browser session
      • Can inspect the dom, look for events, and much much more
      • Selenium tests can be made a part of your PHPUnit Test Suite
  • 42. PHPUnit - Selenium Demo Time!
  • 43. PHPUnit - Continuous Integration Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily, leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly. -- Martin Fowler
  • 44. PHPUnit - PHPUnderControl
      • Created and maintained by Manuel Pischler
      • Cruise Control for the php developer
      • Runs your Unit Tests
      • Builds your documentation
      • Lint checks your code
      • Gives you build and performance metrics
      • The best thing since sliced bread
  • 45. PHPUnit - PHPUnderControl Demo Time!
  • 46. Thank you - Resources
      • PHPUnit: http://phpun.it, http://planet.phpunit.de
      • Selenium: http://selenium.openqa.org/
      • PHPUnderControl: http://www.phpundercontrol.org/
      • My Site: http://www.digitalsandwich.com
      • My Employer's Site: http://dev.sellingsource.com
    • Questions??

×