PhpUnit Best Practices


Published on

My 25 minutes "PHPUnit - Best practices" talk from the 2013 fosdem.

Published in: Technology

PhpUnit Best Practices

  1. PHPUNIT BEST PRACTICES Volker Dusch / @_ _edorian
  2. ABOUT MESoftware EngineerPHP since 11 yearsCICleanCodeDevOpsTDDShippingBullet points
  4. WORKING FORResearchGate gives science back to the people who make it happen. We help researchers build reputation and accelerate scientific progress. On their terms.
  5. GET IN TOUCHstackoverflow:Twitter: @__edoriang+: Volker DuschIRC: edorianMail:
  6. AGENDASome practices I valueYour mileage may varyBy no means complete
  7. WRITE TESTSIts sounds obvious but getting started sometimes is the hardest part!
  8. THE FASTEST THING YOU CAN DOht=cr - saigpoetcm|ge oi: |w -` is`ul s tgn.rjc.o rp Lgn c l;ts $is-q1| eh "rnpg err" et ht e | co Fotae ro! Staging server Testing your builds All without even touching PHPUnitdt=lgnts&asotscr&sf"crTkn aa"oi=etpswr=euecr=$sfoeht=cr - PS - saigpoetcm|ge el,tsue|w -` is`ul X OT d tgn.rjc.o rp Hlo etsr c l;ts $is-q1| eh "oi err" et ht e | co Lgn ro!
  9. LETS GO
  11. PHARwe ht:/erppntd/e/ gt tp/pa.hui.egtppntpacmd+ ppntpa ho x -vrin / -eso orwe ht:/erppntd/e/ gt tp/pa.hui.egtppntpacmd+ ppntpa ho x hui.hrm ppntpa /s/oa/i/hui v urlclbnppntppnt-vrin hui -eso
  12. COMPOSER The Dependency Manager for PHPWith the best from zypper, bundler, pip, gem and npm
  13. PHPUNIT PER opsrjo{ "eur-e" { rqiedv: "hui/hui" ".." ppntppnt: 37* }}cmoe isal opsr ntl.vno/i/hui -vrin /edrbnppnt -eso
  14. PHPUNIT GLOBAL INSTALL{ "eur" { rqie: "hui/hui" ".." ppntppnt: 37* }, "ofg:{ cni" "i-i" "urlclbn" bndr: /s/oa/i/ }}sd ppcmoe isal uo h opsr ntllppni -vrin huut -eso
  15. PEARpear config-set auto_discover 1pear install --version
  16. USE SPECIFIC ASSERTIONS PHPUnit ships with over 90 assertions. Use them to get pretty and helpful error messages.
  17. assertTrue vs assertInstanceOf$o =nwSdls(; fo e tCas)$hs>setre$o isacO Cutbe; ti-asrTu(fo ntnef onal) “Failed asserting that false is true.”$o =nwSdls(; fo e tCas)$hs>setntnefonal $o) ti-asrIsacO(Cutbe, fo; “Failed asserting that stdClass() is an instance of interface Countable.”
  18. assertEquals vs assertJsonStringEqualsJsonFile assertEquals Fie asrigta tosrnsaeeul ald setn ht w tig r qa. --Epce - xetd ++Ata + cul @ @ @ @ -{"ofrne:"ODM,"ak:"HUi" "SN:"paety,"huot Cneec" FSE" Tl" PPnt, JO" Aprnl" Sotu" :"ekn"} Jnis +{"ofrne:"ODM,"ak:"HUi" "SN:"paety,"huot Cneec" FSE" Tl" PPnt, JO" Aprnl" Sotu" :"usn } Hdo"
  19. assertEquals vs assertJsonStringEqualsJsonFile assertJsonStringEqualsJsonFile Fie asrigta toojcsaeeul ald setn ht w bet r qa. --Epce - xetd ++Ata + cul @ @ @ @ sdls Ojc ( tCas bet ofrne = ODM Cneec > FSE ak = HUi Tl > PPnt SN = paety JO > Aprnl - huot = ekn Sotu > Jnis + huot = usn Sotu > Hdo )
  20. HAVE A FAST TEST SUITE If it takes to long to run your tests you wont do it
  22. BY FOLDER STRUCTURE.|-sc - r| `-fo - o| `-br - a| `-Bzpp - a.h`-tss - et |-fntoa - ucinl |-itgain - nerto |-ui - nt | `-fo - o | `-br - a | `-Bzetpp - aTs.h `-wb - eppnttssui hui et/nt
  23. BY CONFIG FILE<etuts tssie> <etut nm=Ui"sfi=Ts.h" tssie ae"nt ufx"etpp> <ietr>et<drcoy drcoytss/ietr> <tssie /etut> <etut nm=Itgain sfi=Ts.nerto.h" tssie ae"nerto" ufx"etItgainpp> <ietr>et<drcoy drcoytss/ietr> <tssie /etut><tssie> /etutsppnt-tssieUi hui -etut nt
  24. OR HOWEVER YOU SEE FITUse @groupUse @filter and naming conventions
  25. BOOTSTRAP ONLY WHAT YOU NEED You can use a test listener: pbi fnto satetut(HUi_rmwr_etut $ut) ulc ucin trTsSiePPntFaeokTsSie sie { / Js a eapeo wa i psil / ut n xml f ht s osbe rqie_DR_.$ut-gtae).otta.h eur _I_ sie>eNm( Bosrppp; }
  26. HOW MANY TESTS? Web: 7 Funtional: One per feature Integration: One per 3 classes Unit: Find a balance*totally made up numbers to drive home the point Im trying to make
  27. WEB TESTS?behat (mink) for js-through-the-server testing - Great for testingyour whole stack Really hard to maintain Mink relives some of the painTest through your front controller instead of the webserver withbehat or phpunit Faster, easier once set up
  28. TEST CLASSES, NOT METHODS > Unit testing, in PHP, is about testing the observable behaviors of a class!Observable from the outside! Nobody cares about the internal state of a class if it never changes the outcome of a method call.
  29. SAMPLE What should we test there? pbi fnto stau(vle { ulc ucin eVle$au) $hs>au =$au; ti-vle vle } pbi fnto eeue){ ulc ucin xct( i ($hs>au){ f !ti-vle trwnwEcpin"oVle n go"; ho e xeto(N au, o od) } rtr $au *1;/ bsns lgc eun vle 0 / uies oi }If we dont call setValue calling execute will throw an exceptionIf we do call setValue calling execute will return the computedresult.So we are testing two behaviors of your class and not the methods inisolation!
  30. RELEVANT BEHAVIORS What to test then?return values pbi fcinclisoaehi(dgesaehi){ ulc uto ecuTFrnet$ereFrnet rtr (dgesaehi -3)*5⁄9 eun $ereFrnet 2 ; }method calls to other objects pbi fcinsoCr){ ulc uto tpa( $hs>adra-egg(; ti-hnbek>nae) $hs>nie>hton) ti-egn-sudw(; }Global state pbi fcinaodhshrPsil(lgesg){ ulc uto viTiWeeosbe$oMsae fl_u_otnssai:$OFL,$oMsae FL_PED; ieptcnet(ttc:LGIE lgesg, IEAPN) $SSINocls]+ _ESO[lgal+; }
  31. DONT TEST GETTERS AND SETTERS One test case per behaviorYou waste timeYour code coverage reports wont tell you about dead codeIf they dont impact the outcome delete them
  32. QUESTIONS? “The secret in testing is in writing testable code” - Miško Hevery Additional resources"The Clean Code Talks -- Unit TestingHow to Write Clean, Testable CodeThe Clean Code Talks - Dont Look For Things!Flaw: Brittle Global State & Singletonsstatic considered harmfulThe UNIT in unit testingAn introduction to PHPUnits @covers annotation