The testing microframework for PHP
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
src allow ass. results to be recored on passed suite Mar 14, 2014

FUnit: The testing microframework for PHP

FUnit is a testing microframework for PHP 5.3+, partially inspired by QUnit. FUnit was created by Ed Finkler for Fictive Kin.

If you can code PHP, you can write tests with FUnit.


  • Simple to write tests and get output – start writing tests fast
  • Short, straightforward syntax
  • Can be run from the CLI – no web server required
  • Fancy colored output in terminal


require __DIR__ . '/FUnit.php';
use \FUnit as fu;  // note the alias to "fu" for terseness

fu::test("this is a test", function() {
    fu::ok(1, "the integer '1' is okay");
    fu::ok(0, "the integer '0' is not okay"); // this will fail!

$exit_code = fu::run();

Will output:

> php example_standalone.php
Running test 'this is a test...'
TEST: this is a test (1/2):
 * PASS ok() the integer '1' is okay
 * FAIL ok() the integer '0' is not okay

TOTAL ASSERTIONS: 1 pass, 1 fail, 0 expected fail, 2 total
TESTS: 1 run, 0 pass, 1 total

See the example_standalone.php file for more, or try running it with php example_standalone.php

Alternately, if you load standalone_example.php in a web browser, it will output a very simple HTML version of the text report. If you're running PHP 5.4 or above, you can use the dev server to view it like so:

php -S example_standalone.php

And then open in a web browser.


Test Suite Building Methods

  • FUnit::test($name, \Closure $test)
    Add a test with the name $name and an anonymous function $test. $test would contain various assertions, like FUnit::ok()

  • FUnit::run($report = true, $filter = null, $report_format = 'text')
    Runs the registered tests.

    • $report (boolean): If false is passed, the report output is suppressed.
    • $filter (string): If this is passed, only tests that contain the $filter string will be run.
    • $report_format (string): Default is 'text'. Also accepts 'xunit'.
  • FUnit::setup(\Closure $setup)
    Register a function to run at the start of each test. See FUnit::fixture()

  • FUnit::teardown(\Closure $setup)
    Register a function to run at the end of each test. See FUnit::fixture() and FUnit::reset_fixtures()

  • FUnit::fixture($key, [$val])
    Retrieve or register a fixture. Use this in FUnit::setup() to assign fixtures to keys, and retrieve those fixtures in your tests

  • FUnit::reset_fixtures()
    Clears out all fixtures in the FUnit::$fixtures array. This doesn't guarantee clean shutdown/close


  • FUnit::ok($a, $msg = null)
    Assert that $a is truthy. Optional $msg describes the test

  • FUnit::not_ok($a, $msg = null)
    Assert that $a is not truthy. Optional $msg describes the test

  • FUnit::equal($a, $b, $msg = null)
    Assert that $a == $b. Optional $msg describes the test

  • FUnit::not_equal($a, $b, $msg = null)
    Assert that $a != $b. Optional $msg describes the test

  • FUnit::strict_equal($a, $b, $msg = null)
    Assert that $a === $b. Optional $msg describes the test

  • FUnit::not_strict_equal($a, $b, $msg = null)
    Assert that $a !== $b. Optional $msg describes the test

  • FUnit::has($needle, $haystack, $msg = null)
    Assert that an array or object ($haystack) has a key or property ($needle)

  • FUnit::not_has($needle, $haystack, $msg = null)
    Assert that an array or object ($haystack) does not have a key or property ($needle). Forgive my grammar.

  • FUnit::fail($msg = null, [$expected = null])
    Force a failed assertion. If $expected === true, it's marked as an expected failure

  • FUnit::expect_fail($msg = null)
    Assets an expected failure. Equivalent to FUnit::fail('msg', true)

  • FUnit::pass($msg = null)
    Force a successful assertion.

  • FUnit::throws($callback, $params, $exception = null, $msg = null)
    Assert that $callback throws an exception of type $exception. $callback must be a callable

  • FUnit::all_ok($a, $callback, $msg = null)
    Iterate over all the items in $a and pass each to $callback. If the callback returns true for all, it passes -- otherwise it fails. $callback must be a callable

Utility Methods

  • FUnit::report($format = 'text')
    Output the test report. If you've suppressed reporting output previously, you can use this to output the report manually.

  • FUnit::exit_code()
    Retrieve the exit code. If any test fails, the exit code will be set to 1. Otherwise 0. You can use this value to return a success or failure result with the PHP function exit().

Configuration Methods

  • FUnit::set_disable_reporting($state)
    If passed true, report will not be output after test runs finish. Re-enable by passing false.

  • FUnit::set_debug($state)
    If passed true, extra debugging info (including timing and details about assertion failures) will be output. Disable by passing false.

  • FUnit::set_silence($state)
    If passed true, only the report will be output -- no progress, debugging info, etc. Disable by passing false.

Report formats

By default, FUnit outputs a colorful text output, formatted for the terminal. You can also output reports in xunit-style xml.

The report format is the third parameter of FUnit::run():


// Outputs a colored text report. This is the default format.
FUnit::run(true, null, 'text');

// Outputs xUnit-style xml
FUnit::run(true, null, 'xunit');

Browser output

The standard text report format will output as very simple HTML if the test file is loaded up through a web server. You can test this with the dev server if you're running PHP 5.4+:

php -S test_file.php

And then open in a web browser.

CLI Test Runner Utility

FUnit was designed to not require a separate test runner tool, but it does come with one at bin/fu (or vendor/bin/fu if you've installed via Composer). fu allows you to run tests in a single file, a group of files in a directory, and filter what tests are run.


  • fu --help
    Get detailed help and information on all options

  • fu ./tests
    Scan the directory ./tests for files that have "test(s)" in their names, and run those tests

  • fu tests.php
    Execute tests in tests.php

  • fu -d tests.php
    Execute tests in tests.php with additional debugging info

  • fu --filter="API" tests.php
    Execute only the tests in tests.php that have "API" in the name

  • fu -s tests.php
    Execute the tests tests.php, but suppress all output other than the report

Note: When fu loads multiple test files, it requires each one. That means all the code within each is executed. Calls to FUnit::run() are suppressed, but non-FUnit code (like exit() calls or require statements) could cause issues.


Install with Composer

If you're using Composer to manage dependencies, you can add FUnit with it.

    "require": {
        "funkatron/funit": "dev-master"

Note that FUnit has not yet reached 1.0! That means BC may break!

If you install via Composer, you can use the auto-generated autoloader to load FUnit, like so:

require "vendor/autoload.php"
use \FUnit as fu;

fu::test("this is a test", function() {
    fu::ok(1, "the integer '1' is okay");
    fu::ok(0, "the integer '0' is not okay"); // this will fail!


Install source from GitHub

To install the source code:

git clone git://

And include it in your scripts:

require_once '/path/to/FUnit/FUnit.php';

Install source from zip/tarball

Alternatively, you can fetch a tarball or zipball:

$ curl | tar xzv
$ wget -O - | tar xzv

Using a Class Loader

If you're using a class loader (e.g., Symfony Class Loader) for PSR-0-style class loading:

$loader->registerNamespace('FUnit', 'path/to/vendor/FUnit');


If you're using a version older than 0.5, the namespace/class name changed to follow PSR-0 autoloader standards. The base class is now \FUnit, not \FUnit\fu. You can still call all your methods with fu::XXX() by aliasing the namespace like so:

use \FUnit as fu