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)

PDF
The History of PHPersistence
KEY
PHPUnit testing to Zend_Test
PDF
DBIx::Class beginners
KEY
Object Relational Mapping in PHP
PPTX
Doctrine 2.0 Enterprise Persistence Layer for PHP
PPT
Building Data Mapper PHP5
PDF
Doctrine For Beginners
ODP
‎Unit tests automation for legacy code‎ at YAPC::NA 2016
PDF
Doctrine and NoSQL
PDF
Unittests für Dummies
PDF
DBIx::Class introduction - 2010
PDF
ZendCon2010 The Doctrine Project
PDF
Dependency Injection
PDF
Doctrine for NoSQL
PDF
Agile Data concept introduction
PDF
Object Oriented Programming with PHP 5 - More OOP
PPT
Working with databases in Perl
ODP
Unit testing: unitils & dbmaintain
PDF
Zend Framework 1 + Doctrine 2
PPT
Pursuing Domain-Driven Design practices in PHP
The History of PHPersistence
PHPUnit testing to Zend_Test
DBIx::Class beginners
Object Relational Mapping in PHP
Doctrine 2.0 Enterprise Persistence Layer for PHP
Building Data Mapper PHP5
Doctrine For Beginners
‎Unit tests automation for legacy code‎ at YAPC::NA 2016
Doctrine and NoSQL
Unittests für Dummies
DBIx::Class introduction - 2010
ZendCon2010 The Doctrine Project
Dependency Injection
Doctrine for NoSQL
Agile Data concept introduction
Object Oriented Programming with PHP 5 - More OOP
Working with databases in Perl
Unit testing: unitils & dbmaintain
Zend Framework 1 + Doctrine 2
Pursuing Domain-Driven Design practices in PHP
Ad

Recently uploaded (20)

PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Encapsulation theory and applications.pdf
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPTX
sap open course for s4hana steps from ECC to s4
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
Spectroscopy.pptx food analysis technology
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
MYSQL Presentation for SQL database connectivity
Mobile App Security Testing_ A Comprehensive Guide.pdf
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Encapsulation theory and applications.pdf
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
sap open course for s4hana steps from ECC to s4
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
The AUB Centre for AI in Media Proposal.docx
Spectroscopy.pptx food analysis technology
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Network Security Unit 5.pdf for BCA BBA.
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Review of recent advances in non-invasive hemoglobin estimation
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Reach Out and Touch Someone: Haptics and Empathic Computing
20250228 LYD VKU AI Blended-Learning.pptx
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf

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/