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.
Serhii Kartashov
 
PDF
Devoxx 15 equals hashcode
bleporini
 
PPT
Advanced PHPUnit Testing
Mike Lively
 
PPT
Test driven development_for_php
Lean Teams Consultancy
 
PDF
Unit Testing in SilverStripe
Ingo Schommer
 
PPT
Zend framework 03 - singleton factory data mapper caching logging
Tricode (part of Dept)
 
PPT
Phpunit testing
Nikunj Bhatnagar
 
PDF
PL/SQL Unit Testing Can Be Fun!
Raimonds Simanovskis
 
Testing database content with DBUnit. My experience.
Serhii Kartashov
 
Devoxx 15 equals hashcode
bleporini
 
Advanced PHPUnit Testing
Mike Lively
 
Test driven development_for_php
Lean Teams Consultancy
 
Unit Testing in SilverStripe
Ingo Schommer
 
Zend framework 03 - singleton factory data mapper caching logging
Tricode (part of Dept)
 
Phpunit testing
Nikunj Bhatnagar
 
PL/SQL Unit Testing Can Be Fun!
Raimonds Simanovskis
 

What's hot (20)

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

Similar to Testing persistence in PHP with DbUnit (20)

PPT
Php frameworks
Anil Kumar Panigrahi
 
PPT
Framework
Nguyen Linh
 
PPT
Create a web-app with Cgi Appplication
olegmmiller
 
ODP
ActiveWeb: Chicago Java User Group Presentation
ipolevoy
 
PDF
Web Scraping with PHP
Matthew Turland
 
PPT
Zend framework 04 - forms
Tricode (part of Dept)
 
KEY
Unit testing zend framework apps
Michelangelo van Dam
 
PDF
Unit testing with zend framework tek11
Michelangelo van Dam
 
KEY
Unit testing with zend framework PHPBenelux
Michelangelo van Dam
 
PPT
Micro-ORM Introduction - Don't overcomplicate
Kiev ALT.NET
 
PPTX
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
Carles Farré
 
PDF
Intro Open Social and Dashboards
Atlassian
 
PPT
P H P Part I I, By Kian
phelios
 
PPT
Corephpcomponentpresentation 1211425966721657-8
PrinceGuru MS
 
PPT
Web Scraping with PHP
Matthew Turland
 
PPT
PHP Unit Testing
Tagged Social
 
PPT
Liferay Training Struts Portlet
Saikrishna Basetti
 
PPT
Система рендеринга в Magento
Magecom Ukraine
 
PDF
QA for PHP projects
Michelangelo van Dam
 
PPTX
Extend sdk
Harsha Nagaraj
 
Php frameworks
Anil Kumar Panigrahi
 
Framework
Nguyen Linh
 
Create a web-app with Cgi Appplication
olegmmiller
 
ActiveWeb: Chicago Java User Group Presentation
ipolevoy
 
Web Scraping with PHP
Matthew Turland
 
Zend framework 04 - forms
Tricode (part of Dept)
 
Unit testing zend framework apps
Michelangelo van Dam
 
Unit testing with zend framework tek11
Michelangelo van Dam
 
Unit testing with zend framework PHPBenelux
Michelangelo van Dam
 
Micro-ORM Introduction - Don't overcomplicate
Kiev ALT.NET
 
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
Carles Farré
 
Intro Open Social and Dashboards
Atlassian
 
P H P Part I I, By Kian
phelios
 
Corephpcomponentpresentation 1211425966721657-8
PrinceGuru MS
 
Web Scraping with PHP
Matthew Turland
 
PHP Unit Testing
Tagged Social
 
Liferay Training Struts Portlet
Saikrishna Basetti
 
Система рендеринга в Magento
Magecom Ukraine
 
QA for PHP projects
Michelangelo van Dam
 
Extend sdk
Harsha Nagaraj
 
Ad

Recently uploaded (20)

PDF
Chapter 2 Digital Image Fundamentals.pdf
Getnet Tigabie Askale -(GM)
 
PDF
Software Development Methodologies in 2025
KodekX
 
PDF
Revolutionize Operations with Intelligent IoT Monitoring and Control
Rejig Digital
 
PDF
Doc9.....................................
SofiaCollazos
 
PDF
CIFDAQ'S Market Insight: BTC to ETH money in motion
CIFDAQ
 
PDF
CIFDAQ's Teaching Thursday: Moving Averages Made Simple
CIFDAQ
 
PDF
This slide provides an overview Technology
mineshkharadi333
 
PDF
Why Your AI & Cybersecurity Hiring Still Misses the Mark in 2025
Virtual Employee Pvt. Ltd.
 
PDF
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
PPTX
Comunidade Salesforce São Paulo - Desmistificando o Omnistudio (Vlocity)
Francisco Vieira Júnior
 
PDF
Orbitly Pitch Deck|A Mission-Driven Platform for Side Project Collaboration (...
zz41354899
 
DOCX
Top AI API Alternatives to OpenAI: A Side-by-Side Breakdown
vilush
 
PDF
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
PDF
Security features in Dell, HP, and Lenovo PC systems: A research-based compar...
Principled Technologies
 
PDF
Enable Enterprise-Ready Security on IBM i Systems.pdf
Precisely
 
PDF
GYTPOL If You Give a Hacker a Host
linda296484
 
PDF
NewMind AI Weekly Chronicles - July'25 - Week IV
NewMind AI
 
PDF
CIFDAQ's Token Spotlight: SKY - A Forgotten Giant's Comeback?
CIFDAQ
 
PPTX
ChatGPT's Deck on The Enduring Legacy of Fax Machines
Greg Swan
 
PDF
Event Presentation Google Cloud Next Extended 2025
minhtrietgect
 
Chapter 2 Digital Image Fundamentals.pdf
Getnet Tigabie Askale -(GM)
 
Software Development Methodologies in 2025
KodekX
 
Revolutionize Operations with Intelligent IoT Monitoring and Control
Rejig Digital
 
Doc9.....................................
SofiaCollazos
 
CIFDAQ'S Market Insight: BTC to ETH money in motion
CIFDAQ
 
CIFDAQ's Teaching Thursday: Moving Averages Made Simple
CIFDAQ
 
This slide provides an overview Technology
mineshkharadi333
 
Why Your AI & Cybersecurity Hiring Still Misses the Mark in 2025
Virtual Employee Pvt. Ltd.
 
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
Comunidade Salesforce São Paulo - Desmistificando o Omnistudio (Vlocity)
Francisco Vieira Júnior
 
Orbitly Pitch Deck|A Mission-Driven Platform for Side Project Collaboration (...
zz41354899
 
Top AI API Alternatives to OpenAI: A Side-by-Side Breakdown
vilush
 
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
Security features in Dell, HP, and Lenovo PC systems: A research-based compar...
Principled Technologies
 
Enable Enterprise-Ready Security on IBM i Systems.pdf
Precisely
 
GYTPOL If You Give a Hacker a Host
linda296484
 
NewMind AI Weekly Chronicles - July'25 - Week IV
NewMind AI
 
CIFDAQ's Token Spotlight: SKY - A Forgotten Giant's Comeback?
CIFDAQ
 
ChatGPT's Deck on The Enduring Legacy of Fax Machines
Greg Swan
 
Event Presentation Google Cloud Next Extended 2025
minhtrietgect
 

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/