NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Packagist · #42 most downloaded on Packagist
The PHP Unit Testing framework.
Last release 3 days ago
05 Oct 2026
Ships on a steady schedule
a new release about every 2 weeks
Some releases are documented
notes for 29 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
14 years old
850 releases · first in 2012
The Software Bill of Materials (SBOM) embedded in the PHAR now uses CycloneDX 1.7 and provides the NTIA minimum elements as well as the data fields th
TestSuite::runTests() doubles garbage collector time when zend.exception_ignore_args is offsetUpBeforeClass() and tearDownAfterClass() were run twice for a test class that is the only test class in a test suite of the XML configuration file that has the name of that test class--ARGS-- section of a PHPT test that start with - were interpreted by PHP instead of being passed to the test when the test also has a --STDIN-- sectionLearn how to install or update PHPUnit 13.4 in the documentation.
One column per quarter.
--coverage-jsonl CLI option and <jsonl> element for the XML configuration file to write a code coverage report in JSONL format, one JSON object per li
executionOrder attribute values and --order-by token lists that spell the order before defects, for example duration-ascending,defectspipeline() on the TestSuite\Sorted event for inspecting which reordering stages were appliedConstraint::negatedToString() and Constraint::negatedFailureDescription() for authoring the description of a constraint that is wrapped in LogicalNot#[RequiresClass] attribute to skip a test if a class does not existChildProcessExtension interface for extensions that need to be bootstrapped in the child process of a test that runs in process isolation--coverage-jsonl CLI option and <jsonl> element for the XML configuration file to write a code coverage report in JSONL format, one JSON object per line, that reports uncovered code rather than every executable line--timeout CLI option to limit the wall-clock time of the entire test runrequireCoverageMetadataOnSmallTests, requireCoverageMetadataOnMediumTests, and requireCoverageMetadataOnLargeTests attributes for the XML configuration file to require code coverage metadata depending on the size of a test; these have precedence over requireCoverageMetadata--- OUTPUT: record that is attributed to the test instead of being passed through unformatted; the record is omitted when beStrictAboutOutputDuringTests or --disallow-test-output already reports the output as riskydefects before the order for --order-by and executionOrder, which will change meaning in PHPUnit 14depends and no-depends for --order-by and executionOrder--order-by and executionOrderexecutionOrder XML configuration attribute, which are currently ignoredConstraint::failureDescriptionInContext() and LogicalNot::negate()#[Group], #[Ticket], #[Small], #[Medium], and #[Large] on parent classes of test classes#[DataProviderClosure] errors when it is run in process isolationLearn how to install or update PHPUnit 13.4 in the documentation.
The first attempt of a test that is retried is reported as attempt 1 of 1 in events, instead of attempt 1 of the configured maximum number of attempts
#[RequiresMethod] is declared as class-string, so static analysis reports an error when it refers to a class that does not exist#[RequiresMethod] attribute that refers to a class which cannot be loaded, for instance because its parent class does not exist, aborts the test run instead of skipping the testLearn how to install or update PHPUnit 13.3 in the documentation.
Control characters and ANSI escape sequences in user-supplied strings such as test names, data set names, and messages are now made visible as \u{NNNN
\u{NNNN} escape sequences instead of being passed through to the terminalLearn how to install or update PHPUnit 13.3 in the documentation.
The compact output displays details on PHPUnit deprecations and PHPUnit notices even when --display-phpunit-deprecations and --display-phpunit-notices…
SourceMapper may be deleted prematurely--display-phpunit-deprecations and --display-phpunit-notices are not usedLearn how to install or update PHPUnit 13.3 in the documentation.
Paths of included files are now escaped when generating the code that is executed in a separate process, so that a path containing special characters
Learn how to install or update PHPUnit 13.3 in the documentation.
Learn how to install or update PHPUnit 13.3 in the documentation .
SourceMap is built in child process even though identifyIssueTrigger is disabled#[CoversFile] attribute is not considered for risky test checkLearn how to install or update PHPUnit 13.3 in the documentation.
Invoking a static hook method such as setUpBeforeClass() no longer triggers a deprecation warning on PHP 8.6
setUpBeforeClass() no longer triggers a deprecation warning on PHP 8.6Learn how to install or update PHPUnit 13.3 in the documentation.
phpunit/php-code-coverage #1140 : Class-oriented HTML report
--repeat CLI option and #[Repeat] attributeexpectOutputString() and expectOutputRegex() to be combined and repeated#[CoversNothing] on methods--retry CLI option #[Retry] attributefailOnAllIssues="true" is combined with an explicitly disabled fine-grained failOn* setting--record-test-run-history and --do-not-record-test-run-history CLI options as well as the recordTestRunHistory attribute for the XML configuration file to control whether the status and duration of each test are recorded for use by --order-by defects and --order-by duration-*--without-class-view CLI option and classView attribute for the XML configuration file to disable the class-oriented view in the HTML code coverage report--without-file-view CLI option and fileView attribute for the XML configuration file to disable the file-oriented view in the HTML code coverage report{PWD} is now substituted with the directory of the PHPT test file in --ENV-- and --INI-- sections of PHPT test files{TMP} (system directory for temporary files) and {ENV:name} (value of environment variable name) are now substituted in --INI-- sections of PHPT test files--INI-- section references an environment variable that is not set is now skipped--SKIPIF-- section of a PHPT test file that prints xfail <reason> now marks the test as expected to fail, as if the PHPT test file had an --XFAIL-- section with that reasontest-run-history instead of test-resultsTestCase no longer captures error_log() output for tests that do not use expectErrorLog(), avoiding the cost of setting up error log redirection for every testerror_log() output from tests without an expectation is no longer echoed (date-stripped) to PHPUnit's output; it goes to the configured error log again, as it did before capture was introducederror_log() without expectErrorLog() now produces stderr output in the child process, which the test runner reports as a test error--XFAIL-- section or xfail output from the --SKIPIF-- section) but passes is now considered risky; this usually means the expected-failure marker is stale and should be removed--SKIPIF-- section produces output that is not recognized is now considered risky; this usually means the skip check itself is broken. The keywords understood by PHP's own test runner that have no PHPUnit counterpart (info, warn, xleak, flaky, and nocache) are tolerated and do not make the test riskydate.timezone=UTC, display_startup_errors=1, fatal_error_backtraces=Off, ignore_repeated_errors=0, precision=14,serialize_precision=-1), consistent with PHP's own test runner; all of them can be overridden per test using the --INI-- section--cache-result CLI option, use --record-test-run-history instead--do-not-cache-result CLI option, use --do-not-record-test-run-history insteadcacheResult XML configuration attribute, use recordTestRunHistory insteadPHPUnit\TextUI\Configuration\Configuration::cacheResult(), use PHPUnit\TextUI\Configuration\Configuration::recordTestRunHistory() insteadPHPUnit\TextUI\Configuration\Configuration::testResultCacheFile(), use PHPUnit\TextUI\Configuration\Configuration::testRunHistoryFile() insteadexpectErrorLog() now only considers error_log() output written after it was called; previously, the expectation was also satisfied by output written before expectErrorLog() was called--FILE--, --FILEEOF--, and --FILE_EXTERNAL-- sections, or more than one expectation section (--EXPECT--, --EXPECTF--, --EXPECTREGEX--, and their _EXTERNAL variants) are now rejected; previously, misspelled sections were silently ignored and duplicated sections silently overwrote each other--EXPECTREGEX-- section must now match the PHPT test's entire output, and . now matches newline characters, consistent with PHP's own test runner; previously, a match on a substring of the output was sufficient for the test to pass--SKIPIF-- section of a PHPT test is no longer mangled when it follows the skip <reason> convention used by PHP's own test suite; previously, the first two characters of the reason were stripped unless the skip: <reason> or skip - <reason> convention was usedPHPUnit\Runner\Phpt\InvalidPhptFileException when a PHPT test file has an empty --FILE-- or --FILEEOF-- section or a --FILE_EXTERNAL-- section that references an empty file; such a file is now rejected while it is parsed and reported as an errored testPHPUnit\Runner\Phpt\InvalidPhptFileException now has a message that explains why the PHPT test file was rejectedLearn how to install or update PHPUnit 13.3 in the documentation.
Regression that stopped test methods from being sorted by source code location
Learn how to install or update PHPUnit 13.2 in the documentation.
Messages for tests that are skipped because of an unsatisfied RequiresPhp , RequiresPhpunit , or RequiresPhpExtension version requirement now include
RequiresPhp, RequiresPhpunit, or RequiresPhpExtension version requirement now include the version that is actually being used@ error suppression and forwards suppressed warnings to previous error handlerassertArrayHasKey() does not accept ArrayAccess implementations with a specific value type when test code is analysed with PHPStan at level 9Learn how to install or update PHPUnit 13.2 in the documentation.
Learn how to install or update PHPUnit 13.2 in the documentation .
error_reporting() output dynamicallyLearn how to install or update PHPUnit 13.2 in the documentation.
Learn how to install or update PHPUnit 13.2 in the documentation .
Learn how to install or update PHPUnit 13.2 in the documentation.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
The Software Bill of Materials (SBOM) embedded in the PHAR now uses CycloneDX 1.7 and provides the NTIA minimum elements as well as the data fields th
setUpBeforeClass() and tearDownAfterClass() were run twice for a test class that is the only test class in a test suite of the XML configuration file that has the name of that test class--ARGS-- section of a PHPT test that start with - were interpreted by PHP instead of being passed to the test when the test also has a --STDIN-- sectionLearn how to install or update PHPUnit 12.5 in the documentation.
The class name argument of #[RequiresMethod] is declared as class-string , so static analysis reports an error when it refers to a class that does not
#[RequiresMethod] is declared as class-string, so static analysis reports an error when it refers to a class that does not exist#[RequiresMethod] attribute that refers to a class which cannot be loaded, for instance because its parent class does not exist, aborts the test run instead of skipping the testLearn how to install or update PHPUnit 12.5 in the documentation.
Control characters and ANSI escape sequences in user-supplied strings such as test names, data set names, and messages are now made visible as \u{NNNN
\u{NNNN} escape sequences instead of being passed through to the terminalLearn how to install or update PHPUnit 12.5 in the documentation.
Paths of included files are now escaped when generating the code that is executed in a separate process, so that a path containing special characters
Learn how to install or update PHPUnit 12.5 in the documentation.
Learn how to install or update PHPUnit 12.5 in the documentation .
SourceMap is built in child process even though identifyIssueTrigger is disabledLearn how to install or update PHPUnit 12.5 in the documentation.
Regression that stopped test methods from being sorted by source code location
Learn how to install or update PHPUnit 12.5 in the documentation.
Learn how to install or update PHPUnit 12.5 in the documentation .
assertArrayHasKey() does not accept ArrayAccess implementations with a specific value type when test code is analysed with PHPStan at level 9Learn how to install or update PHPUnit 12.5 in the documentation.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →