Skip to main content Headstrong Internet

Document your app with PHPUnit Testdox output

Published: 2022-11-03 | Updated: 2022-11-03

When you run your application’s test suite (you do have a test suite, right?) with PHPUnit, you will probably be familiar with the following output style:

PHPUnit 9.5.26 by Sebastian Bergmann and contributors.

Testing 
..........................................R.................R.... 65 / 90 ( 72%)
.........................                                         90 / 90 (100%)

Time: 00:05.650, Memory: 155.00 MB

The main advantage of this output format is that it is concise, especially when you have a lot of tests. It quickly gives you an overview of tests that failed, have errors, or are considered risky.

However, the downside is that it’s not immediately clear what each test is actually testing. Each test is simply represented by a . character and that is all.

There is an alternative that many people do not seem to know about. PHPUnit has an option to change the output format to one that is much more descriptive, and that relies on the information already in your tests to create these descriptions.

Lets say you have a test class such as the following:

<?php
declare(strict_types=1);

use PHPUnitFrameworkTestCase;

final class CustomerSubscriptionsTest extends TestCase
{
    public function test_customer_can_be_subscribed_to_the_mailing_list(): void
    {
        // test code
    }

    public function test_customer_can_be_unsubscribed_from_the_mailing_list(): void
    {
        // test code
    }

    public function test_customer_cannot_be_subscribed_more_than_once(): void
    {
        // test code
    }

    public function test_customer_cannot_unsubscribe_if_not_already_subscribed(): void
    {
        // test code
    }
}

If you add the --testdox option to the PHPUnit command, you will get an alternative output format which looks like this:

PHPUnit 9.5.26 by Sebastian Bergmann and contributors.

Testing /var/www/app/tests

Customer Subscriptions
 ✔ Customer can be subscribed to the mailing list
 ✔ Customer can be unsubscribed from the mailing list
 ✔ Customer cannot be subscribed more than once
 ✔ Customer cannot unsubscribe if not already subscribed

The test descriptions are taken from the method names inside the test class. If you name your methods carefully, using natural language, you are creating documentation right there and then, without any further effort.

Overriding the testdox description

If you would like the name your method something slightly different to the outputted description, you can override it with the @testdox annotation:

/**
 * @testdox Customer can be subscribed OK
 */
public function test_customer_can_be_subscribed_to_the_mailing_list(): void
{
    // test code
}

Using testdox with data providers

If you use data provider methods to run your test against multiple data sets, you can get the values from the data provider into the testdox description as well.

/**
 * @dataProvider additionProvider
 * @testdox Adding $a to $b results in $expected
 */
public function test_can_add_a_to_b_successfully($a, $b, $expected)
{
    // test code
}

Additionally, if you use named sets in your data provider, you can access the set name in the testdox annotation using $_dataName as follows:

/**
 * @dataProvider additionProvider
 * @testdox Adding $a to $b results in $expected for $_dataName
 */
public function testAdd($a, $b, $expected)
{
    // test code
}

public function additionProvider()
{
    return [
        'data set 1' => [0, 0, 0],
        'data set 2' => [0, 1, 1],
        'data set 3' => [1, 0, 1],
        'data set 4' => [1, 1, 3]
    ];
}

This would result in the output for the first data set of Adding 0 to 0 results in 0 for data set 1

Conclusion

Once you start playing around with testdox output, you will probably realise how slack you’ve been when naming your test methods. It gets addictive, and you’ll find yourself tweaking things until you get the perfect desired output!

However, this time is well spent, as all one needs to do to get a summary of the behaviour of a part of your application is to run the test suite with the --testdox option, and the tests themselves will describe the desired behaviour.

Back to top

Application Development

Unlock the value in your business with custom software solutions.

Save time and money, and keep all your customers happy.

Cloud Server Management

We can manage your infrastructure, ensuring your application is always available and performant.

Flexible solutions for all types of app.

Software Consulting

Got a new software project? Don't know where to start?

We can help you plan, design and build a successful application for your business.

Website Design & Build

Development of all types of website from personal blogs to e-commerce sites.

We work with WordPress, CraftCMS, Symfony and more.

Headstrong Logo