README.md is an executable specification. Each chapter is self-contained and artifacts of running one example can be used in all subsequent examples within that chapter. All example code is run, even examples hidden in HTML comments. In fact, all code irrelevant to user`s business needs must be hidden this way including pure integration and unit tests.
In many cases a single example listing can specify both its assumptions (input parameters) and assertions (success state). For example:
// GET /?foo=bar HTTP/1.1
$_GET['foo']; // 'bar'
The test script will interpret it loosely as follows:
$_GET['foo'] = 'bar';
if ($_GET['foo'] !== 'bar') fail();
You can mock a GET or POST request by specifying a commented out HTTP request header at the beginning of your PHP example:
// POST /form.php HTTP/1.1
// Host: www.example.com
//
// input=value&button=submit
Alternatively you can specify HTTP header separtely right before the PHP example it belongs to:
GET /index.html HTTP/1.1
Host: www.example.com
Some scripts may depend on other scripts or data files. You can specify such dependencies by naming the file (e.g. hello_world.php) in paragraph preceeding the listing of its content and ending the paragraph with a colon:
echo 'Hello. World.';
Then you can reference that dependency by prepending its name with 'path/to/'
, e.g.:
echo 'Say: ';
include 'path/to/hello_world.php';
Say: Hello. World.
You may also add images as dependencies, e.g. test.gif:
You can make assertions about the expected state of variables, expected errors and exceptions:
// Assertions about types:
$foo; // bool
$foo; // int
$foo; // float
$foo; // string
$foo; // array
$foo; // object
$foo; // callable
$foo; // resource
$foo; // null
// Assertions about scalar values:
$scalar; // true
$scalar; // false
$scalar; // 123
$scalar; // 123.00
$scalar; // 'test string'
// Assertions about arrays:
$array; // ['a', 'b', 'c']
$array; // ['a', 'b', ...]
$array; // ['a' => ..., 'b', 'c']
// Assertions about objects:
$object; // ClassOrInterfaceName
// Assertions about exceptions:
funcOrMethod(); // throws ExceptionClass('Optional Error string')
// Assertions about errors, warnings and notices:
funcOrMethod(); // triggers 'Error, warning or notice message string'
You can also make assertions about expected output:
echo 'Hello World!';
Hello World!
Effectively any output produced by a fenced PHP code can be compared byte for byte to either any other fenced code block or an image that immediately follows.