Unit Testing with PHPUnit

by Joeri Timmermans

  • What is Unit Testing?
  • Debunking the myths
  • Why do Unit Testing?
  • PHPUnit
  • Starting with PHPUnit
  • Basic assertions
  • Hello world!
  • Fixtures
  • Mock objects
  • Interesting reads
  • Questions?

//TODO:

What is Unit Testing?

 

Wikipedia:

"Unit testing is a software testing method by which individual units of source code are tested to determine if they are fit for use"

Debunking the myths

  • It Takes Too Long
  • There’s No Need to Test:
    My Code Already Works!
  • Expensive
  • It’s No Fun
  • Automation
  • Readable code == Testable code
  • Test code on functionality
  • Reduce bugs in new and existing features
  • Reduce cost of changes
  • Easier refactoring
  • Progress indication of the project
  • Alerts generation for CI-tools
  • Forces you to slow down and think
  • Speed up development and reduce fear

Why do (Unit) Testing

PHPUnit

  • Created by Sebastian Bergmann
  • Part of xUnit Family
  •      /sebastianbergmann/phpunit

Starting with PHPUnit

  • Download phar:
    https://phpunit.de
     
  • Composer:
    "phpunit/phpunit": "^8"
     
  • Setup phpunit.xml

phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>

<phpunit
    backupGlobals               = "false" backupStaticAttributes      = "false"
    colors                      = "true" convertErrorsToExceptions   = "true"
    convertNoticesToExceptions  = "true" convertWarningsToExceptions = "true"
    processIsolation            = "false" stopOnFailure               = "false"
    syntaxCheck                 = "false" bootstrap                   = "bootstrap.php.cache" >

    <testsuites>
        <testsuite name="Project Test Suite">
            <directory>../src/*/*Bundle/Tests</directory>
            <directory>../src/*/Bundle/*Bundle/Tests</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>../src</directory>
            <exclude>
                <directory>../src/*/*Bundle/Resources</directory>
                <directory>../src/*/*Bundle/Tests</directory>
                <directory>../src/*/Bundle/*Bundle/Resources</directory>
                <directory>../src/*/Bundle/*Bundle/Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>

Basic assertions

  • AssertTrue/AssertFalse - Check the input to verify it equals true/false

  • AssertEquals - Check the result against another input for a match

  • AssertGreaterThan - Check the result to see if it’s larger than a value
    (there’s also LessThan, GreaterThanOrEqual, and LessThanOrEqual)

  • AssertContains - Check that the input contains a certain value

  • AssertType - Check that a variable is of a certain type

  • AssertNull - Check that a variable is null

  • AssertFileExists - Verify that a file exists

  • AssertRegExp - Check the input against a regular expression

  • ...

Hello world!

<?php 

namespace Example;

class HelloWorld
{
	public $helloWorld;

	public function __construct($string = 'Hello World!')
	{
		$this->helloWorld = $string;
	}

	public function sayHello()
	{
		return $this->helloWorld;
	}
}

Our first test

<?php

namespace Example;

class HelloWorldTest extends \PHPUnit_Framework_TestCase
{

    public function testSayHello()
    {        
        $hw = new HelloWorld();
        $string = $hw->sayHello();
        $this->assertEquals('Hello World!', $string);
    }

}

The result!

PHPUnit 4.2.5 by Sebastian Bergmann.

Configuration read from /var/www/example/build/phpunit.xml

.

Time: 70 ms, Memory: 3.50Mb

OK (1 test, 1 assertion)

Fixtures

  • "Known state" of an application
    • needs to be "set up" at start
    • needs to be "torn down" at end
    • shares "states" over test methods
<?php

namespace Example;

class MyListTest extends \PHPUnit_Framework_TestCase
{

    protected $myList;

    public function setUp()
    {
        $this->myList = array();
    }

    public function testMyListEmpty()
    {
        $this->assertEquals(0, sizeof($this->myList));
    }

    public function testMyListHasOne()
    {
        array_push($this->myList, 'myItem');
        $this->assertEquals(1, sizeof($this->myList));
    }

    public function tearDown()
    {
        unset($this->myList);
    }
    
}

The result!

PHPUnit 4.2.5 by Sebastian Bergmann.

Configuration read from /var/www/example/build/phpunit.xml

..

Time: 67 ms, Memory: 3.50Mb

OK (2 tests, 2 assertions)

Mock objects

  • Simulated objects
  • Mimics API or behaviour
  • In a controlled way
  • To test real objects

Mock objects

<?php 

namespace Example;

class HelloMailer
{
	public $mailer;

	public function __construct(Mailer $mailer)
	{
		$this->mailer = $mailer;
	}

	public function sendMessage($message)
	{
		return $this->mailer->send($message);
	}
}
<?php

namespace Example;

class HelloMailerTest extends \PHPUnit_Framework_TestCase
{
    protected $mailer;

    public function setUp()
    {
        $mailer = $this->getMockBuilder('Example\Mailer')
                           ->setMockClassName('Mailer')
                           ->disableOriginalConstructor()
                           ->setMethods(array('send'))
                           ->getMock();

        $mailer->expects($this->any())
                   ->method('send')
                   ->with($this->equalTo('Hello mailer!'))
                   ->will($this->returnValue(true));

        $this->mailer = $mailer;
    }

    public function testSend()
    {   
        $hm = new HelloMailer($this->mailer);

        $response = $hm->sendMessage('Hello mailer!');
        $this->assertTrue($response);
    }

}

The result!

PHPUnit 4.2.5 by Sebastian Bergmann.

Configuration read from /var/www/example/build/phpunit.xml

.

Time: 80 ms, Memory: 4.00Mb

OK (1 test, 1 assertion)

Interesting reads

  • https://phpunit.de/
  • http://www.dragonbe.com/
  • http://www.sitepoint.com/tutorial-introduction-to-unit-testing-in-php-with-phpunit/

Questions?

Thank you

  •      @Joeri_timmer
  •      /pix-art
  •      www.pix-art.be