KD2\Test is a unit testing library, easy to use and understand, and very lightweight and fast.

Simple example of various test methods:

use KD2\Test;

Test::assert(true, 'true should always be true');
Test::equals(true, 1, '1 is expected to be true');
Test::strictlyEquals(4, strlen('test'), 'strlen is supposed to be returning an integer of 4');

$obj = (object) ['test' => 42];
Test::isObject($obj, '$obj should be an object');
Test::isInstanceOf(\stdClass::class, $obj, 'object is not an instance of stdClass');
Test::hasPropery('test', $obj, 'Object should have a test property');

	function () { throw new \RuntimeException('Error'); },
	'Expected exception of type RuntimeException');

When a test fail, a new KD2\TestException exception will be thrown including details to the specific error.

You can also invoke private/protected methods and access private/protected properties from classes:

class MyClass
    private $secret = 'abcd';

    protected getSecret(bool $really_get = false): ?string
        return $really_get ? $this->secret : null;

$c = new MyClass;

Test::strictlyEquals('abcd', Test::invoke($c, 'getSecret'));
Test::strictlyEquals('abcd', Test::invoke($c, 'getSecret', [true]));

Test::strictlyEquals('abcd', Test::getProperty($c, 'secret'));

Finally helper methods similar to PHPunit are available to run sets of units tests:

class MyTest
    protected $redis;

    public function setUp()
        $this->redis = new RedisClient('localhost:6379');

    public function tearDown()

    public function testHashTable()
        Test::equals(1, $this->redis->hset('testhash', 'name', 'Bohwaz'));
        Test::equals('BohwaZ', $this->redis->hget('testhash', 'name'));

    public function testKeys()
        Test::equals(1, $this->redis->set('testkey', 'pizza'));
        Test::equals('pizza', $this->redis->get('testkey'));

Test::runMethods(new MyTest);

This example will run each method which name begins with 'test' in its name. If a method named 'setUp' exists it will be run before each test, and if a method named 'tearDown' exists it will be run after each test too. So in this case it is the same as doing:

$t = new MyTest;



runMethods returns an array containing all errors and failed assertions. If everything was fine, the array will be empty.

A second method is available to run all methods of all classes contained in a file :


Like runMethods it will return an array containing all errors encountered.

Finally, an utility method run, the most useful, is available to test all files in a directory and display the results. It will take either a directory or a file name and run all methods of all files, displaying the results after each file.

KD2\Test::run(__DIR__ . '/tests');

If passed a directory name, this will only select files where the name ends with Test.php, to change that it is possible to pass a different regexp pattern as a second argument:

KD2\Test::run(__DIR__ . '/tests', '/^.*\.php$/');

Sample output:

QueueCookieTest.php: 18 successful assertions, 1 errors
1.	QueueCookieTest::testConfig

	[equals] Equals condition failed:
	--- string(9) "localhost"
	+++ string(10) "localhosst"

	Line 24 in QueueCookieTest.php

RedisClientTest.php: 3 successful assertions, no errors
QueueTest.php: 49 successful assertions, no errors