Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHPUnit Workshop CCXX13

1761ecd7fe763583553dde43e62c47bd?s=47 Joshua Thijssen
November 07, 2013
120

PHPUnit Workshop CCXX13

1761ecd7fe763583553dde43e62c47bd?s=128

Joshua Thijssen

November 07, 2013
Tweet

Transcript

  1. TechAdemy.nl PHPUNIT An introduction into unit-testing with PHP

  2. TechAdemy.nl WELCOME!

  3. TechAdemy.nl Joshua Thijssen Freelance consultant, developer and trainer @ NoxLogic

    & TechAdemy Founder of the Dutch Web Alliance. Development in PHP, Python, C, Java. Lead developer of Saffire. Blog: http://adayinthelifeof.nl Email: jthijssen@noxlogic.nl Twitter: @jaytaph
  4. TechAdemy.nl http://www.techademy.nl

  5. TechAdemy.nl

  6. TechAdemy.nl schedule • A mind-numbing and dreaded talk about unit-testing.

    • Hours and hours of trying to setup our systems for PHPUnit. • Spending ages on trying our first unit tests. • Never ever reaching the advanced stuff..
  7. TechAdemy.nl What is unit testing?

  8. TechAdemy.nl • Unit testing • Integration testing • Stress testing

    • Regression testing • Acceptance testing • A/B testing • Security testing • Usability testing Much more....
  9. TechAdemy.nl FooTest.php: Foo.php <?php class foo { public function baz()

    { return 1; } } <?php require “Foo.php”; class fooTest extends PHPUnit_Framework_TestCase { public function testBlahBlah() { $foo = new Foo(); $this->assertEquals($foo->baz(), 1); } }
  10. TechAdemy.nl

  11. TechAdemy.nl FooTest.php: Foo.php <?php class foo { public function baz()

    { return 1; } public function isOdd($number) { if (($number & 1) == 1) { return true; } else { return false; } } } <?php include_once "Foo.php"; class fooTest extends PHPUnit_Framework_TestCase { public function testBlahBlah() { $foo = new Foo(); $this->assertEquals($foo->baz(), 1); } public function testIsOdd() { $foo = new Foo(); $this->assertTrue($foo->isOdd(1)); } }
  12. TechAdemy.nl

  13. TechAdemy.nl FooTest.php: <?php include_once "foo.php"; class fooTest extends PHPUnit_Framework_TestCase {

    public function testBlahBlah() { $foo = new Foo(); $this->assertEquals($foo->baz(), 1); } public function testIsOdd() { $foo = new Foo(); $this->assertTrue($foo->isOdd(1)); } public function testDoesIsOddReturnFalseWhenAnEvenDigitIsGiven { $foo = new Foo(); $this->assertFalse($foo->isOdd(2)); } }
  14. TechAdemy.nl

  15. TechAdemy.nl This is it! You’re done! go home! really!

  16. TechAdemy.nl • Every test must be able to be executed

    separately and without dependencies. • Test “units”, not “applications” • MVC: controller tests, but these are not unit tests. • Be careful with external resources (DB, Mail, HTTP etc)
  17. TechAdemy.nl • Don’t strive for 100% code coverage. • Not

    important, and probably not realistically possible • High code coverage != great tests! • Code coverage the hotspots.
  18. TechAdemy.nl Why write unit-tests?

  19. TechAdemy.nl • Developers should code properly in the first place!

    • We don’t have time enough to do unittesting! • Tests keep failing. We can’t change our whole base! • Too much to test!
  20. TechAdemy.nl • writing tests increases coding time. • writing tests

    decreases debug time. • overall decreases development time.
  21. TechAdemy.nl • Is your code working as intended ? •

    Are old bugs not returned by accident (merges) ? • Are new bugs not introduced ? • Is your architecture flexible enough ?
  22. TechAdemy.nl phpunit advanced • setUp(), tearDown() • @depends • @dataproviders

    • @exception • mocking & stubbing
  23. TechAdemy.nl <?php class fooTest extends PHPUnit_Framework_TestCase { public function testBlahBlah()

    { $foo = new Bar(); .... } public function testBlah() { $foo = new Bar(); .... } }
  24. TechAdemy.nl <?php class fooTest extends PHPUnit_Framework_TestCase { public setUp() {

    $this->_foo = new Bar(); } public tearDown() { unset($this->_foo); } public function testBlahBlah() { .... } public function testBlah() { .... } }
  25. TechAdemy.nl <?php class fooTest extends PHPUnit_Framework_TestCase { public function testFoo()

    { .... } /** * @depends testFoo */ public function testBar() { .... } }
  26. TechAdemy.nl Annotations have to be inside docblocks, not comments! comment

    = /* hello */ docblock = /** hello */
  27. TechAdemy.nl <?php class fooTest extends PHPUnit_Framework_TestCase { public function testCount()

    { $foo = new Foo(); $this->assertEquals($foo->add(1, 2), 3); $this->assertEquals($foo->add(10,-4), 6); $this->assertEquals($foo->add(4, 6), 10); ... } }
  28. TechAdemy.nl <?php class fooTest extends PHPUnit_Framework_TestCase { /** * @dataprovider

    countProvider */ public function testCount($a, $b, $c) { $foo = new Foo(); $this->assertEquals($foo->add($a, $b), $c); } public function countProvider() { return array( array(1, 2, 3), array(10, -4, 6), array(4, 6, 10) ); } }
  29. TechAdemy.nl <?php class fooTest extends PHPUnit_Framework_TestCase { public function testCount()

    { $foo = new Foo(); try { $foo->functionWithException(); $this->fail(“An exception should have occurred”); } catch (Exception $e) { } } }
  30. TechAdemy.nl <?php class fooTest extends PHPUnit_Framework_TestCase { /** * @expectedException

    Exception */ public function testCount() { $foo = new Foo(); $foo->functionWithException(); } }
  31. TechAdemy.nl <?php class fooTest extends PHPUnit_Framework_TestCase { public function testCount()

    { $this->setExpectedException(“Exception”); $foo = new Foo(); $foo->functionWithException(); } }
  32. TechAdemy.nl Mocking & Stubbing

  33. TechAdemy.nl untestable code!

  34. TechAdemy.nl <?php class MyMailer { protected $_from; protected $_body; protected

    $_subject; function setFrom($from) { $this->_from = $from; } ....... function mail(array $to) { $count = 0; foreach ($to as $recipient) { if (mail($recipient, $this->_subject, $this->_body)) $count++; } return $count; } }
  35. TechAdemy.nl <?php class MyMailer { protected $_from; protected $_body; protected

    $_subject; function setFrom($from) { $this->_from = $from; } ....... function mail(array $to) { $count = 0; foreach ($to as $recipient) { if ($this->_mail($recipient)) $count++; } return $count; } protected function _mail($to) { return mail($to, $this->_subject, $this->_body); } }
  36. TechAdemy.nl <?php include_once "mail.php"; class mailTest extends PHPUnit_Framework_TestCase { ...

    public function testMail() { $mailer = new MyMailer(); $mailer->setSubject("blaat"); $mailer->setFrom("jthijssen@example.com"); $mailer->setBody("meeh"); $to = array("aap@example.com", "blaat@example.com", "all@example.com"); $this->assertEquals($mailer->mail($to), 3); } }
  37. TechAdemy.nl <?php include_once "mail.php"; class Mock_MyMailer extends MyMailer { protected

    function _mail($to) { return true; } } class mailTest extends PHPUnit_Framework_TestCase { ... public function testMail() { $mailer = new Mock_MyMailer(); $mailer->setSubject("blaat"); $mailer->setFrom("jthijssen@example.com"); $mailer->setBody("meeh"); $to = array("aap@example.com", "blaat@example.com", "all@example.com"); $this->assertEquals($mailer->mail($to), 3); } }
  38. TechAdemy.nl <?php class mailTest extends PHPUnit_Framework_TestCase { public function testMail()

    { $stub = $this->getMockBuilder('MyMailer', array('_mail'))->getMock(); $stub->expects($this->any()) ->method('_mail') ->will($this->returnValue(true)); $stub->setSubject("blaat"); $stub->setFrom("jthijssen@example.com"); $stub->setBody("meeh"); $to = array("aap@example.com", "blaat@example.com", "all@example.com"); $this->assertEquals($stub->mail($to), 3); } }
  39. TechAdemy.nl If you find that you cannot test your code

    through PHPUnit, you are doing it wrong!
  40. TechAdemy.nl public function pay(Article $article) { $psp = new PaymentProvider();

    $psp->setAmount($article->getAmount()); return $psp->pay(); }
  41. TechAdemy.nl public function setPaymentProvider(PaymentProvider $psp) { $this->_psp = $psp; }

    public function getPaymentProvider() { return $this->_psp; } public function pay(Article $article) { $psp = $this->getPaymentProvider(); $psp->setAmount($article->getAmount()); return $psp->pay(); }
  42. TechAdemy.nl public function testPayAccepted() { $stub = $this->getMockBuilder(‘paymentprovider’, array(‘pay’))->getMock(); $stub->expects($this->any())

    ->method(‘pay’) ->will($this->returnValue(true)); $article = new Article(); $article->setAmount(15); $foo = new Foo(); $foo->setPaymentProvider($stub); $this->assertTrue($foo->pay($article)); $this->assertEquals($user->getAmount(), 85); }
  43. TechAdemy.nl public function testPayFailed() { $stub = $this->getMockBuilder(‘paymentprovider’, array(‘pay’))->getMock(); $stub->expects($this->any())

    ->method(‘pay’) ->will($this->returnValue(false)); $article = new Article(); $article->setAmount(15); $foo = new Foo(); $foo->setPaymentProvider($stub); $this->assertFalse($foo->pay($article)); $this->assertEquals($user->getAmount(), 100); }