This project provides a composer package and a Phar archive with an extension for reporting phpunit/phpunit test execution details to agents.
After installing and bootstrapping the extension, when running your tests with phpunit/phpunit, the extension will detect whether an agent is running the tests and replace the default output with test execution details that are easier for agents to consume.
When tests pass, the extension outputs:
{
"result": "success",
"summary": {
"assertions": 5,
"deprecations": 0,
"errors": 0,
"failures": 0,
"incomplete": 0,
"notices": 0,
"phpunitDeprecations": 0,
"phpunitNotices": 0,
"phpunitWarnings": 0,
"risky": 0,
"skipped": 0,
"tests": 5,
"warnings": 0
}
}When tests fail (exit code 1), the extension outputs:
{
"result": "failure",
"summary": {
"assertions": 5,
"deprecations": 0,
"errors": 0,
"failures": 2,
"incomplete": 0,
"notices": 0,
"phpunitDeprecations": 0,
"phpunitNotices": 0,
"phpunitWarnings": 0,
"risky": 0,
"skipped": 0,
"tests": 5,
"warnings": 0
},
"details": {
"failures": [
{
"file": "/path/to/ExampleTest.php",
"line": 27,
"message": "Failed asserting that false is true.",
"test": "Namespace\\ExampleTest::testFailing"
},
{
"actual": "bar",
"diff": "--- Expected\n+++ Actual\n@@ @@\n-'foo'\n+'bar'\n",
"expected": "foo",
"file": "/path/to/ExampleTest.php",
"line": 34,
"message": "Failed asserting that two strings are identical.",
"test": "Namespace\\ExampleTest::testComparisonFailing"
}
]
}
}When tests fail with comparison assertions, the actual, diff, and expected fields provide details about the mismatch. These fields are only present for comparison failures.
When tests error (exit code 2), the extension outputs:
{
"result": "exception",
"summary": {
"assertions": 5,
"deprecations": 0,
"errors": 1,
"failures": 2,
"incomplete": 0,
"notices": 0,
"phpunitDeprecations": 0,
"phpunitNotices": 0,
"phpunitWarnings": 0,
"risky": 0,
"skipped": 0,
"tests": 5,
"warnings": 0
},
"details": {
"errors": [
{
"file": "/path/to/ExampleTest.php",
"line": 32,
"message": "Something went wrong.",
"test": "Namespace\\ExampleTest::testErroring"
}
],
"failures": [
{
"file": "/path/to/ExampleTest.php",
"line": 27,
"message": "Failed asserting that false is true.",
"test": "Namespace\\ExampleTest::testFailing"
},
{
"actual": "bar",
"diff": "--- Expected\n+++ Actual\n@@ @@\n-'foo'\n+'bar'\n",
"expected": "foo",
"file": "/path/to/ExampleTest.php",
"line": 34,
"message": "Failed asserting that two strings are identical.",
"test": "Namespace\\ExampleTest::testComparisonFailing"
}
]
}
}The summary always reports the count for every category, so that an agent has a complete overview of the test run. The details section, however, only contains an entry for a category when the test run produces at least one occurrence of it, so that an agent has all the information it can act on without unnecessary noise. For example, when tests trigger deprecations, the extension outputs:
{
"result": "success",
"summary": {
"assertions": 5,
"deprecations": 1,
"errors": 0,
"failures": 0,
"incomplete": 0,
"notices": 0,
"phpunitDeprecations": 0,
"phpunitNotices": 0,
"phpunitWarnings": 0,
"risky": 0,
"skipped": 0,
"tests": 5,
"warnings": 0
},
"details": {
"deprecations": [
{
"file": "/path/to/ExampleTest.php",
"line": 42,
"message": "Method Namespace\\Example::doSomething() is deprecated.",
"triggeredBy": [
"Namespace\\ExampleTest::testTriggeringDeprecation"
]
}
]
}
}The phpunitDeprecations, phpunitNotices, and phpunitWarnings categories report deprecations, notices, and warnings triggered by phpunit/phpunit itself - as opposed to deprecations, notices, and warnings triggered by PHP or by the code under test. For example, when a test configures no expectations for a mock object, phpunit/phpunit triggers a PHPUnit notice, and the extension outputs:
{
"result": "success",
"summary": {
"assertions": 5,
"deprecations": 0,
"errors": 0,
"failures": 0,
"incomplete": 0,
"notices": 0,
"phpunitDeprecations": 0,
"phpunitNotices": 1,
"phpunitWarnings": 0,
"risky": 0,
"skipped": 0,
"tests": 5,
"warnings": 0
},
"details": {
"phpunitNotices": [
{
"file": "/path/to/ExampleTest.php",
"line": 21,
"message": "No expectations were configured for the mock object for Namespace\\Example. Consider refactoring your test code to use a test stub instead. The #[AllowMockObjectsWithoutExpectations] attribute can be used to opt out of this check.",
"test": "Namespace\\ExampleTest::testTriggeringPhpunitNotice"
}
]
}
}A phpunitDeprecations, phpunitNotices, or phpunitWarnings entry triggered by the test runner itself - rather than by a test - contains only a message. The phpunitNotices category requires phpunit/phpunit:^12.1.0; on older versions its count is always 0.
The JSON output conforms to the JSON schema included in this package.
The extension uses ergebnis/agent-detector to detect the presence of agents.
The extension is compatible with the following versions of phpunit/phpunit:
Run
composer require --dev ergebnis/phpunit-agent-reporterto install ergebnis/phpunit-agent-reporter as a composer package.
Download phpunit-agent-reporter.phar from the latest release.
Before the extension can report test execution details in phpunit/phpunit, you need to bootstrap it.
To bootstrap the extension as a composer package when using
phpunit/phpunit:^13.0.0phpunit/phpunit:^12.0.0phpunit/phpunit:^11.0.0phpunit/phpunit:^10.0.0
adjust your phpunit.xml configuration file and configure the
extensionselement onphpunit/phpunit:^13.0.0extensionselement onphpunit/phpunit:^12.0.0extensionselement onphpunit/phpunit:^11.0.0extensionselement onphpunit/phpunit:^10.0.0
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
>
+ <extensions>
+ <bootstrap class="Ergebnis\PHPUnit\AgentReporter\Extension"/>
+ </extensions>
<testsuites>
<testsuite name="unit">
<directory>test/Unit/</directory>
</testsuite>
</testsuites>
</phpunit>To bootstrap the extension as a PHAR when using
phpunit/phpunit:^13.0.0phpunit/phpunit:^12.0.0phpunit/phpunit:^11.0.0phpunit/phpunit:^10.0.0
adjust your phpunit.xml configuration file and configure the
extensionsDirectoryattribute and theextensionselement onphpunit/phpunit:^13.0.0extensionsDirectoryattribute and theextensionselement onphpunit/phpunit:^12.0.0extensionsDirectoryattribute and theextensionselement onphpunit/phpunit:^11.0.0extensionsDirectoryattribute and theextensionselement onphpunit/phpunit:^10.0.0
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
+ extensionsDirectory="directory/where/you/saved/the/extension/phars"
>
+ <extensions>
+ <bootstrap class="Ergebnis\PHPUnit\AgentReporter\Extension"/>
+ </extensions>
<testsuites>
<testsuite name="unit">
<directory>test/Unit/</directory>
</testsuite>
</testsuites>
</phpunit>The maintainers of this project record notable changes to this project in a changelog.
The maintainers of this project suggest following the contribution guide.
The maintainers of this project ask contributors to follow the code of conduct.
The maintainers of this project provide limited support.
You can support the maintenance of this project by sponsoring @ergebnis.
This project currently supports the following PHP versions:
The maintainers of this project add support for a PHP version following its initial release and may drop support for a PHP version when it has reached its end of life.
This project has a security policy.
This project uses the MIT license.
This package is inspired by nunomaduro/pao, originally licensed under MIT by Nuno Maduro.
Follow @localheinz and @ergebnis on Twitter.