PHPUnit & You
PHPUnit?

PHPUnit is a test suite framework.

Pretty much the standard in PHP. Used by:
   Zend Framework

   Symfony

   ezComponents and many many more.


Fully featured (more later).
Improvements over
   SimpleTest
Better command line tools.

Better coverage reports.

Better selection of assertions.

Better mock objects.

Better tool chain support.

Pretty much all win.
Assertions
Assertions

Assertions are stricter in PHPUnit.

More assertions to use.

Better reporting on failure

More consistent interface.

Easily extensible.
Stricter

1   <?php
2   $this->assertFalse(array()); // FAIL
3   $this->assertNull(false); // FAIL
4   $this->assertTrue(1); // FAIL
5   $this->assertTrue('oh noes'); // FAIL
Moar
 1   <?php
 2   // General
 3   $this->assertContains('some', 'Awesome');
 4   $this->assertEmpty(array());
 5
 6   // files
 7   $this->assertFileExists('/path/to/file');
 8   $this->assertFileEquals('/path/to/expected', '/path/to/actual');
 9
10   //objects
11   $this->assertInstanceOf('Controller', $thing);
Better failures
 1   1) MyTest::makeSureStuffIsTheSame
 2   Failed asserting that two strings are equal.
 3   --- Expected
 4   +++ Actual
 5   @@ @@
 6    This is some
 7   -text
 8   -on multiple lines
 9   +words
10   +on
11   +a second line
Consistent
1   <?php
2   // Always expected, result
3   $this->assertEquals($expect, $result, $message);
4   $this->assertSame($expect, $result, $message);
5   $this->assertContains($expect, $result, $message);
6   $this->assertInstanceOf($expect, $result, $message);
7   $this->assertRegExp($pattern, $result, $message);
8   $this->assertTrue($result, $message);
9   $this->assertFalse($result, $message);
Extensible
1   <?php
2   // Create new assertions using the built-in ones.
3   function assertJsonEquals($expected, $result, $message = null) {
4       $this->assertEquals(
5           json_encode($expected),
6           json_encode($result),
7           $message
8       );
9   }
Annotations
Annotations

Doc block comment tags that do stuff!

Allows for declarative tests.

Test generators.

Buffering.
Testing exceptions
 1   <?php
 2   /**
 3     * Test to make sure ohNo() explodes
 4     *
 5     * @expectedException RuntimeException
 6     * @expectedExceptionMessage On noes.
 7     * @expectedExceptionCode 25
 8     */
 9   function testSomething() {
10        $this->Thing->ohNo();
11   }
Generators
 1   <?php
 2   public static function dataGenerator() {
 3        return array(
 4            array(1, 1, 2),
 5            array(2, 2, 4)
 6        );
 7   }
 8   /**
 9     * Adding stuff up
10     *
11     * @dataProvider dataGenerator
12     */
13   function testAdding($a, $b, $expected) {
14        $this->assertEquals($expected, $a + $b);
15   }
Output buffering
 1   <?php
 2   /**
 3     * Check saying hello.
 4     *
 5     * @ouputBuffering enabled
 6     */
 7   function testHello() {
 8        $this->Helper->hello('Sam');
 9        $this->assertEquals('Hello Sam', ob_get_contents());
10   }
Fixtures
Fixtures


They are the same!

No really, they are totally the same as before.
Mock Objects
Mock objects

Better built, and a better interface.

More expressive and powerful.

Works with exceptions.

Extensible.
Create a stub
 1 <?php
 2 function testProcess() {
 3     $mock = $this->getMock('AuthorizeNet', 'process');
 4     $mock->expects($this->once())
 5         ->method('process')
 6         ->with($this->Order)
 7         ->will($this->returnValue('Order successful'));
 8
 9     $this->Order->setGateway($mock);
10     $this->Order->process();
11 }


    Stub out expensive resources during testing.
Break stuff
 1 <?php
 2 function testProcessFailure() {
 3     $mock = $this->getMock('AuthorizeNet', array('process'));
 4     $mock->expects($this->at(2))
 5         ->method('process')
 6         ->with($this->Order)
 7         ->will($this->throwException(
 8             new GatewayOrderFailedException()
 9         ));
10
11     $this->Order->setGateway($mock);
12     $this->Order->process();
13 }

         Simulate failures that are hard to test.
Safety check
1   <?php
2   $response = $this->getMock('CakeResponse');
3   $response->expects($this->once())
4       ->method('header')
5       ->with('Location: /posts');
6   $this->Controller->response = $response;
7   $this->Controller->myMethod();



      Check objects are calling others correctly.
Strategies for mocks


Constructor injection.

Setter injection.

You’ll need ways of getting mocks into your code.
Code coverage
Code coverage
How much of your code gets run in your tests.

Requires xDebug.

Comes in several formats:

  Clover format.

  Comprehensive HTML report.

  Single test reports.
Clover reports
Clover reports. XML le that works well with
Jenkins/Hudson.


Console/cake testsuite 
--coverage-clover clover.xml 
app AllTests
Complete HTML
       report
 Full detailed report for your entire project.

 Slower to generate, but more complete.


Console/cake testsuite 
--coverage-html ./webroot/coverage 
app AllTests
¡Sample/Demo!
Individual reports

Single test results, shows coverage for each test
case/group.

Generated at run time.

Faster than comprehensive report.
¡Sample/Demo!
Runners

Command line runner.

Web runner.

Some con gurations have troubles running
sessions in cli. But its a con g option.

Main difference is how you use them.
Demo time!
Continuous
         integration

CakePHP plays nice with Jenkins, and other CI
servers.

Run your tests all the time.

Automate everything.
DEMO!
Questions?

PHPunit and you

  • 1.
  • 2.
    PHPUnit? PHPUnit is atest suite framework. Pretty much the standard in PHP. Used by: Zend Framework Symfony ezComponents and many many more. Fully featured (more later).
  • 3.
    Improvements over SimpleTest Better command line tools. Better coverage reports. Better selection of assertions. Better mock objects. Better tool chain support. Pretty much all win.
  • 4.
  • 5.
    Assertions Assertions are stricterin PHPUnit. More assertions to use. Better reporting on failure More consistent interface. Easily extensible.
  • 6.
    Stricter 1 <?php 2 $this->assertFalse(array()); // FAIL 3 $this->assertNull(false); // FAIL 4 $this->assertTrue(1); // FAIL 5 $this->assertTrue('oh noes'); // FAIL
  • 7.
    Moar 1 <?php 2 // General 3 $this->assertContains('some', 'Awesome'); 4 $this->assertEmpty(array()); 5 6 // files 7 $this->assertFileExists('/path/to/file'); 8 $this->assertFileEquals('/path/to/expected', '/path/to/actual'); 9 10 //objects 11 $this->assertInstanceOf('Controller', $thing);
  • 8.
    Better failures 1 1) MyTest::makeSureStuffIsTheSame 2 Failed asserting that two strings are equal. 3 --- Expected 4 +++ Actual 5 @@ @@ 6 This is some 7 -text 8 -on multiple lines 9 +words 10 +on 11 +a second line
  • 9.
    Consistent 1 <?php 2 // Always expected, result 3 $this->assertEquals($expect, $result, $message); 4 $this->assertSame($expect, $result, $message); 5 $this->assertContains($expect, $result, $message); 6 $this->assertInstanceOf($expect, $result, $message); 7 $this->assertRegExp($pattern, $result, $message); 8 $this->assertTrue($result, $message); 9 $this->assertFalse($result, $message);
  • 10.
    Extensible 1 <?php 2 // Create new assertions using the built-in ones. 3 function assertJsonEquals($expected, $result, $message = null) { 4 $this->assertEquals( 5 json_encode($expected), 6 json_encode($result), 7 $message 8 ); 9 }
  • 11.
  • 12.
    Annotations Doc block commenttags that do stuff! Allows for declarative tests. Test generators. Buffering.
  • 13.
    Testing exceptions 1 <?php 2 /** 3 * Test to make sure ohNo() explodes 4 * 5 * @expectedException RuntimeException 6 * @expectedExceptionMessage On noes. 7 * @expectedExceptionCode 25 8 */ 9 function testSomething() { 10 $this->Thing->ohNo(); 11 }
  • 14.
    Generators 1 <?php 2 public static function dataGenerator() { 3 return array( 4 array(1, 1, 2), 5 array(2, 2, 4) 6 ); 7 } 8 /** 9 * Adding stuff up 10 * 11 * @dataProvider dataGenerator 12 */ 13 function testAdding($a, $b, $expected) { 14 $this->assertEquals($expected, $a + $b); 15 }
  • 15.
    Output buffering 1 <?php 2 /** 3 * Check saying hello. 4 * 5 * @ouputBuffering enabled 6 */ 7 function testHello() { 8 $this->Helper->hello('Sam'); 9 $this->assertEquals('Hello Sam', ob_get_contents()); 10 }
  • 16.
  • 17.
    Fixtures They are thesame! No really, they are totally the same as before.
  • 18.
  • 19.
    Mock objects Better built,and a better interface. More expressive and powerful. Works with exceptions. Extensible.
  • 20.
    Create a stub 1 <?php 2 function testProcess() { 3 $mock = $this->getMock('AuthorizeNet', 'process'); 4 $mock->expects($this->once()) 5 ->method('process') 6 ->with($this->Order) 7 ->will($this->returnValue('Order successful')); 8 9 $this->Order->setGateway($mock); 10 $this->Order->process(); 11 } Stub out expensive resources during testing.
  • 21.
    Break stuff 1<?php 2 function testProcessFailure() { 3 $mock = $this->getMock('AuthorizeNet', array('process')); 4 $mock->expects($this->at(2)) 5 ->method('process') 6 ->with($this->Order) 7 ->will($this->throwException( 8 new GatewayOrderFailedException() 9 )); 10 11 $this->Order->setGateway($mock); 12 $this->Order->process(); 13 } Simulate failures that are hard to test.
  • 22.
    Safety check 1 <?php 2 $response = $this->getMock('CakeResponse'); 3 $response->expects($this->once()) 4 ->method('header') 5 ->with('Location: /posts'); 6 $this->Controller->response = $response; 7 $this->Controller->myMethod(); Check objects are calling others correctly.
  • 23.
    Strategies for mocks Constructorinjection. Setter injection. You’ll need ways of getting mocks into your code.
  • 24.
  • 25.
    Code coverage How muchof your code gets run in your tests. Requires xDebug. Comes in several formats: Clover format. Comprehensive HTML report. Single test reports.
  • 26.
    Clover reports Clover reports.XML le that works well with Jenkins/Hudson. Console/cake testsuite --coverage-clover clover.xml app AllTests
  • 27.
    Complete HTML report Full detailed report for your entire project. Slower to generate, but more complete. Console/cake testsuite --coverage-html ./webroot/coverage app AllTests
  • 28.
  • 29.
    Individual reports Single testresults, shows coverage for each test case/group. Generated at run time. Faster than comprehensive report.
  • 30.
  • 31.
    Runners Command line runner. Webrunner. Some con gurations have troubles running sessions in cli. But its a con g option. Main difference is how you use them.
  • 32.
  • 33.
    Continuous integration CakePHP plays nice with Jenkins, and other CI servers. Run your tests all the time. Automate everything.
  • 34.
  • 35.