Testing your application

by Joeri Timmermans

  • 28 years old
  • Gamer, PHP Developer
    with a passion for Food & Drinks
  • Interactive Multimedia Design
  • Symfony2 @ 
  •      @Joeri_timmer
  •      /pix-art
  •      www.pix-art.be (Blog)

Who am i?

  • What is "Testing"?
  • Debunking the myths
  • Why do Testing?
  • Different types of Testing
  • PHPUnit & Behat
  • Starting with PHPUnit
  • Basic assertions
  • Hello world!
  • Fixtures
  • Mock objects
  • Starting with Behat
  • Mink Extension
  • Page visiting
  • Interesting reads
  • Questions?

// TODO:

What is "Testing"?

Wikipedia:

"Software testing is an investigation conducted to provide stakeholders with information about the quality of the product or service under test."

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 Testing?

Different types of Testing

Unit

System

Integration

Functional

User Acceptance

Performance/Stress

Usability

White Box/ Black Box

Security/ Penetration

PHPUnit

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

Behat

  • Feature/Integration Testing
  • Created by Konstantin Kudryashov
  • Behavior-driven development framework
  •       /Behat/Behat
  • Download phar:
    https://phpunit.de
  • Composer: 
    "phpunit/phpunit": "4.3.*",
    
  • Setup phpunit.xml

Starting with PHPUnit

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

  • 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)
  • Composer: 
    "behat/behat": "^3.0",
    "behat/mink": "^1.6",
    "behat/mink-extension": "^2.0",
    "behat/mink-selenium2-driver": "1.2.0"
  • Setup behat.yml
  • FeatureContext.php

Starting with Behat

behat.yml

default:
    suites:
        functional:
            paths: [ %paths.base%/features ]
            contexts:
                - FeatureContext
    extensions:
        Behat\MinkExtension:
            base_url: http://localhost/
            sessions:
                default:
                    selenium2: ~

FeatureContext.php

<?php


use Behat\MinkExtension\Context\MinkContext;


/**
 * Features context.
 */
class FeatureContext extends MinkContext
{
    /**
     * Initializes context.
     * Every scenario gets its own context object.
     */
    public function __construct()
    {
        // Initialize your context here
    }

    /**
     * @Given /^I wait for (\d+) seconds$/
     */
    public function iWaitForSeconds($seconds)
    {
        $this->getSession()->wait($seconds * 1000);
    }
}

Mink Extension

More info : https://github.com/Behat/MinkExtension

Our first test

#pagevisit.feature

Feature: pagevisit
	This is a standard behat test to see if the given
        page is visited and show the right content

Scenario: When i visit the homepage i should see notifications
    Given I am on "/interactive-multimedia-design-imd"
    Then I should see "Interactive multimedia design (IMD)"
    Then I should see "Professionele Bachelor"

The result!

$ vendor/bin/behat
Feature: pagevisit
	This is a standard behat test to see if the 
        given page is visited and show the right content

  Scenario: When i visit the homepage i should see notifications                          
  # features/pagevisit.feature:4
    Given I am on "/interactive-multimedia-design-imd"                                    
    # FeatureContext::visit()
    Then I should see "Interactive multimedia design (IMD)"                               
    # FeatureContext::assertPageContainsText()
    Then I should see "Professionele Bachelor" 
    # FeatureContext::assertPageContainsText()

1 scenario (1 passed)
3 steps (3 passed)
0m7.77s (13.74Mb)
  • https://phpunit.de/
  • http://www.dragonbe.com/
  • http://www.sitepoint.com/tutorial-introduction-to-unit-testing-in-php-with-phpunit/
  • http://www.pix-art.be/post/testing-your-symfony-application-with-behat

Interesting reads

Questions?

  •                   (www.intracto.com)
  •      @Joeri_timmer
  •      /pix-art
  •      www.pix-art.be (Blog)

Thank you!

https://github.com/pix-art/phpunitdemo

Try it yourself

Testing your application

By Joeri Timmermans

Testing your application

Introduction to Automated Testing with PHPUnit and Behat.

  • 523
Loading comments...

More from Joeri Timmermans