williams / testtube
TestTube: A lightweight and extensible unit testing framework for PHP.
Installs: 5
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Type:project
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
- Create a new TestTube project (you can replace 'example' with your desired directory name):
composer create-project williams/testtube example
- Configure
composer.json
to autoload the PHP libraries you want to test:
"autoload": { "psr-4": { "Namespace\\Of\\Library\\" : "path/to/library/" } }
- Regenerate autoload files:
composer dump-autoload
Writing Your First Test
Let’s create a simple test for a Calculator
class.
- Inside the
tests
directory, create a folder to group your test files (e.g.,demo
). Create a PHP file for your tests, such ascalculator.php
:
//tests/demo/calculator.php return new class extends BaseTest{ };
- 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 ];
- 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){ } };
- Define the body of the test, using an appropriate
assert
method:
public function testAdd($calculator){ $output = $calculator->add(2,3); $this->assertEquals(5,$output); }
- 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.
- 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:
- Create a reusable template:
// templates/CalculatorBaseTest.php use Demo\Calculator; class CalculatorBaseTest extends BaseTest{ public function boot(){ return new Calculator; } }
- 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); } };