SlideShare a Scribd company logo
Testing persistence (in PHP) PHPUnit & DbUnit
Our story by unit testing classes Started from inside to the outside
Tools and principles Using PHPUnit with Mock objects  to isolate the SUT Design for testability (SOLID) Use the front door first One condition per test http://xunitpatterns.com/Principles of Test Automation.html http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
PHPUnit class   TestClass        extends  PHPUnit_Framework_TestCase {      public   function   setUp () {}      public   function   testMethod () {}      public   function   tearDown () {} }
Problems No integration guarantees Not effective for refactoring legacy code Does not ensure external quality
Need for integration tests To ensure external quality from top to bottom
Unit testing DAOs with DI and mocks $connection   =  createMockExpecting(      " INSERT INTO table SET field = 'value' " ); $dao   =   new  Dao( $connection ); $dao -> insert ( 'value' ); Tells nothing about the database interaction
Testing DAOs - injected connection $connection   =  createLocalTestConnection(); $dao   =   new  Dao( $connection ); $dao -> insert ( 'value' ); assertInsertedValueMatches( 'value' ); Hard to replace in end to end tests
Dependency lookup
Testing DAOs - dependency lookup $dao   =   new  Dao(); $dao -> insert ( 'value' ); assertInsertedValueMatches( 'value' ); http://xunitpatterns.com/Dependency Lookup.html
DbUnit + Etsy extensions
Test case init class   RemoverDaoTest   extends  DatabaseTestCaseBase { /**   * @return PHPUnit_Extensions_MultipleDatabase_Database[]   */   protected   function   getDatabaseConfigs ()   {   return   array (   $this -> getDbConfigBuilder ()   -> connection ( $this -> getCentralDbConnection ())   -> dataSet ( $this -> createXmlDataSet ( 'init.xml' ))   -> build ()   );   }
Datasets user:  -    id: 1    name: Ingrid <dataset>     <table   name= &quot;user&quot; >         <column> id </column>         <column> name </column>         <row>             <value> 1 </value>             <value> Ingrid </value>         </row>     </table> </dataset> MySQL XML YAML
Assertions public   function   testRemoveNoProblem () {     $remover   =   new  RemoverDao();     $remover -> removeUser ( 1 );     $this -> assertDataSetsEqual (   $this -> createYamlDataSet ( 'empty.yml' ), $this -> getCentralDbConnection () -> createDataSet ( array ( 'user' ))    ); }
Datasets user:  -    id: 1    name: Ingrid    created_at: 2012-01-16 <dataset>     <table   name= &quot;user&quot; >         <column> id </column>         <column> name </column>         <column> created_at </column>         <row>             <value> 1 </value>             <value> Ingrid </value>             <value> 2012-01-16 </value>         </row>     </table> </dataset> MySQL XML YAML
Dataset filter $datasetFilter  =   new  PHPUnit_Extensions_Database_DataSet_DataSetFilter(   $dataset ); $datasetFilter -> addIncludeTables ( array ( 'user' ) ); $datasetFilter -> setExcludeColumnsForTable ( 'user' ,  array ( 'created_at' ) );
Datasets user:  -    id: 1    name: Ingrid    created_at:  ##TIME## <dataset>     <table   name= &quot;user&quot; >         <column> id </column>         <column> name </column>         <column> created_at </column>         <row>             <value> 1 </value>             <value> Ingrid </value>             <value> ##TIME## </value>         </row>     </table> </dataset> MySQL XML YAML
Replacement dataset $replacementDataset   =   new  PHPUnit_Extensions_Database_DataSet_ReplacementDataSet (    $dataset ,  array ( '##TIME##'   =>   TimeService::time ()) );
Implicit setup Common initial state, extended test-by-test Hard to share
Inline setup Define only the tables being used in common setup Insert all the necessary data inline in the test method Still messy to share common datasets with xml or yml Minimal fixture! 
Inline datasets with PHP Value objects + builders Convert to dataset for: inserting into database using in assertions
Setup $user    =  UserBuilder :: create () -> build (); $video   =  VideoBuilder :: create ()    -> owner ( $user )    -> private ()    -> build (); TestDataInserter :: create (getCentralDbConnection())    -> add ( 'user' ,  $user )    -> add ( 'video' ,  $video );
Excercise VideoPublisherDao :: create () -> publish ( $video -> id ); Http service DAO HttpClient :: create () -> call ( 'Video::publish' ,  $video -> id );
Verify assertDataSetsEqual(    $this -> createDataSet ( 'video' ,  $video ),    $this -> getCentralDbConnection () -> createDataSet ( array ( 'video' )) );
Layer crossing tests - where we use it Http services Daemons Cron jobs Ajax calls
The power of layer crossing tests Refactoring (legacy) code Increasing code coverage
There are downsides too We use the back door => risk of  overspecification Empty initial state  hides concurrency problems parallel testing more difficult
Concurrent end-to-end black box tests Uses only the front door (public api) Isolation with unique identifiers &  Δ assertions Tests real concurrency Harder to track bugs & intermittent tests http://engineering.imvu.com/2011/01/19/buildbot-and-intermittent-tests/
[email_address] twitter.com/pepov

More Related Content

PPTX
Testing database content with DBUnit. My experience.
PDF
Devoxx 15 equals hashcode
PPT
Advanced PHPUnit Testing
PPT
Test driven development_for_php
PDF
Unit Testing in SilverStripe
PPT
Zend framework 03 - singleton factory data mapper caching logging
PPT
Phpunit testing
PDF
PL/SQL Unit Testing Can Be Fun!
Testing database content with DBUnit. My experience.
Devoxx 15 equals hashcode
Advanced PHPUnit Testing
Test driven development_for_php
Unit Testing in SilverStripe
Zend framework 03 - singleton factory data mapper caching logging
Phpunit testing
PL/SQL Unit Testing Can Be Fun!

What's hot (20)

PDF
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
PPTX
Unit Testng with PHP Unit - A Step by Step Training
PPT
Core Php Component Presentation
ODP
Getting to Grips with SilverStripe Testing
PDF
Triggers and Stored Procedures
PPTX
Owl: The New Odoo UI Framework
ODP
Introduction to Django
PDF
Workshop quality assurance for php projects - ZendCon 2013
PPTX
Test in action week 4
PDF
Having Fun with Play
PDF
UA testing with Selenium and PHPUnit - PFCongres 2013
PDF
Unit testing with PHPUnit - there's life outside of TDD
PDF
Testing the frontend
PDF
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
PDF
Unit testing PHP apps with PHPUnit
PDF
Quality Assurance for PHP projects - ZendCon 2012
PDF
Using Task Queues and D3.js to build an analytics product on App Engine
PDF
Hear no evil, see no evil, patch no evil: Or, how to monkey-patch safely.
PDF
Introduction to Unit Testing with PHPUnit
KEY
Workshop quality assurance for php projects tek12
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
Unit Testng with PHP Unit - A Step by Step Training
Core Php Component Presentation
Getting to Grips with SilverStripe Testing
Triggers and Stored Procedures
Owl: The New Odoo UI Framework
Introduction to Django
Workshop quality assurance for php projects - ZendCon 2013
Test in action week 4
Having Fun with Play
UA testing with Selenium and PHPUnit - PFCongres 2013
Unit testing with PHPUnit - there's life outside of TDD
Testing the frontend
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
Unit testing PHP apps with PHPUnit
Quality Assurance for PHP projects - ZendCon 2012
Using Task Queues and D3.js to build an analytics product on App Engine
Hear no evil, see no evil, patch no evil: Or, how to monkey-patch safely.
Introduction to Unit Testing with PHPUnit
Workshop quality assurance for php projects tek12
Ad

Similar to Testing persistence in PHP with DbUnit (20)

PPT
Php frameworks
PPT
Framework
PPT
Create a web-app with Cgi Appplication
ODP
ActiveWeb: Chicago Java User Group Presentation
PDF
Web Scraping with PHP
PPT
Zend framework 04 - forms
KEY
Unit testing zend framework apps
PDF
Unit testing with zend framework tek11
KEY
Unit testing with zend framework PHPBenelux
PPT
Micro-ORM Introduction - Don't overcomplicate
PPTX
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
PDF
Intro Open Social and Dashboards
PPT
P H P Part I I, By Kian
PPT
Corephpcomponentpresentation 1211425966721657-8
PPT
Web Scraping with PHP
PPT
PHP Unit Testing
PPT
Liferay Training Struts Portlet
PPT
Система рендеринга в Magento
PDF
QA for PHP projects
PPTX
Extend sdk
Php frameworks
Framework
Create a web-app with Cgi Appplication
ActiveWeb: Chicago Java User Group Presentation
Web Scraping with PHP
Zend framework 04 - forms
Unit testing zend framework apps
Unit testing with zend framework tek11
Unit testing with zend framework PHPBenelux
Micro-ORM Introduction - Don't overcomplicate
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
Intro Open Social and Dashboards
P H P Part I I, By Kian
Corephpcomponentpresentation 1211425966721657-8
Web Scraping with PHP
PHP Unit Testing
Liferay Training Struts Portlet
Система рендеринга в Magento
QA for PHP projects
Extend sdk
Ad

Recently uploaded (20)

PDF
Machine learning based COVID-19 study performance prediction
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
cuic standard and advanced reporting.pdf
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PDF
Getting Started with Data Integration: FME Form 101
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
A Presentation on Artificial Intelligence
PPTX
Machine Learning_overview_presentation.pptx
PDF
Encapsulation theory and applications.pdf
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Machine learning based COVID-19 study performance prediction
Reach Out and Touch Someone: Haptics and Empathic Computing
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Advanced methodologies resolving dimensionality complications for autism neur...
cuic standard and advanced reporting.pdf
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Digital-Transformation-Roadmap-for-Companies.pptx
Unlocking AI with Model Context Protocol (MCP)
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Spectral efficient network and resource selection model in 5G networks
Programs and apps: productivity, graphics, security and other tools
Assigned Numbers - 2025 - Bluetooth® Document
Getting Started with Data Integration: FME Form 101
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
A Presentation on Artificial Intelligence
Machine Learning_overview_presentation.pptx
Encapsulation theory and applications.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
Profit Center Accounting in SAP S/4HANA, S4F28 Col11

Testing persistence in PHP with DbUnit

  • 1. Testing persistence (in PHP) PHPUnit & DbUnit
  • 2. Our story by unit testing classes Started from inside to the outside
  • 3. Tools and principles Using PHPUnit with Mock objects  to isolate the SUT Design for testability (SOLID) Use the front door first One condition per test http://xunitpatterns.com/Principles of Test Automation.html http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
  • 4. PHPUnit class TestClass        extends PHPUnit_Framework_TestCase {     public function setUp () {}     public function testMethod () {}     public function tearDown () {} }
  • 5. Problems No integration guarantees Not effective for refactoring legacy code Does not ensure external quality
  • 6. Need for integration tests To ensure external quality from top to bottom
  • 7. Unit testing DAOs with DI and mocks $connection = createMockExpecting(      &quot; INSERT INTO table SET field = 'value' &quot; ); $dao = new Dao( $connection ); $dao -> insert ( 'value' ); Tells nothing about the database interaction
  • 8. Testing DAOs - injected connection $connection = createLocalTestConnection(); $dao = new Dao( $connection ); $dao -> insert ( 'value' ); assertInsertedValueMatches( 'value' ); Hard to replace in end to end tests
  • 10. Testing DAOs - dependency lookup $dao = new Dao(); $dao -> insert ( 'value' ); assertInsertedValueMatches( 'value' ); http://xunitpatterns.com/Dependency Lookup.html
  • 11. DbUnit + Etsy extensions
  • 12. Test case init class RemoverDaoTest extends DatabaseTestCaseBase { /** * @return PHPUnit_Extensions_MultipleDatabase_Database[] */ protected function getDatabaseConfigs () { return array ( $this -> getDbConfigBuilder () -> connection ( $this -> getCentralDbConnection ()) -> dataSet ( $this -> createXmlDataSet ( 'init.xml' )) -> build () ); }
  • 13. Datasets user:  -    id: 1    name: Ingrid <dataset>     <table name= &quot;user&quot; >         <column> id </column>         <column> name </column>         <row>             <value> 1 </value>             <value> Ingrid </value>         </row>     </table> </dataset> MySQL XML YAML
  • 14. Assertions public function testRemoveNoProblem () {     $remover = new RemoverDao();     $remover -> removeUser ( 1 );     $this -> assertDataSetsEqual ( $this -> createYamlDataSet ( 'empty.yml' ), $this -> getCentralDbConnection () -> createDataSet ( array ( 'user' ))    ); }
  • 15. Datasets user:  -    id: 1    name: Ingrid    created_at: 2012-01-16 <dataset>     <table name= &quot;user&quot; >         <column> id </column>         <column> name </column>         <column> created_at </column>         <row>             <value> 1 </value>             <value> Ingrid </value>             <value> 2012-01-16 </value>         </row>     </table> </dataset> MySQL XML YAML
  • 16. Dataset filter $datasetFilter = new PHPUnit_Extensions_Database_DataSet_DataSetFilter( $dataset ); $datasetFilter -> addIncludeTables ( array ( 'user' ) ); $datasetFilter -> setExcludeColumnsForTable ( 'user' , array ( 'created_at' ) );
  • 17. Datasets user:  -    id: 1    name: Ingrid    created_at: ##TIME## <dataset>     <table name= &quot;user&quot; >         <column> id </column>         <column> name </column>         <column> created_at </column>         <row>             <value> 1 </value>             <value> Ingrid </value>             <value> ##TIME## </value>         </row>     </table> </dataset> MySQL XML YAML
  • 18. Replacement dataset $replacementDataset = new PHPUnit_Extensions_Database_DataSet_ReplacementDataSet (   $dataset , array ( '##TIME##' => TimeService::time ()) );
  • 19. Implicit setup Common initial state, extended test-by-test Hard to share
  • 20. Inline setup Define only the tables being used in common setup Insert all the necessary data inline in the test method Still messy to share common datasets with xml or yml Minimal fixture! 
  • 21. Inline datasets with PHP Value objects + builders Convert to dataset for: inserting into database using in assertions
  • 22. Setup $user   = UserBuilder :: create () -> build (); $video = VideoBuilder :: create ()   -> owner ( $user )   -> private ()   -> build (); TestDataInserter :: create (getCentralDbConnection())   -> add ( 'user' , $user )   -> add ( 'video' , $video );
  • 23. Excercise VideoPublisherDao :: create () -> publish ( $video -> id ); Http service DAO HttpClient :: create () -> call ( 'Video::publish' , $video -> id );
  • 24. Verify assertDataSetsEqual(   $this -> createDataSet ( 'video' , $video ),   $this -> getCentralDbConnection () -> createDataSet ( array ( 'video' )) );
  • 25. Layer crossing tests - where we use it Http services Daemons Cron jobs Ajax calls
  • 26. The power of layer crossing tests Refactoring (legacy) code Increasing code coverage
  • 27. There are downsides too We use the back door => risk of  overspecification Empty initial state  hides concurrency problems parallel testing more difficult
  • 28. Concurrent end-to-end black box tests Uses only the front door (public api) Isolation with unique identifiers &  Δ assertions Tests real concurrency Harder to track bugs & intermittent tests http://engineering.imvu.com/2011/01/19/buildbot-and-intermittent-tests/