The PHP Unit Testing For Noob

Why Talking About This Topic

  • For the newer of unit testing
  • The adavantages of doing unit testing
  • Talk about some cases

Who Am I?

Chun-Sheng Li

  • 2+ year PHP development
  • Web service development
  • Web application development
  • PHP packages development
  • My Github account

Testing Fundamentals

Testing Fundamentals

What Is Unit Testing?

Survey

Have you ever done unit testing?

Why Doing Unit Testing?

Samples

The Sample Of Unit Testing

The Sample Of Unit Testing

<?php

//Add two numbers class

class AdditionNumber
{
    public function addTwoNumbers($number1, $number2)
    {
        return $number1 + $number2;
    }
}

The Testing Code

<?php

//Add two numbers class
// the version of PHPUnit 4.8 or older.

class AdditionNumberTest extends PHPUnit_Framework_TestCase
{
    public function testAddTwoNumbersCanBeAdded()
    {
        $addition = new AdditionNumber();
        $result = $addition->addTwoNumbers(1, 2);
        $expected = 3;
        
        $this->assertSame($result, $expected);
    }
}

The Testing Code(cont'd)

<?php

// Add two numbers class
// The version of PHPUnit 5.7 or older.
// The prefix "test" style

use PHPUnit/Framework/TestCase;

class AdditionNumberTest extends TestCase
{
    public function testAddTwoNumbersCanBeAdded()
    {
        $addition = new AdditionNumber();
        $result = $addition->addTwoNumbers(1, 2);
        $expected = 3;
        
        $this->assertSame($result, $expected);
    }
}

The Testing Code(cont'd)

<?php

// Add two numbers class.
// the version of PHPUnit 5.7 or older.
// annotation style

use PHPUnit/Framework/TestCase;

class AdditionNumberTest extends TestCase
{
    /** @test */
    public function addTwoNumbersCanBeAdded()
    {
        $addition = new AdditionNumber();
        $result = $addition->addTwoNumbers(1, 2);
        $expected = 3;
        
        $this->assertSame($result, $expected);
    }
}

The phpunit.xml Config File

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

<phpunit
    backupGlobals="false"
    backupStaticAttributes="false"
    bootstrap="/path/to/bootstrap.php"
    colors="true"
    convertErrorsToExceptions="true"
    convertNoticesToExceptions="true"
    convertWarningsToExceptions="true"
    charset="UTF-8"
    processIsolation="false">


The phpunit.xml Config File

    <testsuites>
        <testsuite name="Test Suite Name">
            <directory suffix=".php">./tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory suffix=".php">./src</directory>
        </whitelist>
    </filter>

    <logging>
        <log type="coverage-html" target="/path/to/folder"/>
    </logging>

</phpunit>

Running Unit Testing

Don't forget to install the Xdebug extension

Running Unit Testing

Code Coverage Report

Code Coverage Report

The whole sample project is available here.

Why Doing Unit Testing?

More Examples

YahooWeatherAPI

A PHP library to communicate with Yahoo Weather API.

Project is available here.

Testing Code

  • My first unit testing code snippets.
  • Actually, the annotation should be removed.
  • Don't use prefix and annotation style together.
<?php
/*
 * (c) Jérémy Marodon         <marodon.jeremy@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Th3Mouk\YahooWeatherAPI\Tests;
use GuzzleHttp\Client;
use PHPUnit\Framework\TestCase;
use Th3Mouk\YahooWeatherAPI\YahooWeatherAPI;
class YahooWeatherClientTests extends TestCase
{
    /** @test */
    public function testCallApiWoeidException()
    {
        $service = new YahooWeatherAPI();
        $this->expectException(\Exception::class);
        try {
            $response = $service->callApiWoeid(null);
        } catch (\Exception $e) {
            throw $e;
        }
    }

Testing Code

  • The proper testing method name.
<?php
/*
 * (c) Jérémy Marodon         <marodon.jeremy@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Th3Mouk\YahooWeatherAPI\Tests;
use GuzzleHttp\Client;
use PHPUnit\Framework\TestCase;
use Th3Mouk\YahooWeatherAPI\YahooWeatherAPI;
class YahooWeatherClientTests extends TestCase
{
    public function testCallApiWoeidException()
    {
        $service = new YahooWeatherAPI();
        $this->expectException(\Exception::class);
        try {
            $response = $service->callApiWoeid(null);
        } catch (\Exception $e) {
            throw $e;
        }
    }

Exception Testing

  • The annotation style for testing exceptions.
<?php
/*
 * (c) Jérémy Marodon         <marodon.jeremy@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Th3Mouk\YahooWeatherAPI\Tests;
use GuzzleHttp\Client;
use PHPUnit\Framework\TestCase;
use Th3Mouk\YahooWeatherAPI\YahooWeatherAPI;
class YahooWeatherClientTests extends TestCase
{
    /**
     * @expectedException \Exception
     */
    public function testCallApiWoeidException()
    {
        $service = new YahooWeatherAPI();
        $response = $service->callApiWoeid(null);
    }

Meaning Testing Method Name

Method name Mapped testing method name
callApiWoeid testCallApiWoeidException
callApiCityName testCallApiCityNameException
callApi testCallApiLastResponse
setClient testSetClient
setLastResponse testSetLastResponse

Find Bugs

OpenWeatherMap-PHP-Api

A PHP API to parse weather data and weather history from OpenWeatherMap.org.

Project is available here

Code Coverage

Determine How Much Code Is Being Tested!

Unit Testing Improvement

Original Code Coverage Percent

Unit Testing Improvement

New Code Coverage Percent

Find Issues

  • Replace sprintf with str_replace in Weather.php.
  • Replace json_last_error_msg with json_last_error in OpenWeatherMap.php.
  • Replace the "#" with ";" for ini file.

str_replace Problem

json_last_error_msg Problem

Comment Problem

php-youtube-api

PHP wrapper for the Youtube Data API v3 ( Non-OAuth )

Project is available here.

The Current Code Coverage

Find Issues

  • In Youtube.php, the line 629 should check whether the array length is zero.
  • The Youtube class constructor adds the optional parameter to let users add the specified ca cert file.

Check The Array Length

CA Cert File Problems

One More Thing...

Travis-CI

The Public Continuous Integration Service

Enable Your Specified Project

Set Your Proper .travis.yml

language: php

sudo: false

php:
  - 5.3
  - 5.4
  - 5.5
  - 5.6
  - 7.0
  - nightly

matrix:
  fast_finish: true
  allow_failures:
    - php: nightly

before_install:
  - phpenv config-rm xdebug.ini


Create Your .travis.yml

install:
  - mkdir -p ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d
  - echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
  - mkdir -p build/logs
  - composer global require satooshi/php-coveralls:@stable --no-update
  - composer global update --prefer-dist --no-interaction
  - composer update --prefer-dist --no-interaction $COMPOSER_FLAGS

before_script:
  - echo "zend_extension=xdebug.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini

script:
  - vendor/bin/phpunit

Enable Your Favorite Code Coverage Service

Add Proper Configuration In .travis.yml

after_success:
  - bash <(curl -s https://codecov.io/bash)

Running Task!

Check Out The Job Log

That's All!

Summary

  • Do unit testing right now!
  • Using travis-ci service
  • Contribute the projects :)

Thank You For Your Listening!