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

PHPUnit Workshop CCXX13

Joshua Thijssen
November 07, 2013
190

PHPUnit Workshop CCXX13

Joshua Thijssen

November 07, 2013
Tweet

Transcript

  1. 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: [email protected] Twitter: @jaytaph
  2. 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..
  3. TechAdemy.nl • Unit testing • Integration testing • Stress testing

    • Regression testing • Acceptance testing • A/B testing • Security testing • Usability testing Much more....
  4. 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); } }
  5. 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)); } }
  6. 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)); } }
  7. 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)
  8. 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.
  9. 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!
  10. TechAdemy.nl • writing tests increases coding time. • writing tests

    decreases debug time. • overall decreases development time.
  11. 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 ?
  12. TechAdemy.nl <?php class fooTest extends PHPUnit_Framework_TestCase { public function testBlahBlah()

    { $foo = new Bar(); .... } public function testBlah() { $foo = new Bar(); .... } }
  13. 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() { .... } }
  14. TechAdemy.nl <?php class fooTest extends PHPUnit_Framework_TestCase { public function testFoo()

    { .... } /** * @depends testFoo */ public function testBar() { .... } }
  15. 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); ... } }
  16. 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) ); } }
  17. 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) { } } }
  18. TechAdemy.nl <?php class fooTest extends PHPUnit_Framework_TestCase { /** * @expectedException

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

    { $this->setExpectedException(“Exception”); $foo = new Foo(); $foo->functionWithException(); } }
  20. 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; } }
  21. 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); } }
  22. TechAdemy.nl <?php include_once "mail.php"; class mailTest extends PHPUnit_Framework_TestCase { ...

    public function testMail() { $mailer = new MyMailer(); $mailer->setSubject("blaat"); $mailer->setFrom("[email protected]"); $mailer->setBody("meeh"); $to = array("[email protected]", "[email protected]", "[email protected]"); $this->assertEquals($mailer->mail($to), 3); } }
  23. 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("[email protected]"); $mailer->setBody("meeh"); $to = array("[email protected]", "[email protected]", "[email protected]"); $this->assertEquals($mailer->mail($to), 3); } }
  24. 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("[email protected]"); $stub->setBody("meeh"); $to = array("[email protected]", "[email protected]", "[email protected]"); $this->assertEquals($stub->mail($to), 3); } }
  25. TechAdemy.nl If you find that you cannot test your code

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

    $psp->setAmount($article->getAmount()); return $psp->pay(); }
  27. 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(); }
  28. 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); }
  29. 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); }