Your SlideShare is downloading. ×
0
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
Unit Testing Presentation
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

Unit Testing Presentation

685

Published on

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
685
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
13
Comments
0
Likes
0
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. Fundamentals of unit testing in PHP usingPHPUnit<br />Nicolas A. Bérard-Nault<br />5 May 2011<br />
  • 2. Some of the goals of test automation<br />For the stakeholders:<br /><ul><li>Improvingexternalqualityby reducingdefectdensity
  • 3. Improvinginternalqualityby increasingmaintainability
  • 4. Reduced short and long-termrisk</li></ul>For the programmers:<br /><ul><li>Facilitatingdefectlocalization
  • 5. Use tests as documentation
  • 6. Use tests as a specification</li></li></ul><li>The automatedtesting continuum<br />Integration tests<br />Unit tests<br />Functional tests<br />« Black box »<br />$$$<br />Slow<br />Functionality<br />« White box »<br />$<br />Fast<br />Code<br />Programmers are definitelyresponsible for these tests<br />QA is (usually) responsible for these tests<br />
  • 7. PHPUnit and the xUnitfamily<br /><ul><li>Written by Sebastian Bergmann
  • 8. Member of the xUnitfamily
  • 9. Direct descendant of sUnitwritten by Kent Beck and jUnit, written by Beck and Erich Gamma</li></ul>Website: http://www.phpunit.de<br />Code coverageisprovidedusing the xDebug extension: http://www.xdebug.org<br />
  • 10. Your first <br />PHPUnittest (1)<br />Goal: test an implementation of ROT13<br />System under test:<br />functionrot13($text)<br />{<br />$len = strlen($text);<br />for ($i = 0; $i < $len; $i++)<br /> {<br />$text{$i} = chr((ord($text{$i}) - ord('a') + 13) % 26 + ord('a'));<br /> }<br />return$text;<br />}<br />Initial naïve approach: Formulateexpectedbehavior<br />
  • 11. Your first <br />PHPUnittest (2)<br />Class namehas Test suffix<br />Base class for tests<br />class Rot13Test extendsPHPUnit_Framework_TestCase<br />{<br />public functiontestWord()<br /> {<br />$this->assertEquals('cheryl', rot13('purely'));<br /> }<br />}<br />Test methodhas test prefix<br />Post-condition verification<br />
  • 12. Your first <br />PHPUnittest (3)<br />nicobn@nicobn-laptop:~$ phpunit rot13.php<br />PHPUnit 3.5.5 by Sebastian Bergmann.<br />.<br />Time: 0 seconds, Memory: 3.50Mb<br />OK (1 test, 1 assertion)<br />The test passes but have wereallycovered all of our bases ?<br />
  • 13. Preconditions, invariants and postconditions<br />functionrot13($text)<br />{<br />$len = strlen($text);<br />for ($i = 0; $i < $len; $i++)<br /> {<br />$text{$i} = chr((ord($text{$i}) - ord('a') + 13) % 26 + ord('a'));<br /> }<br />return$text;<br />}<br />Precondition: $text must be a string<br />Precondition: $text must belower case<br />Invariant: non-alpha characters must remainunchanged<br />Postcondition: each alpha character must bemoved 13 positions <br />Wescrewed up ! How many more tests do weneed ? <br />
  • 14. NEWFLASH: It’s not a question of how awesomelyawesome of a programmer you are, but a question of methodology !<br />Sad panda issad<br />
  • 15. Test first ! (1)<br />“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.”<br />(Wikipedia)<br />
  • 16. Test first ! (2a)<br />functionrot13($text)<br />{<br />}<br />class Rot13Test extendsPHPUnit_Framework_TestCase<br />{<br />public function test_A_Lower()<br /> {<br />$this->assertEquals('n', rot13('a'));<br /> }<br />}<br />There was 1 failure:<br />1) Rot13Test::test_A_Lower<br />Failed asserting that two strings are equal.<br />--- Expected<br />+++ Actual<br />@@ @@<br />-n<br />+<br />
  • 17. Test first ! (2b)<br />functionrot13($text)<br />{<br />return‘n’;<br />}<br />class Rot13Test extendsPHPUnit_Framework_TestCase<br />{<br />public function test_A_Lower()<br /> {<br />$this->assertEquals('n', rot13('a'));<br /> }<br />}<br />PHPUnit 3.5.5 by Sebastian Bergmann.<br />.<br />Time: 1 second, Memory: 3.50Mb<br />OK (1 test, 1 assertion)<br />
  • 18. Test first ! (2c)<br />functionrot13($text)<br />{<br />returnchr(ord($text{0}) + 13);<br />}<br />class Rot13Test extendsPHPUnit_Framework_TestCase<br />{<br />public function test_A_Lower()<br /> {<br />$this->assertEquals('n', rot13('a'));<br /> }<br />}<br />PHPUnit 3.5.5 by Sebastian Bergmann.<br />.<br />Time: 1 second, Memory: 3.50Mb<br />OK (1 test, 1 assertion)<br />
  • 19. Test first ! (3a)<br />functionrot13($text)<br />{<br />returnchr(ord($text{0}) + 13);<br />}<br />class Rot13Test extendsPHPUnit_Framework_TestCase<br />{<br />public function test_A_Lower()<br /> {<br />$this->assertEquals('n', rot13('a'));<br /> }<br />public function test_N_Lower()<br /> {<br />$this->assertEquals(‘a', rot13(‘n'));<br /> }<br />}<br />FAIL !<br />
  • 20. Test first ! (3b)<br />functionrot13($text)<br />{<br />return chr((ord($text{0}) - ord('a') + 13) % 26 + ord('a'));<br />}<br />class Rot13Test extendsPHPUnit_Framework_TestCase<br />{<br />public function test_A_Lower()<br /> {<br />$this->assertEquals('n', rot13('a'));<br /> }<br />public function test_N_Lower()<br /> {<br />$this->assertEquals(‘a', rot13(‘n'));<br /> }<br />}<br />PASS !<br />
  • 21. Test first ! (4a)<br />functionrot13($text)<br />{<br /> return chr((ord($text{0}) - ord('a') + 13) % 26 + ord('a'));<br />}<br />class Rot13Test extendsPHPUnit_Framework_TestCase<br />{<br />public function test_A_Lower()<br /> {<br />$this->assertEquals('n', rot13('a'));<br /> }<br />public function test_N_Lower()<br /> {<br />$this->assertEquals(‘a', rot13(‘n'));<br /> }<br />public functiontest_Symbol()<br /> {<br />$this->assertEquals('$', rot13('$'));<br /> }<br />}<br />FAIL !<br />
  • 22. Test first ! (4b)<br />functionrot13($text)<br />{<br />if (!ctype_alnum($text{0})) {<br />return$text{0};<br /> }<br /> return chr((ord($text{0}) - ord('a') + 13) % 26 + ord('a'));<br />}<br />class Rot13Test extendsPHPUnit_Framework_TestCase<br />{<br />public function test_A_Lower()<br /> {<br />$this->assertEquals('n', rot13('a'));<br /> }<br />public function test_N_Lower()<br /> {<br />$this->assertEquals(‘a', rot13(‘n'));<br /> }<br />public functiontest_Symbol()<br /> {<br />$this->assertEquals('$', rot13('$'));<br /> }<br />}<br />PASS !<br />
  • 23. Test first ! (5a)<br />functionrot13($text)<br />{<br />if (!ctype_alnum($text{0})) {<br />return$text{0};<br /> }<br /> return chr((ord($text{0}) - ord('a') + 13) % 26 + ord('a'));<br />}<br />class Rot13Test extendsPHPUnit_Framework_TestCase<br />{<br />/* […] */<br />public functiontest_N_Upper()<br /> {<br />$this->assertEquals('A', rot13('N'));<br /> }<br />}<br />FAIL !<br />
  • 24. Test first ! (5b)<br />functionrot13($text)<br />{<br />if (!ctype_alnum($text{0})) {<br />return$text{0};<br /> }<br />if (ctype_upper($text{0})) {<br />$delta = ord('A');<br /> } else {<br />$delta = ord('a');<br /> }<br /> return chr((ord($text{0}) - $delta + 13) % 26 + $delta);<br />}<br />class Rot13Test extendsPHPUnit_Framework_TestCase<br />{<br />/* […] */<br />public functiontest_N_Upper()<br /> {<br />$this->assertEquals('A', rot13('N'));<br /> }<br />}<br />PASS !<br />
  • 25. Test first ! (6a)<br />functionrot13($text)<br />{<br />if (!ctype_alnum($text{0})) {<br />return$text{0};<br /> }<br />if (ctype_upper($text{0})) {<br />$delta = ord('A');<br /> } else {<br />$delta = ord('a');<br /> }<br /> return chr((ord($text{0}) - $delta + 13) % 26 + $delta);<br />}<br />class Rot13Test extendsPHPUnit_Framework_TestCase<br />{<br />/* […] */<br />public functiontest_N_Purely()<br /> {<br />$this->assertEquals(‘$purely$', rot13(‘$cheryl$'));<br /> }<br />}<br />FAIL !<br />
  • 26. Test first ! (6b)<br />functionrot13($text)<br />{<br />$str = '';<br />$len = strlen($text);<br />for ($i = 0; $i < $len; $i++)<br /> {<br />if (!ctype_alnum($text{$i})) {<br />$str .= $text{$i};<br /> } else {<br /> if (ctype_upper($text{$i})) {<br />$delta = ord('A');<br /> } else {<br />$delta = ord('a');<br /> }<br />$str.= chr((ord($text{$i}) - $delta + 13) % 26 + $delta);<br /> }<br /> }<br />return$str;<br />}<br />PASS !<br />
  • 27. Test-drivendevelopment<br />RED<br />GREEN<br />REFACTOR<br />
  • 28. PHPUnit assertions<br />Note: most assertions have a assertNotXXXX() counterpart.<br />
  • 29. Test status<br />Do yourself and yourcolleaguesa favor and mark tests as skipped or incompletewhen relevant !<br />
  • 30. Anatomy of a<br />unit test<br />SETUP: Create the fixture<br />EXERCISE: Execute the system under test (SUT)<br />VERIFY: Check expectations (state mutations, output, invariants, etc.)<br />TEAR DOWN: Clean the fixture<br />
  • 31. Whatis a good tests<br /><ul><li>Deterministic
  • 32. FULLY automated
  • 33. Self-checking
  • 34. Simple, robust
  • 35. Expressive
  • 36. Should not harm the developmentprocess in the long run</li></ul>Tests, if usedincorrectly, canbedetrimental to a project<br />
  • 37. Principles of test automation<br />1) INDEPENDANCE: A test should not interactwithanother test (shared mutable state). <br />2) NO TEST CODE IN PRODUCTION: Ban if ($test). Don’teventhink about it.<br />3) ISOLATION: Each SUT must beindependant. State mutations duringexerciseshould<br />onlyoccur in and by the SUT.<br />4) D.R.Y.: Do not repeatyourself. Valid for fixture setup as well as test overlap.<br />5) CLEAR INTENTIONS: A test shouldbe simple and clearlycommunicateits scope.<br />6) MINIMIZE UNTESTABLE CODE: Sorry, please replace minimize by eliminate.<br />7) TEST FIRST: Preventsmostsmells, ensureshighcoverage, providesimmediate feedback.<br />8) DO NOT TEST YOUR PRIVATES: The need to test a privatemethodis a symptom of a deeperproblem.<br />
  • 38. Exempligratia<br />Symfony2’s routing component:<br />https://github.com/symfony/symfony/blob/master/tests/Symfony/Tests/Component/Routing/Matcher/UrlMatcherTest.php<br />Example of a feeble test (objectcreation code repeated), long test (testMatch).<br />Symfony2’s DOM Crawler:<br />https://github.com/symfony/symfony/blob/master/tests/Symfony/Tests/Component/DomCrawler/CrawlerTest.php<br />Example of utility methods (at the bottom), @covers, SUT factorymethod (createTestCrawler). <br />Symfony2’s HttpKernel component:<br />https://github.com/symfony/symfony/blob/master/tests/Symfony/Tests/Component/HttpKernel/KernelTest.php<br />Example of test doubles.<br />
  • 39. Resources<br />The seminal book on unit testing. Written by Gerard Meszaros.<br />ISBN-13: 978-0131495050<br />

×