Unit Testing¶
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¶
or by manually adding it to composer.json
:
Once PHPUnit is installed, create a directory called tests
in project root directory with a subdirectory called Unit
:
Configure Test Namespace¶
In order to autoload our test directory, we must add our test namespace to composer. Add the below to composer and modify it to fit your needs.
Now, create a phpunit.xml
file as follows:
The phpunit.xml
file¶
Modify the phpunit.xml
below to fit your needs and save it in your project root directory. This will run any tests under the tests/Unit
directory.
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
verbose="true"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuite name="Phalcon - Unit Test">
<directory>./tests/Unit</directory>
</testsuite>
</phpunit>
Phalcon Incubator Test¶
Phalcon provides a test library that provides a few abstract classes you can use to bootstrap the Unit Tests themselves. These files exist in Phalcon Incubator Test repository.
You can use the Incubator test library by adding it as a dependency:
or by manually adding it to composer.json
:
Creating a Unit Test¶
It is always wise to autoload your classes using namespaces. The configuration below assumes that you are using PSR-4 to autoload your project classes via a composer configuration. Doing so, 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, as in most cases you should be mocking your dependencies. If you happen to need one, you can add it to the DI
in the AbstractUnitTest
.
Abstract Unit Test¶
First, create a base Unit Test called AbstractUnitTest.php
in your tests/Unit
directory:
<?php
declare(strict_types=1);
namespace Tests\Unit;
use Phalcon\Di\Di;
use Phalcon\Di\FactoryDefault;
use Phalcon\Incubator\Test\PHPUnit\UnitTestCase;
use PHPUnit\Framework\IncompleteTestError;
abstract class AbstractUnitTest extends UnitTestCase
{
private bool $loaded = false;
protected function setUp(): void
{
parent::setUp();
$di = new FactoryDefault();
Di::reset();
Di::setDefault($di);
$this->loaded = true;
}
public function __destruct()
{
if (!$this->loaded) {
throw new IncompleteTestError(
"Please run parent::setUp()."
);
}
}
}
Your First Test¶
Create the test below and save it in your tests/Unit
directory.
<?php
declare(strict_types=1);
namespace Tests\Unit;
class UnitTest extends AbstractUnitTest
{
public function testTestCase(): void
{
$this->assertEquals(
"roman",
"roman",
"This will pass"
);
$this->assertEquals(
"hope",
"ava",
"This will fail"
);
}
}
If you need to overload the setUp
method, it is important you call the parent or Phalcon will not properly initialize.
protected function setUp(): void
{
parent::setUp();
//...
}
````
### Running Unit Tests
When you execute `vendor/bin/phpunit` in your command line, you will get the following output:
```bash
$ phpunit
PHPUnit 9.5.23 by Sebastian Bergmann and contributors.
Runtime: PHP 8.1.8 with Xdebug 3.1.5
Configuration: /var/www//phpunit.xml
Time: 3 ms, Memory: 3.25Mb
There was 1 failure:
1) Test\Unit\UnitTest::testTestCase
This will fail
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'hope'
+'ava'
/var/www/tests/Unit/UnitTest.php:25
FAILURES!
Tests: 1, Assertions: 2, Failures: 1.