An inline method and doc comment test runner
Test Flight allows you to define unit tests inside your classes. There are two different types of tests available:
Inline methods
, simple PHP methods annotated with @testDoc Comment
, code examples in the method documentation wrapped into<code>...</code>
Documentation
, code snippets in Markdown documentation files wrapped in ```php ... ```
This project is inspired by
- Rust's
rustdoc
which allows to run code examples defined in doc comments - and the unit testing in D and Rust, where tests can be part of the actual implementation
The current implementation is in a very early stage. PHP 7 is required.
Goal Goal
Test Flight is not designed to replace popular test suites like PHPUnit or Codeception. It helps getting started with unit testing in small projects, removes boilerplate code and encourages to add usage examples to the documentation (and helps to avoid errors in those).
Criticism Criticism
In contrast to compiled languages where test methods can be removed during compilation, test methods for Test Flight will remain in deployed code. But due to Reflection test methods don't have to be public.
Installation Installation
composer.phar require cundd/test-flight
Create Tests Create Tests
Create DocComment tests
Provide a DocComment for your method and add a code example within <code>...</code>
:
class Me {
private $name = '';
function __construct($name)
{
$this->name = $name;
}
/**
* The examples can be single line
*
* <code>test_flight_assert((new Me('Daniel'))->getName() === 'Daniel')</code>
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* ... and multi line
* <code>
* $instance = new Me('Daniel');
* test_flight_assert('Leinad' === $instance->getNameReversed());
* </code>
*
* @return string
*/
public function getNameReversed()
{
return ucfirst(strtolower(strrev($this->name)));
}
}
Create documentation tests
Every code snippet inside a Markdown file that is wrapped into a PHP code block is a documentation test:
```php
assert(true);
```
Take a look at this file as an example.
Creating inline method tests
class MyClass {
public function getName()
{
return 'Daniel';
}
/**
* @test
*/
protected function makeSureSomethingIsTrue()
{
// Non-static methods will be called on an instance of the class
test_flight_assert('Daniel' === $this->getName());
}
}
Method tests can also be static. This may be required if the creation of an instance requires arguments.
class ComplexClass {
private $name = '';
function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
/**
* @test
*/
protected static function makeSureSomethingIsTrue()
{
$instance = new ComplexClass('Daniel');
test_flight_assert('Daniel' === $instance->getName());
}
}
Run Tests Run Tests
vendor/bin/test-flight path/to/source
You can also specify the type of tests to run:
# Run DocComment tests
vendor/bin/test-flight path/to/source --type doccomment
# Run documentation tests
vendor/bin/test-flight path/to/source --type documentation
# Run method tests
vendor/bin/test-flight path/to/source --type method
More verbose output can be triggered with -v
:
vendor/bin/test-flight path/to/source -v
Add a custom bootstrap file to be included before the tests are run:
vendor/bin/test-flight --bootstrap path/to/bootstrap.php path/to/source
Configuration Configuration
Test-Flight can be configured through command line arguments and JSON files.
The following examples showcase the configuration options for bootstrap
:
Specify the bootstrap file as command line argument
vendor/bin/test-flight --bootstrap path/to/bootstrap.php path/to/source
Create a JSON file and pass it as argument
{
"path": "../../src/",
"bootstrap": "test-bootstrap.php"
}
vendor/bin/test-flight --configuration path/to/configuration.json
Create .test-flight.json
in the current directory
{
"path": "src/",
"bootstrap": "tests/resources/test-bootstrap.php"
}
ls .test-flight.json;
vendor/bin/test-flight
Assertions Assertions
Currently only a few assertions are built in. They always come in two flavours, a static method and a function (wrapping the method).
Test if the assertion is true
test_flight_assert($assertion, [string $message])
\Cundd\TestFlight\Assert::assert($assertion, [string $message])
Test if the callback throws an exception
test_flight_throws(callable $callback, [string $expectedException], [string $message])
\Cundd\TestFlight\Assert::throws(callable $callback, [string $expectedException], [string $message])
Test if the actual value matches the expected
test_flight_assert_same($expected, $actual, [string $message])
\Cundd\TestFlight\Assert::assertSame($expected, $actual, [string $message])
Test if the value is truthy
test_flight_assert_true($actual, [string $message])
\Cundd\TestFlight\Assert::assertTrue($actual, [string $message])
Test if the value is falsy
test_flight_assert_false($actual, [string $message])
\Cundd\TestFlight\Assert::assertFalse($actual, [string $message])
Test if the given object is an instance of the given class
test_flight_assert_instance_of($actual, string $className, [string $message])
\Cundd\TestFlight\Assert::assertInstanceOf($actual, string $className, [string $message])
Test if the given value is an instance of the given type
test_flight_assert_type($actual, string $type, [string $message])
\Cundd\TestFlight\Assert::assertTypeOf($actual, string $type, [string $message])