SlideShare uma empresa Scribd logo
1 de 29
Fundamentals of unit testing in PHP usingPHPUnit Nicolas A. Bérard-Nault 5 May 2011
Some of the goals of test automation For the stakeholders: ,[object Object]
Improvinginternalqualityby increasingmaintainability
Reduced short and long-termriskFor the programmers: ,[object Object]
Use tests as documentation
Use tests as a specification,[object Object]
PHPUnit and the xUnitfamily ,[object Object]
Member of the xUnitfamily
Direct descendant of sUnitwritten by Kent Beck and jUnit, written by Beck and Erich GammaWebsite: http://www.phpunit.de Code coverageisprovidedusing the xDebug extension: http://www.xdebug.org
Your first  PHPUnittest (1) Goal: test an implementation of ROT13 System under test: functionrot13($text) { $len = strlen($text); for ($i = 0; $i < $len; $i++)     { $text{$i} = chr((ord($text{$i}) - ord('a') + 13) % 26 + ord('a'));     } return$text; } Initial naïve approach: Formulateexpectedbehavior
Your first  PHPUnittest (2) Class namehas Test suffix Base class for tests class Rot13Test extendsPHPUnit_Framework_TestCase { public functiontestWord()     { $this->assertEquals('cheryl', rot13('purely'));     } } Test methodhas test prefix Post-condition verification
Your first  PHPUnittest (3) nicobn@nicobn-laptop:~$ phpunit rot13.php PHPUnit 3.5.5 by Sebastian Bergmann. . Time: 0 seconds, Memory: 3.50Mb OK (1 test, 1 assertion) The test passes but have wereallycovered all of our bases ?
Preconditions, invariants and postconditions functionrot13($text) { $len = strlen($text); for ($i = 0; $i < $len; $i++)     { $text{$i} = chr((ord($text{$i}) - ord('a') + 13) % 26 + ord('a'));     } return$text; } Precondition: $text must be a string Precondition: $text must belower case Invariant: non-alpha characters must remainunchanged Postcondition: each alpha character must bemoved 13 positions  Wescrewed up ! How many more tests do weneed ?
NEWFLASH: It’s not a question of how awesomelyawesome of a programmer you are, but a question of methodology ! Sad panda issad
Test first ! (1) “Applying ROT13 to a piece of text merely requires examining its alphabetic characters and replacing each one by the letter 13 places further along in the alphabet, wrapping back to the beginning if necessary. A becomes N, B becomes O, and so on up to M, which becomes Z, then the sequence continues at the beginning of the alphabet: N becomes A, O becomes B, and so on to Z, which becomes M. Only those letters which occur in the English alphabet are affected; numbers, symbols, whitespace, and all other characters are left unchanged. Because there are 26 letters in the English alphabet and 26 = 2 × 13, the ROT13 function is its own inverse.” (Wikipedia)
Test first ! (2a) functionrot13($text) { } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower()     { $this->assertEquals('n', rot13('a'));     } } There was 1 failure: 1) Rot13Test::test_A_Lower Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -n +
Test first ! (2b) functionrot13($text) { return‘n’; } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower()     { $this->assertEquals('n', rot13('a'));     } } PHPUnit 3.5.5 by Sebastian Bergmann. . Time: 1 second, Memory: 3.50Mb OK (1 test, 1 assertion)
Test first ! (2c) functionrot13($text) { returnchr(ord($text{0}) + 13); } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower()     { $this->assertEquals('n', rot13('a'));     } } PHPUnit 3.5.5 by Sebastian Bergmann. . Time: 1 second, Memory: 3.50Mb OK (1 test, 1 assertion)
Test first ! (3a) functionrot13($text) { returnchr(ord($text{0}) + 13); } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower()     { $this->assertEquals('n', rot13('a'));     } public function test_N_Lower()     { $this->assertEquals(‘a', rot13(‘n'));     } } FAIL !
Test first ! (3b) functionrot13($text) { return chr((ord($text{0}) - ord('a') + 13) % 26 + ord('a')); } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower()     { $this->assertEquals('n', rot13('a'));     } public function test_N_Lower()     { $this->assertEquals(‘a', rot13(‘n'));     } } PASS !
Test first ! (4a) functionrot13($text) {    return chr((ord($text{0}) - ord('a') + 13) % 26 + ord('a')); } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower()     { $this->assertEquals('n', rot13('a'));     } public function test_N_Lower()     { $this->assertEquals(‘a', rot13(‘n'));     } public functiontest_Symbol()     { $this->assertEquals('$', rot13('$'));     } } FAIL !
Test first ! (4b) functionrot13($text) { if (!ctype_alnum($text{0})) { return$text{0};     }    return chr((ord($text{0}) - ord('a') + 13) % 26 + ord('a')); } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower()     { $this->assertEquals('n', rot13('a'));     } public function test_N_Lower()     { $this->assertEquals(‘a', rot13(‘n'));     } public functiontest_Symbol()     { $this->assertEquals('$', rot13('$'));     } } PASS !
Test first ! (5a) functionrot13($text) { if (!ctype_alnum($text{0})) { return$text{0};     }    return chr((ord($text{0}) - ord('a') + 13) % 26 + ord('a')); } class Rot13Test extendsPHPUnit_Framework_TestCase { /* […] */ public functiontest_N_Upper()     { $this->assertEquals('A', rot13('N'));     } } FAIL !
Test first ! (5b) functionrot13($text) { if (!ctype_alnum($text{0})) { return$text{0};     } if (ctype_upper($text{0})) { $delta = ord('A');     } else { $delta = ord('a');     }    return chr((ord($text{0}) - $delta + 13) % 26 + $delta); } class Rot13Test extendsPHPUnit_Framework_TestCase { /* […] */ public functiontest_N_Upper()     { $this->assertEquals('A', rot13('N'));     } } PASS !
Test first ! (6a) functionrot13($text) { if (!ctype_alnum($text{0})) { return$text{0};     } if (ctype_upper($text{0})) { $delta = ord('A');     } else { $delta = ord('a');     }    return chr((ord($text{0}) - $delta + 13) % 26 + $delta); } class Rot13Test extendsPHPUnit_Framework_TestCase { /* […] */ public functiontest_N_Purely()     { $this->assertEquals(‘$purely$', rot13(‘$cheryl$'));     } } FAIL !
Test first ! (6b) functionrot13($text) { $str = ''; $len = strlen($text); for ($i = 0; $i < $len; $i++)     { if (!ctype_alnum($text{$i})) { $str .= $text{$i};         } else {             if (ctype_upper($text{$i})) { $delta = ord('A');             } else { $delta = ord('a');             } $str.= chr((ord($text{$i}) - $delta + 13) % 26 + $delta);         }     } return$str; } PASS !
Test-drivendevelopment RED GREEN REFACTOR
PHPUnit assertions Note: most assertions have a assertNotXXXX() counterpart.
Test status Do yourself and yourcolleaguesa favor and mark tests as skipped or incompletewhen relevant !

Mais conteúdo relacionado

Mais procurados

Beginning PHPUnit
Beginning PHPUnitBeginning PHPUnit
Beginning PHPUnit
Jace Ju
 
Test in action week 2
Test in action   week 2Test in action   week 2
Test in action week 2
Yi-Huan Chan
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
Enterprise PHP Center
 
Python Unit Test
Python Unit TestPython Unit Test
Python Unit Test
David Xie
 

Mais procurados (20)

Advanced PHPUnit Testing
Advanced PHPUnit TestingAdvanced PHPUnit Testing
Advanced PHPUnit Testing
 
PHPUnit best practices presentation
PHPUnit best practices presentationPHPUnit best practices presentation
PHPUnit best practices presentation
 
Unit testing PHP apps with PHPUnit
Unit testing PHP apps with PHPUnitUnit testing PHP apps with PHPUnit
Unit testing PHP apps with PHPUnit
 
Test your code like a pro - PHPUnit in practice
Test your code like a pro - PHPUnit in practiceTest your code like a pro - PHPUnit in practice
Test your code like a pro - PHPUnit in practice
 
PHPUnit
PHPUnitPHPUnit
PHPUnit
 
Unit Testng with PHP Unit - A Step by Step Training
Unit Testng with PHP Unit - A Step by Step TrainingUnit Testng with PHP Unit - A Step by Step Training
Unit Testng with PHP Unit - A Step by Step Training
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
 
Beginning PHPUnit
Beginning PHPUnitBeginning PHPUnit
Beginning PHPUnit
 
Unit testing
Unit testingUnit testing
Unit testing
 
Unlock The Mystery Of PHPUnit (Wave PHP 2018)
Unlock The Mystery Of PHPUnit (Wave PHP 2018)Unlock The Mystery Of PHPUnit (Wave PHP 2018)
Unlock The Mystery Of PHPUnit (Wave PHP 2018)
 
PHPUnit testing to Zend_Test
PHPUnit testing to Zend_TestPHPUnit testing to Zend_Test
PHPUnit testing to Zend_Test
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Test Driven Development With Python
Test Driven Development With PythonTest Driven Development With Python
Test Driven Development With Python
 
An introduction to Google test framework
An introduction to Google test frameworkAn introduction to Google test framework
An introduction to Google test framework
 
Test in action week 2
Test in action   week 2Test in action   week 2
Test in action week 2
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
 
C++ Unit Test with Google Testing Framework
C++ Unit Test with Google Testing FrameworkC++ Unit Test with Google Testing Framework
C++ Unit Test with Google Testing Framework
 
Phpunit
PhpunitPhpunit
Phpunit
 
Testing Code and Assuring Quality
Testing Code and Assuring QualityTesting Code and Assuring Quality
Testing Code and Assuring Quality
 
Python Unit Test
Python Unit TestPython Unit Test
Python Unit Test
 

Semelhante a Unit Testing Presentation

COMM 166 Final Research Proposal GuidelinesThe proposal should.docx
COMM 166 Final Research Proposal GuidelinesThe proposal should.docxCOMM 166 Final Research Proposal GuidelinesThe proposal should.docx
COMM 166 Final Research Proposal GuidelinesThe proposal should.docx
cargillfilberto
 
COMM 166 Final Research Proposal GuidelinesThe proposal should.docx
COMM 166 Final Research Proposal GuidelinesThe proposal should.docxCOMM 166 Final Research Proposal GuidelinesThe proposal should.docx
COMM 166 Final Research Proposal GuidelinesThe proposal should.docx
drandy1
 
COMM 166 Final Research Proposal GuidelinesThe proposal should.docx
COMM 166 Final Research Proposal GuidelinesThe proposal should.docxCOMM 166 Final Research Proposal GuidelinesThe proposal should.docx
COMM 166 Final Research Proposal GuidelinesThe proposal should.docx
monicafrancis71118
 

Semelhante a Unit Testing Presentation (20)

Lazy Java
Lazy JavaLazy Java
Lazy Java
 
Mario Fusco - Lazy Java - Codemotion Milan 2018
Mario Fusco - Lazy Java - Codemotion Milan 2018Mario Fusco - Lazy Java - Codemotion Milan 2018
Mario Fusco - Lazy Java - Codemotion Milan 2018
 
Lazy java
Lazy javaLazy java
Lazy java
 
Lazy Java
Lazy JavaLazy Java
Lazy Java
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
Intro to Testing in Zope, Plone
Intro to Testing in Zope, PloneIntro to Testing in Zope, Plone
Intro to Testing in Zope, Plone
 
Core java
Core javaCore java
Core java
 
maXbox Starter 36 Software Testing
maXbox Starter 36 Software TestingmaXbox Starter 36 Software Testing
maXbox Starter 36 Software Testing
 
Kamil witecki asynchronous, yet readable, code
Kamil witecki asynchronous, yet readable, codeKamil witecki asynchronous, yet readable, code
Kamil witecki asynchronous, yet readable, code
 
Automated Unit Testing
Automated Unit TestingAutomated Unit Testing
Automated Unit Testing
 
Groovy Basics
Groovy BasicsGroovy Basics
Groovy Basics
 
Quality Assurance
Quality AssuranceQuality Assurance
Quality Assurance
 
COMM 166 Final Research Proposal GuidelinesThe proposal should.docx
COMM 166 Final Research Proposal GuidelinesThe proposal should.docxCOMM 166 Final Research Proposal GuidelinesThe proposal should.docx
COMM 166 Final Research Proposal GuidelinesThe proposal should.docx
 
COMM 166 Final Research Proposal GuidelinesThe proposal should.docx
COMM 166 Final Research Proposal GuidelinesThe proposal should.docxCOMM 166 Final Research Proposal GuidelinesThe proposal should.docx
COMM 166 Final Research Proposal GuidelinesThe proposal should.docx
 
COMM 166 Final Research Proposal GuidelinesThe proposal should.docx
COMM 166 Final Research Proposal GuidelinesThe proposal should.docxCOMM 166 Final Research Proposal GuidelinesThe proposal should.docx
COMM 166 Final Research Proposal GuidelinesThe proposal should.docx
 
Mutation Testing: Start Hunting The Bugs
Mutation Testing: Start Hunting The BugsMutation Testing: Start Hunting The Bugs
Mutation Testing: Start Hunting The Bugs
 
TDD Training
TDD TrainingTDD Training
TDD Training
 
using python module: doctest
using python module: doctestusing python module: doctest
using python module: doctest
 
Unit testing
Unit testingUnit testing
Unit testing
 
Writing tests
Writing testsWriting tests
Writing tests
 

Último

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Último (20)

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 

Unit Testing Presentation

  • 1. Fundamentals of unit testing in PHP usingPHPUnit Nicolas A. Bérard-Nault 5 May 2011
  • 2.
  • 4.
  • 5. Use tests as documentation
  • 6.
  • 7.
  • 8. Member of the xUnitfamily
  • 9. Direct descendant of sUnitwritten by Kent Beck and jUnit, written by Beck and Erich GammaWebsite: http://www.phpunit.de Code coverageisprovidedusing the xDebug extension: http://www.xdebug.org
  • 10. Your first PHPUnittest (1) Goal: test an implementation of ROT13 System under test: functionrot13($text) { $len = strlen($text); for ($i = 0; $i < $len; $i++) { $text{$i} = chr((ord($text{$i}) - ord('a') + 13) % 26 + ord('a')); } return$text; } Initial naïve approach: Formulateexpectedbehavior
  • 11. Your first PHPUnittest (2) Class namehas Test suffix Base class for tests class Rot13Test extendsPHPUnit_Framework_TestCase { public functiontestWord() { $this->assertEquals('cheryl', rot13('purely')); } } Test methodhas test prefix Post-condition verification
  • 12. Your first PHPUnittest (3) nicobn@nicobn-laptop:~$ phpunit rot13.php PHPUnit 3.5.5 by Sebastian Bergmann. . Time: 0 seconds, Memory: 3.50Mb OK (1 test, 1 assertion) The test passes but have wereallycovered all of our bases ?
  • 13. Preconditions, invariants and postconditions functionrot13($text) { $len = strlen($text); for ($i = 0; $i < $len; $i++) { $text{$i} = chr((ord($text{$i}) - ord('a') + 13) % 26 + ord('a')); } return$text; } Precondition: $text must be a string Precondition: $text must belower case Invariant: non-alpha characters must remainunchanged Postcondition: each alpha character must bemoved 13 positions Wescrewed up ! How many more tests do weneed ?
  • 14. NEWFLASH: It’s not a question of how awesomelyawesome of a programmer you are, but a question of methodology ! Sad panda issad
  • 15. Test first ! (1) “Applying ROT13 to a piece of text merely requires examining its alphabetic characters and replacing each one by the letter 13 places further along in the alphabet, wrapping back to the beginning if necessary. A becomes N, B becomes O, and so on up to M, which becomes Z, then the sequence continues at the beginning of the alphabet: N becomes A, O becomes B, and so on to Z, which becomes M. Only those letters which occur in the English alphabet are affected; numbers, symbols, whitespace, and all other characters are left unchanged. Because there are 26 letters in the English alphabet and 26 = 2 × 13, the ROT13 function is its own inverse.” (Wikipedia)
  • 16. Test first ! (2a) functionrot13($text) { } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower() { $this->assertEquals('n', rot13('a')); } } There was 1 failure: 1) Rot13Test::test_A_Lower Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -n +
  • 17. Test first ! (2b) functionrot13($text) { return‘n’; } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower() { $this->assertEquals('n', rot13('a')); } } PHPUnit 3.5.5 by Sebastian Bergmann. . Time: 1 second, Memory: 3.50Mb OK (1 test, 1 assertion)
  • 18. Test first ! (2c) functionrot13($text) { returnchr(ord($text{0}) + 13); } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower() { $this->assertEquals('n', rot13('a')); } } PHPUnit 3.5.5 by Sebastian Bergmann. . Time: 1 second, Memory: 3.50Mb OK (1 test, 1 assertion)
  • 19. Test first ! (3a) functionrot13($text) { returnchr(ord($text{0}) + 13); } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower() { $this->assertEquals('n', rot13('a')); } public function test_N_Lower() { $this->assertEquals(‘a', rot13(‘n')); } } FAIL !
  • 20. Test first ! (3b) functionrot13($text) { return chr((ord($text{0}) - ord('a') + 13) % 26 + ord('a')); } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower() { $this->assertEquals('n', rot13('a')); } public function test_N_Lower() { $this->assertEquals(‘a', rot13(‘n')); } } PASS !
  • 21. Test first ! (4a) functionrot13($text) { return chr((ord($text{0}) - ord('a') + 13) % 26 + ord('a')); } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower() { $this->assertEquals('n', rot13('a')); } public function test_N_Lower() { $this->assertEquals(‘a', rot13(‘n')); } public functiontest_Symbol() { $this->assertEquals('$', rot13('$')); } } FAIL !
  • 22. Test first ! (4b) functionrot13($text) { if (!ctype_alnum($text{0})) { return$text{0}; } return chr((ord($text{0}) - ord('a') + 13) % 26 + ord('a')); } class Rot13Test extendsPHPUnit_Framework_TestCase { public function test_A_Lower() { $this->assertEquals('n', rot13('a')); } public function test_N_Lower() { $this->assertEquals(‘a', rot13(‘n')); } public functiontest_Symbol() { $this->assertEquals('$', rot13('$')); } } PASS !
  • 23. Test first ! (5a) functionrot13($text) { if (!ctype_alnum($text{0})) { return$text{0}; } return chr((ord($text{0}) - ord('a') + 13) % 26 + ord('a')); } class Rot13Test extendsPHPUnit_Framework_TestCase { /* […] */ public functiontest_N_Upper() { $this->assertEquals('A', rot13('N')); } } FAIL !
  • 24. Test first ! (5b) functionrot13($text) { if (!ctype_alnum($text{0})) { return$text{0}; } if (ctype_upper($text{0})) { $delta = ord('A'); } else { $delta = ord('a'); } return chr((ord($text{0}) - $delta + 13) % 26 + $delta); } class Rot13Test extendsPHPUnit_Framework_TestCase { /* […] */ public functiontest_N_Upper() { $this->assertEquals('A', rot13('N')); } } PASS !
  • 25. Test first ! (6a) functionrot13($text) { if (!ctype_alnum($text{0})) { return$text{0}; } if (ctype_upper($text{0})) { $delta = ord('A'); } else { $delta = ord('a'); } return chr((ord($text{0}) - $delta + 13) % 26 + $delta); } class Rot13Test extendsPHPUnit_Framework_TestCase { /* […] */ public functiontest_N_Purely() { $this->assertEquals(‘$purely$', rot13(‘$cheryl$')); } } FAIL !
  • 26. Test first ! (6b) functionrot13($text) { $str = ''; $len = strlen($text); for ($i = 0; $i < $len; $i++) { if (!ctype_alnum($text{$i})) { $str .= $text{$i}; } else { if (ctype_upper($text{$i})) { $delta = ord('A'); } else { $delta = ord('a'); } $str.= chr((ord($text{$i}) - $delta + 13) % 26 + $delta); } } return$str; } PASS !
  • 28. PHPUnit assertions Note: most assertions have a assertNotXXXX() counterpart.
  • 29. Test status Do yourself and yourcolleaguesa favor and mark tests as skipped or incompletewhen relevant !
  • 30. Anatomy of a unit test SETUP: Create the fixture EXERCISE: Execute the system under test (SUT) VERIFY: Check expectations (state mutations, output, invariants, etc.) TEAR DOWN: Clean the fixture
  • 31.
  • 36. Should not harm the developmentprocess in the long runTests, if usedincorrectly, canbedetrimental to a project
  • 37. Principles of test automation 1) INDEPENDANCE: A test should not interactwithanother test (shared mutable state). 2) NO TEST CODE IN PRODUCTION: Ban if ($test). Don’teventhink about it. 3) ISOLATION: Each SUT must beindependant. State mutations duringexerciseshould onlyoccur in and by the SUT. 4) D.R.Y.: Do not repeatyourself. Valid for fixture setup as well as test overlap. 5) CLEAR INTENTIONS: A test shouldbe simple and clearlycommunicateits scope. 6) MINIMIZE UNTESTABLE CODE: Sorry, please replace minimize by eliminate. 7) TEST FIRST: Preventsmostsmells, ensureshighcoverage, providesimmediate feedback. 8) DO NOT TEST YOUR PRIVATES: The need to test a privatemethodis a symptom of a deeperproblem.
  • 38. Exempligratia Symfony2’s routing component: https://github.com/symfony/symfony/blob/master/tests/Symfony/Tests/Component/Routing/Matcher/UrlMatcherTest.php Example of a feeble test (objectcreation code repeated), long test (testMatch). Symfony2’s DOM Crawler: https://github.com/symfony/symfony/blob/master/tests/Symfony/Tests/Component/DomCrawler/CrawlerTest.php Example of utility methods (at the bottom), @covers, SUT factorymethod (createTestCrawler). Symfony2’s HttpKernel component: https://github.com/symfony/symfony/blob/master/tests/Symfony/Tests/Component/HttpKernel/KernelTest.php Example of test doubles.
  • 39. Resources The seminal book on unit testing. Written by Gerard Meszaros. ISBN-13: 978-0131495050