Overview

Writing proper tests can assist in writing better software. If you set up proper test cases you can eliminate most functional bugs and better maintain your software.

Integrating PHPUnit with Phalcon

Если вы еще не установили PHPUnit, вы можете сделать это с помощью следующей команды:

composer require phpunit/phpunit:^5.0

или вручную добавить его в composer.json:

<br />{
    "require-dev": {
        "phpunit/phpunit": "^5.0"
    }
}

После установки PHPUnit ​​создайте директорию tests в корне проекта:

app/
public/
tests/

Далее, нам понадобится “хелпер” для подготовки приложения к модульному тестированию.

The PHPUnit helper file

A helper file is required to bootstrap the application for running the tests. We have prepared a sample file. Put the file in your tests/ directory as TestHelper.php.

<?php

use Phalcon\Di;
use Phalcon\Di\FactoryDefault;
use Phalcon\Loader;

ini_set("display_errors", 1);
error_reporting(E_ALL);

define("ROOT_PATH", __DIR__);

 set_include_path(
    ROOT_PATH . PATH_SEPARATOR . get_include_path()
);

// Необходим для phalcon/incubator
include __DIR__ . "/../vendor/autoload.php";

// Используем автозагрузчик приложений для автозагрузки классов.
$loader = new Loader();

$loader->registerDirs(
    [
        ROOT_PATH, 
    ]
);

$loader->register();

$di = new FactoryDefault();

Di::reset();

// Здесь можно добавить любые необходимые сервисы в контейнер зависимостей

Di::setDefault($di);

Если вам необходимо протестировать какой-либо компонент из вашей библиотеки компонентов, добавьте его в автозагрузчик или используйте автозагрузчик вашего основного приложения.

Для облегчения написания модульных тестов, мы создали несколько абстрактных классов, которые вы можете использовать для настройки самих тестов. Вы можете получить их из Инкубатора.

Вы можете использовать Инкубатор, добавив его в качестве зависимости:

composer require phalcon/incubator

или вручную добавить его в composer.json:

{
    "require": {
        "phalcon/incubator": "^3.2"
    }
}

Вы также можете склонировать репозиторий, используя ссылку: https://github.com/phalcon/incubator.

The phpunit.xml file

Теперь создайте файл phpunit.xml как показано ниже:

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

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

    <testsuite name="Phalcon - Testsuite">
        <directory>./</directory>
    </testsuite>
</phpunit>

Modify the phpunit.xml to fit your needs and save it in tests. This will run any tests under the tests directory.

Sample Unit Test

To run any Unit Tests you need to define them. The autoloader will make sure the proper files are loaded so all you need to do is create the files and phpunit will run the tests for you.

This example does not contain a config file, most test cases however, do need one. You can add it to the DI to get the UnitTestCase file.

First create a base Unit Test called UnitTestCase.php in your tests directory:

<?php

use Phalcon\Di;
use Phalcon\Test\UnitTestCase as PhalconTestCase;

abstract class UnitTestCase extends PhalconTestCase
{
    /**
     * @var bool
     */
    private $_loaded = false;

    public function setUp()
    {
        parent::setUp();

        // Load any additional services that might be required during testing
        $di = Di::getDefault();

        // Get any DI components here. If you have a config, be sure to pass it to the parent

        $this->setDi($di);

        $this->_loaded = true;
    }

    /**
     * Check if the test case is setup properly
     *
     * @throws \PHPUnit_Framework_IncompleteTestError;
     */
    public function __destruct()
    {
        if (!$this->_loaded) {
            throw new \PHPUnit_Framework_IncompleteTestError(
                "Please run parent::setUp()."
            );
        }
    }
}

It’s always a good idea to separate your Unit Tests in namespaces. For this test we will create the namespace ‘Test’. So create a file called tests\Test\UnitTest.php:

<?php

namespace Test;

/**
 * Class UnitTest
 */
class UnitTest extends \UnitTestCase
{
    public function testTestCase()
    {
        $this->assertEquals(
            "works",
            "works",
            "This is OK"
        );

        $this->assertEquals(
            "works",
            "works1",
            "This will fail"
        );
    }
}

Now when you execute phpunit in your command-line from the tests directory you will get the following output:

$ phpunit
PHPUnit 3.7.23 by Sebastian Bergmann.

Configuration read from /var/www/tests/phpunit.xml

Time: 3 ms, Memory: 3.45Mb

There was 1 failure:

1) Test\UnitTest::testTestCase
This will fail
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'works'
+'works1'

/var/www/tests/Test/UnitTest.php:25

FAILURES!
Tests: 1, Assertions: 2, Failures: 1.

Now you can start building your Unit Tests. You can view a good guide here. We also recommend reading the PHPUnit documentation if you’re not familiar with PHPUnit.