williams/testtube

TestTube: A lightweight and extensible unit testing framework for PHP.

v0.1.0 2024-10-03 14:04 UTC

This package is auto-updated.

Last update: 2025-05-01 00:10:30 UTC


README

TestTube is a lightweight and extensible unit testing framework for PHP. Originally built to support the Xpression library, its design prioritizes flexibility, making it suitable for small to medium-sized projects.

Requirements

  • Composer must be installed.

Installation

  1. Create a new TestTube project (you can replace 'example' with your desired directory name):
composer create-project williams/testtube example
  1. Configure composer.json to autoload the PHP libraries you want to test:
"autoload": {
    "psr-4": {
        "Namespace\\Of\\Library\\" : "path/to/library/"
    }
}
  1. Regenerate autoload files:
composer dump-autoload

Writing Your First Test

Let’s create a simple test for a Calculator class.

  1. Inside the tests directory, create a folder to group your test files (e.g., demo). Create a PHP file for your tests, such as calculator.php:
//tests/demo/calculator.php

return new class extends BaseTest{
};
  1. Define a boot method to instantiate the object(s) required for your tests:
use Demo\Calculator;

return new class extends BaseTest{

    public function boot(){
        return new Calculator;
    }
};

If more than one object is required, return an array containing the objects:

return [ new Foo, new Bar ];
  1. Create a test method. Each test method should take as parameters the objects returned by the boot method. By default, test method names must be camel-cased and start with 'test':
use Demo\Calculator;

return new class extends BaseTest{

    public function boot(){
        return new Calculator;
    }

    public function testAdd($calculator){

    }

};
  1. Define the body of the test, using an appropriate assert method:
   public function testAdd($calculator){
       $output = $calculator->add(2,3);
       $this->assertEquals(5,$output);
   }
  1. Run your tests from the project's root directory
php test

Example Output:

1 test file found.
1 test (1 assertion). 1 Passed, 0 Failed.
  1. Modify the expected value to simulate a failed test:
$this->assertEquals(6, $result); // Intentionally wrong

Re-running the tests will produce:

1 test file found.
1 test (1 assertion). 0 Passed, 1 Failed.

The following assertions were unsuccessful:

[demo/calculator.php] Failed to assert 6 equals 5.

Once a test file contains more than one test, the output will show both the filename and method name to help pinpoint failures.

Advanced Features

Assertions

TestTube includes several assert methods:

  • assertEquals($expected, $actual, $failureMessage = null)
  • assertTrue($boolean, $failureMessage = null)
  • assertFalse($boolean, $failureMessage = null)

The $failureMessage parameter is optional, and a default message will be generated if omitted.

Custom Test Method Names

If you need non-standard test method names, you can declare them using the $useMethods property. You can also disable automatic detection of test methods starting with "test" by setting $useTestMethods to false:

return new class extends BaseTest {
    protected $useMethods = ['customTest'];
    protected $useTestMethods = false;

    public function customTest() {
        // This is a valid test method.
    }

    public function testExample() {
        // This method will not be treated as a test due to $useTestMethods being false.
    }
};

Templates

To follow the DRY (Don't Repeat Yourself) principle, TestTube allows you to extend from templates stored in the templates directory. For example, to share a boot method across multiple test files:

  1. Create a reusable template:
// templates/CalculatorBaseTest.php

use Demo\Calculator;

class CalculatorBaseTest extends BaseTest{

    public function boot(){
        return new Calculator;
    }
}
  1. In your test file, extend this template:
// tests/demo/calculator.php

return new class extends CalculatorBaseTest{

    public function testAdd($calculator){
        $output = $calculator->add(2,3);
        $this->assertEquals(5,$output);
    }
};

The setup Method

The setup method helps to maintain a separation of concerns between object creation and configuration. It allows for any further customisation of the objects returned by the boot method before each test. Like test methods, it must accept each object returned by boot as a parameter:

return new class extends CalculatorBaseTest {
    public function setup($calculator) {
        $calculator->useRadians();
        $calculator->roundDecimalPlaces(2);
    }
};