My favorites | Sign in
Project Home
Search
for
Documentation  

Featured
Updated Mar 12, 2008 by izimo...@gmail.com

Important note: this document is a work in progress and may change in the future.

Table Of Contents

Introduction

Anatomy of a doctest

Doctest flags explained

The expects syntax

The phpdt commandline runner

Some examples

references


Introduction

Testing_DocTest allows the developer to write unit tests directly in the

 blocs of your PHP functions, classes and class methods. 

It comes with a default runner that will parse all your

 blocs and will run the extracted tests, running tests is as simple as: 

$ phpdt /path/to/your/code

There are several advantages in using Testing_DocTest:

  • it makes unit tests writing funnier, easier and quicker (there's no infrastructure to setup, you just install the package, write your code examples tests and you're done !);
  • it ensures that docstrings are up-to-date by verifying that all examples work as documented;
  • it enforces writing of tutorial documentation, liberally illustrated with input-output examples.

[Back to top]

Anatomy of a doctest

Doctests blocks can be located in the

 blocks of: 
  • File level docstrings;
  • Classes docstrings;
  • Class method docstrings;
  • Functions docstrings.

A doctest block can have the following structure:

  • A name: using the doctest: keyword (optional);
  • A skip condition: using the skip-if: keyword (optional);
  • Zero or more flags: using the flags: keyword (optional);
  • One or more lines of PHP code;
  • An expected result, using the expects: keyword that can be on one or more lines;
  • A cleaning line: using the clean: keyword (optional);

An exhaustive example:

<?php

/**
 * <code>
 * // doctest: DOCTEST_NAME
 * // flags: FLAG_1, FLAG_2, ..., FLAG_N
 * // skip-if: PHP_CODE_THAT_RETURN_A_BOOL
 * 
 * PHP_CODE;
 * PHP_CODE;
 * 
 * // expects:
 * // EXPECT_LINE_1
 * // EXPECT_LINE_2
 * // ...
 * // EXPECT_LINE_N
 * 
 * // clean: PHP_CODE
 * </code>
 */
function someFunction() {
}

?>

The above can also be written like this:

<?php

/**
 * <code>
 * // doctest: DOCTEST_NAME
 * // flags: FLAG_1
 * // flags: FLAG_2
 * // flags: ...
 * // flags: FLAG_N
 * // skip-if:
 * // PHP_CODE_THAT_RETURN_A_BOOL
 * PHP_CODE;
 * PHP_CODE;
 * // expects:
 * // EXPECT_LINE_1
 * // EXPECT_LINE_2
 * // ...
 * // EXPECT_LINE_N
 * // clean:
 * // PHP_CODE
 * </code>
 */
function someFunction() {
}

?>

[Back to top]

Doctest flags explained

Doctests accepts various flags that can be used to control how the runner will compare expected and actual results, or just skip specific tests.

Flags can be cumulated like this:

// flags: FLAG1, FLAG2

or like this:

// flags: FLAG1
// flags: FLAG2

Flags available:

  • NORMALIZE_WHITESPACE: tells the runner to compare strings ignoring all whitespace differences (spaces, tabs and newline chars);
  • CASE_INSENSITIVE: tells the runner to compare strings ignoring case;
  • SKIP: tells the parser to just ignore the test unconditionally (if you want to skip a test given a specific condition, use the skip-if keyword in your test instead);
  • ELLIPSIS: allow to pass a wildcard pattern: [...] that will match any string in the actual result.

Below an example that illustrate the use of doctest flags:

<?php
/**
 * <code>
 * // flags: NORMALIZE_WHITESPACE
 * echo testFlags('   fo  o        ');
 * // expects:
 * // function says: foo
 * </code>
 * 
 * <code>
 * // flags: NORMALIZE_WHITESPACE
 * echo testFlags('foo');
 * // expects:
 * // function
 * // says:
 * // f o o
 * </code>
 *
 * <code>
 * // flags: CASE_INSENSITIVE
 * echo testFlags('foo');
 * // expects:
 * // FuNcTiOn says: Foo
 * </code>
 *
 * <code>
 * // flags: SKIP
 * echo testFlags('bar');
 * // expects:
 * // don't care too much... the test will be skipped
 * </code>
 *
 * <code>
 * // flags: ELLIPSIS
 * echo testFlags('bar');
 * // expects:
 * // function [...]: [...]
 * </code>
 *
 * @param string $foo some string
 *
 * @return string
 */
function testFlags($foo='')
{
    return 'function says: ' . strtolower($foo);
}
?>

[Back to top]

The expects syntax

The syntax for specifying what you expect from a php code bloc is quite simple:

// expects:
// EXPECT_LINE_1;
// EXPECT_LINE_2;
// ...
// EXPECT_LINE_N;

If you want to wrap long lines without making the runner believe you expects a multiline string, you can use the "\" char, here's an example:

<?php

/**
 * <code>
 * echo myFunc();
 * // expects:
 * // Some long line \
 * // that I want to \
 * // wrap for readability.
 * </code>
 */
function myFunc() {
    return 'Some long line that I want to wrap for readability';
}
?>

[Back to top]

The phpdt commandline runner

phpdt usage is pretty well documented by itself, just type the following on your terminal:

$ phpdt --help

And you will get:

DocTest command line frontend.

Usage:
  /usr/bin/phpdt [options] <files...>

Options:
  -q, --quiet                    Be quiet when executing tests.
  -f flags, --flags=flags        A space separated list of flags to set for
                                 *all* tests, flags can be:
                                 STRICT_WHITESPACE, IGNORE_CASE or SKIP
  -n, --no-colors                Do not colorize output on console.
  -l logfile, --logfile=logfile  Log output to file instead of stdout.
  -h, --help                     show this help message and exit
  --version                      show the program version and exit

Arguments:
  files  list of files and/or directories containing doc tests.

One thing to remember is that you must launch the phpdt utility in the appropriate directory, for example if you want to test code that have the following structure:

Dir/
    SomeFile.php
    /SubDir
        SomeFile.inc.php

And that in SomeFile.php there's a relative include:

require_once 'SubDir/SomeFile.inc.php';

Then you will do the following:

$ cd Dir
$ phpdt SomeFile.php

[Back to top]

Some examples

[Back to top]

References

[Back to top]


Sign in to add a comment
Powered by Google Project Hosting