Ursprünglich habe ich diesen Artikel am 3. April 2026 als Newsletter an meine Abonnentinnen und Abonnenten verschickt. Weitere Informationen findest du am Ende dieses Artikels.
Data Provider mit Closures
Mit Data Providern lässt sich dieselbe Testmethode mit unterschiedlichen Eingaben ausführen, ohne sie zu duplizieren. Bisher musste die Verbindung zwischen einem Test und seinem Data Provider über einen Methodennamen als String hergestellt werden. Das funktioniert, manche Entwicklerinnen und Entwickler bevorzugen es jedoch, die Testdaten direkt an der Testmethode bereitzustellen: mit expliziter Syntax anstatt über eine String-Referenz auf eine separate Methode.
PHP 8.5 hat die Unterstützung für Closures in konstanten Ausdrücken eingeführt. PHPUnit 13.1 nutzt dies mit dem neuen Attribut #[DataProviderClosure], implementiert in Pull Request #6526. Anstatt eine separate Methode über ihren Namen zu referenzieren, kann der Data Provider jetzt direkt als statische Closure definiert werden:
#[DataProviderClosure( static function (): array { return [ 'zeros' => [0, 0, 0], 'one plus one' => [1, 1, 2], ]; } )] public function testAdd(int $a, int $b, int $expected): void { $this->assertSame($expected, $a + $b); }
Die Closure muss statisch sein und ein Array oder Traversable zurückgeben, das die Argument-Sets für die Testmethode liefert, wie bei einer konventionellen Data Provider-Methode.
Zu beachten ist, dass #[DataProviderClosure] PHP 8.5 oder höher erfordert, da Closures in konstanten Ausdrücken in früheren PHP-Versionen nicht unterstützt werden.
Umfassenderes Open Test Reporting
Open Test Reporting (OTR) ist ein herstellerneutrales Format zur Aufzeichnung und zum Austausch von Testergebnissen. PHPUnit unterstützt das Schreiben von OTR-XML-Logdateien bereits seit einiger Zeit. Mit PHPUnit 13.1 werden die in diesen Logdateien erfassten Informationen deutlich umfangreicher.
Unerwartete Ausgaben
Wenn ein Test unerwartete Ausgaben erzeugt, beispielsweise durch print- oder var_dump()-Aufrufe, werden diese Ausgaben jetzt in der OTR-XML-Logdatei erfasst (#6501). Bisher waren diese Informationen nur in der Konsole sichtbar. Durch die Erfassung in der Logdatei können Werkzeuge, die OTR-Daten verarbeiten, unerwartete Ausgaben nun zusammen mit anderen Testergebnissen anzeigen. Das erleichtert es, versehentliche Debug-Ausgaben in der Testsuite zu identifizieren und zu bereinigen.
Issues
Deprecations, Notices, Warnings und Errors, die während der Testausführung auftreten, werden jetzt in der OTR-XML-Logdatei aufgezeichnet (#6524). Jedes Issue wird mit strukturierten Metadaten erfasst, darunter Typ, Nachricht, Quellposition und, bei Deprecations, ob der Auslöser direkt, indirekt oder aus dem getesteten Code stammte.
Werkzeuge, die OTR-Daten auswerten, sehen damit nicht nur Erfolg oder Fehlschlag, sondern auch die während des Laufs aufgetretenen Issues.
Gruppeninformationen
Testgruppen, die über das Attribut #[Group] zugewiesen werden, sind jetzt als Tags in der OTR-XML-Logdatei enthalten (#6523). Das ermöglicht es Werkzeugen, die auf OTR aufbauen, Testergebnisse auf Basis derselben Gruppierung zu filtern, zu kategorisieren und darzustellen, die bereits zur Organisation der Testsuite verwendet wird.
Benutzerdefinierte Issue Trigger Resolver
PHPUnit klassifiziert Deprecations danach, wo sie ausgelöst werden und woher sie stammen. Diese Klassifizierung bestimmt beispielsweise, ob eine Deprecation als „direkt“ oder „indirekt“ gemeldet wird, was wiederum beeinflusst, wie sie angezeigt wird und ob sie zum Fehlschlagen der Testsuite führt.
In den meisten Fällen klassifiziert die eingebaute Logik von PHPUnit korrekt. Es gibt jedoch Situationen, in denen Frameworks oder Bibliotheken zwischen dem eigenen Code und der tatsächlichen Quelle einer Deprecation stehen und so eine Fehlklassifizierung verursachen. Ein häufiges Beispiel ist Symfonys DebugClassLoader, der Deprecations im Auftrag anderer Klassen auslöst. PHPUnit würde eine solche Deprecation dem Class Loader zuschreiben und nicht dem Code, der sie tatsächlich verursacht hat.
PHPUnit 13.1 begegnet diesem Problem mit der Unterstützung für benutzerdefinierte Issue Trigger Resolver (#6530). Es ist jetzt möglich, einen eigenen Resolver zu implementieren und ihn in der XML-Konfigurationsdatei über das neue Element <issueTriggerResolvers> zu registrieren:
<source> <include> <directory>src</directory> </include> <issueTriggerResolvers> <class name="App\Testing\SymfonyIssueTriggerResolver"/> </issueTriggerResolvers> </source>
Ein benutzerdefinierter Resolver untersucht den Stack Trace und die Deprecation-Nachricht und kann die Zuordnung von aufrufender und aufgerufener Stelle korrigieren, wenn er das Muster erkennt. Wenn ein Resolver einen bestimmten Fall nicht behandelt, greift PHPUnit auf den nächsten Resolver in der Kette zurück, wobei der eingebaute Standard-Resolver den letzten Fallback darstellt.
Das bedeutet, dass Frameworks wie Symfony einen Resolver bereitstellen können, der Deprecations, die durch ihren Infrastrukturcode ausgelöst werden, korrekt zuordnet. So wird sichergestellt, dass die Klassifizierung in den Testergebnissen den tatsächlichen Ursprung des Problems genau widerspiegelt.
Code Coverage und PHPCOV
PHPUnit 13.1 wird mit phpunit/php-code-coverage 14.0 ausgeliefert, das erhebliche Verbesserungen bei der Serialisierung von Code Coverage-Daten und der Berichterstellung mit sich bringt. Parallel dazu wurde PHPCOV 13.0 veröffentlicht, das das Zusammenführen von Code-Coverage-Daten über verschiedene Maschinen und Build-Umgebungen hinweg unterstützt.
Diese Änderungen sind umfangreich genug für einen eigenen Artikel, den ich in Kürze veröffentlichen werde. Hier ist zunächst ein kurzer Überblick über die wichtigsten Verbesserungen:
- Serialisierte Code-Coverage-Daten verwenden jetzt relative Pfade, wodurch es möglich wird, Coverage auf einer Maschine zu sammeln und Berichte auf einer anderen zu generieren.
- PHPCOV 13.0 kann serialisierte Code-Coverage-Dateien auch dann zusammenführen, wenn sie mit unterschiedlichen Basispfaden erstellt wurden. Das ist essenziell für verteilte CI-Pipelines.
- Der HTML-Code-Coverage-Bericht verwendet standardmäßig eine neue, farbenblindfreundlichere Farbpalette, und die Farben können über die XML-Konfigurationsdatei von PHPUnit angepasst werden.
Livestream
Hier ist die Aufzeichnung des Livestreams, in dem ich die wichtigsten Änderungen in PHPUnit 13.1 erläutert habe:
Exklusive Einblicke direkt in deinem Posteingang
Alle zwei Monate, zeitgleich mit jedem PHPUnit Feature Release, schicke ich meinen Abonnentinnen und Abonnenten eine ausführliche Einordnung der neuen Funktionen: was sie tun, wie sie implementiert sind und warum sie aufgenommen wurden. Das ist der Kontext, den das ChangeLog nicht liefert.
Den Inhalt des Newsletters veröffentliche ich einen Monat nach dem Versand an meine Abonnenten hier auf dieser Website. Jetzt abonnieren, um die Informationen so früh wie möglich zu erhalten.