Test-Framework für PHP erhält Änderungen Schritt für Schritt

PHPUnit 9.0 ist da: Die Features der Major-Version
Keine Kommentare

Für das Test-Framework PHPUnit liegt eine neue Version vor. Zwar bringt PHPUnit 9.0 keine signifikanten Neuerungen, doch ein paar wichtige Änderungen gibt es doch. Sebastian Bergmann, Erfinder des Frameworks, stellt die neue Version vor.

Die deutsche Sprache erlaubt durch die Verkettung von Substantiven die Bildung von praktisch endlos langen Worten. Worte wie beispielsweise „Hauptversionsnummererhöhungs-angst“. Mit diesem Wort, oder vielleicht eher Unwort, beschreibt man die Angst vieler Softwareprojekte vor dem Erhöhen der Hauptversionsnummer (Englisch: major version), beispielsweise von 8.5 auf 9.0. So lagen beispielsweise elf Jahre zwischen der Veröffentlichung von PHP 5.0 und der Veröffentlichung von PHP 7.0. Dass es auch anders geht, hat Mozilla mit dem Release-Prozess für den Firefox-Browser gezeigt, von dem alle sechs bis acht Wochen eine neue Major-Version erscheint. Ab diesem Jahr will Mozilla sogar alle vier Wochen eine neue Major-Version von Firefox veröffentlichen. Vor diesem Hintergrund ist die jährliche Erhöhung der Hauptversionsnummer von PHPUnit geradezu zahm.

PHPUnit 9.0: Eine neue Major-Version

Am 7. Februar 2020 ist mit PHPUnit 9 eine neue Major-Version des Standard-Testframeworks der PHP-Welt erschienen. Mit einer neuen Hauptversionsnummer wie „9“ verbindet man üblicherweise eine Flut von neuen Features oder andere Leistungsverbesserungen. Das PHPUnit-Projekt handhabt dies jedoch anders und so bringt beispielsweise PHPUnit 9.0 keine signifikanten neuen Features. Diese werden erst im Laufe des Jahres mit PHPUnit 9.1 et cetera kommen.

Alle zwei Monate, und zwar am ersten Freitag im Februar, April, Juni, August, Oktober und Dezember, erscheint eine neue Version von PHPUnit. Bei der neuen Version im Februar handelt es sich um eine Major-Version, bei den anderen Versionen um Minor-Versionen. Den Grundsätzen von Semantic Versioning folgend bedeutet dies, dass die Februar-Version nicht abwärts kompatibel mit den Vorgängerversionen ist und beispielsweise Features entfernt. Die anderen Versionen hingegen sind zu ihren Vorgängern abwärtskompatibel und führen beispielsweise neue Features ein. Aber warum werden jedes Jahr im Februar Features aus PHPUnit entfernt oder so geändert, dass ein Anpassen der eigenen Tests notwendig wird?

PHPUnit ist fast zwanzig Jahre alt. Das bedeutet zum einen, dass Features, die vor fünf, zehn, fünfzehn oder gar zwanzig Jahren noch notwendig waren, heute keinen Nutzen mehr haben. In vielen Fällen, beispielsweise die Unterstützung des direkten Testens von privaten Objekt-Attributen, hat alte Funktionalität nicht nur keinen positiven Nutzen mehr, sondern vielmehr sogar einen negativen Effekt: Entwickler denken, nur weil es eine Funktionalität in PHPUnit gibt, ist es eine gute Idee, diese zu verwenden. Dies kann im schlimmsten Fall dazu führen, dass man Software unsauber entwickelt. Zum anderen muss eine Software wie PHPUnit ständig an Änderungen im Ökosystem angepasst werden: neue Versionen von PHP sind ebenso zu unterstützen wie neue Distributionskanäle. Die Migration einer Codebasis wie der von PHPUnit ist eben nicht über Nacht von PHP 5 nach PHP 7 zu migrieren. Und auch die Ablösung von PEAR-Paketen durch die Unterstützung für Composer PHP-Archive (PHAR) hat damals einiges an Zeit gekostet. Darüber hinaus steigt die Komplexität des Codes durch Workarounds für Bugs in bestimmten PHP-Versionen und Unterstützung unterschiedlicher PHP-Versionen in derselben PHPUnit-Version ebenso wie durch das Hinzufügen neuer Funktionalität.

Lange Zeit war ich, mehr oder weniger, der einzige Entwickler von PHPUnit. Weil eben nur ich bereit war, mit dieser Codebasis zu arbeiten. Das war meine Schuld, da ich vor zwanzig Jahren nicht schon wusste, was ich heute über Architektur und Programmierung wei߬, und die Konsequenzen von Design-Entscheidungen nicht absehen konnte.

International PHP Conference

How Much Framework?

by Arne Blankerts (thePHP.cc)

Building a Cloud-Friendly Application

by Larry Garfield (Platform.sh)

Crafting Maintainable Laravel Applications

by Jason McCreary (Pure Concepts, LLC)

JavaScript Days 2020

Wie ich eine React-Web-App baue

mit Elmar Burke (Blendle) und Hans-Christian Otto (Suora)

Architektur mit JavaScript

mit Golo Roden (the native web)


Alberto Brandolini beschreibt eine solche Situation wie folgt: „The dark secret of the Dungeon Master is that he knows every trap in the existing legacy software, because he was the one to leave the traps around. […] Knowledge, in the form of accidental complexity starts accumulating in the head of the Dungeon Master, and silently grows“.

Es tröstet mich ein wenig, dass ich damit nicht alleine bin. Erich Gamma und Kent Beck, die ursprünglichen Autoren von JUnit, haben ähnliche Probleme: „The problem is in software design often the consequences of your decisions don’t become apparent for years. One of the advantages of having to live with JUnit for 8 years, is now we can look back and see which decisions we made worked nicely and which we would have done differently“.

Mittlerweile hat sich die Situation deutlich gebessert. Zum einen tragen die jährlichen Major-Versionen, die sowohl Funktionalität aus PHPUnit entfernen beziehungsweise so verändern, dass Implementierung und Verwendung einfacher werden, als auch Unterstützung für alte PHP-Versionen entfernen, dazu bei, dass die Codebasis von PHPUnit verständlicher und wartbarer wird. Zum anderen habe die regelmä߬ig Code-Sprints der letzten Jahre dazu beigetragen, dass neue Entwickler zum PHPUnit-Projekt gekommen sind, die mich nun bei meiner Arbeit unterstützen.

Marco Pivetta fasst dies wie folgt zusammen: „[PHPUnit] has been very stale for ages, and is now moving much faster thanks to people now willing to invest time in it (thanks to constant rework and cleaning)“.

Die Neuerung von PHPUnit 9.0 im Überblick

Nachdem das Warum der jährlichen Änderungen nun hoffentlich klarer geworden ist, ist es Zeit, dass wir uns die Änderungen von PHPUnit 9 genauer anschauen.

PHP 7.3 oder neuer benötigt

PHPUnit 9 benötigt PHP 7.3 (oder neuer). Die aktive Unterstützung von PHP 7.2 durch das PHP-Projekt endete am 30. November 2019. Stand heute werden nur PHP 7.3 und PHP 7.4 offiziell und aktiv unterstützt. PHPUnit 9 wird auf PHP 7.3 und PHP 7.4 unterstützt. Wenn Ende des Jahres PHP 8 erscheint, so wird auch diese Version sehr wahrscheinlich von PHPUnit 9 unterstützt werden.

Wenn Sie noch PHP 7.2 einsetzen, dann sollten Sie jetzt mit der Migration auf eine aktuelle PHP-Version, idealerweise PHP 7.4, beginnen. Das PHP-Projekt bietet keine Bugfixes mehr für PHP 7.2 und sicherheitskritische Fehler werden nur noch bis zum 30. November 2020 behoben. Ein langfristiges Ziel sollte sein, das Aktualisieren der eingesetzten PHP-Version als regelmäßige Aufgabe – und nicht als spezielles Projekt, das nur alle Jubeljahre angegangen wird – zu begreifen. Der entsprechende Aktualisierungsprozess sollte sich am aktiven Support des PHP-Projekts für aktuelle PHP-Versionen ausrichten.

Wenn Sie PHP 7.3 noch nicht verwenden können oder wollen, dann können Sie natürlich auch PHPUnit 9 noch nicht verwenden. Noch stellt dies kein allzu großes Problem dar, da PHPUnit 8.5, das noch mit PHP 7.2 funktioniert, bis Februar 2021 mit Bugfixes unterstützt wird. Allerdings verpassen Sie natürlich sämtliche Verbesserungen neuerer Versionen von PHP und PHPUnit.

Zusicherungsmethode assertEquals()

assertEquals() ist die am häufigsten genutzte Zusicherungsmethode. Leider, denn assertSame() ist fast immer die bessere Alternative. Im Laufe der Jahre wurden assertEquals() viele optionale Parameter hinzugefügt. Einige von diesen konnten nicht zusammen genutzt werden, was immer wieder zu Edge Case-Fehler in der zugrunde liegenden Implementierung geführt hat. Das Hauptproblem mit einer langen Liste von optionalen Parametern ist, dass man die ersten vier angeben muss, wenn man beispielsweise den fünften verwenden will. Und wer kann sich schon merken, wofür all diese Parameter gut sind? Ich jedenfalls nicht.

Um Abhilfe zu schaffen, wurden in PHPUnit 7.5 spezialisierte Alternativen eingeführt und in PHPUnit 8 die folgenden optionalen Parameter von assertEquals() abgekündigt:

  • $delta
  • $maxDepth
  • $canonicalize
  • $ignoreCase

Diese Parameter, von denen übrigens $maxDepth schon lange keinen Effekt mehr hatte, wurden nun in PHPUnit 9 entfernt.

Der optionale Parameter $delta konnte genutzt werden, um zwei Zahlenwerte so miteinander zu vergleichen, dass sie auch noch als gleich betrachtet werden, wenn sie — bis auf ein Delta — nur fast gleich sind. Beispielsweise stellt $this->assertEquals(1.0, 1.1, “, 0.1); sicher, dass der tatsächliche Wert 1.1 mit einem Delta von 0.1 dem erwarteten Wert 1.0 entspricht. Dies kann und muss nun einfacher und lesbarer mit $this->assertEqualsWithDelta(1.0, 1.1, 0.1); ausgedrückt werden.

Der optionale Parameter $canonicalize konnte genutzt werden, um sowohl den erwarteten als auch den tatsächlichen Wert vor ihrem Vergleich in eine kanonische (einheitliche) Form zu bringen. Für Werte vom Typ Array wird hierfür beispielsweise eine Sortierung durchgeführt. Da $canonicalize der sechste Parameter (sowie der vierte optionale Parameter nach den beiden nicht optionalen Parametern $expected und $actual) war, musste man eine solche Zusicherung in der Vergangenheit mit $this->assertEquals($expected, $actual, “, 0.0, 10, true); ausdrücken. Dies kann und muss nun einfacher und lesbarer mit $this->assertEqualsCanonicalizing($expected, $actual); ausgedrückt werden.

Der optionale Parameter $ignoreCase konnte genutzt werden, um Groß- und Kleinschreibung für den Vergleich von erwartetem und tatsächlichem Wert zu ignorieren. Eine solche Zusicherung konnte man in der Vergangenheit nur mit $this->assertEquals($expected, $actual, “, 0.0, 10, false, true); ausdrücken. Dies kann und muss nun einfacher und lesbarer mit $this->assertEqualsIgnoringCase($expected, $actual); ausgedrückt werden.

Der Vollständigkeit halber sei erwähnt, dass alles, was oben ausgeführt wurde, auch für assertNotEquals(), das Inverse zu assertEquals(), gilt.

Analog zum Entfernen der optionalen Parameter $canonicalize und $ignoreCase aus der API von assertEquals() wurden die entsprechenden optionalen Parameter ebenfalls aus der API von assertFileEquals() und assertStringEqualsFile() entfernt. An ihrer Stelle gibt es nun spezialisierte Zusicherungsmethoden:

  • assertFileEqualsCanonicalizing()
  • assertFileEqualsIgnoringCase()
  • assertStringEqualsFileCanonicalizing()
  • assertStringEqualsFileIgnoringCase()

Dies gilt natürlich auch für assertFileNotEquals() und assertStringNotEqualsFile(), die Inverse zu assertFileEquals() und assertStringEqualsFile().

Verwendung von assertContains() mit String-Haystacks nicht mehr möglich

Im Laufe der Zeit waren optionale Parameter auch zur assertContains()-Zusicherungsmethode hinzugefügt worden. Darüber hinaus wurde ihr Anwendungsbereich von Arrays sowie Objekten, die Iterator implementieren, auf Strings ausgeweitet. Immer wieder kam es dabei zu Problemen, die sich auch der Umsetzung verschiedener, teilweise miteinander in Konflikt stehenden, Use Cases in derselben Codeeinheit ergaben.

Um diese Probleme zu beheben, wurden in PHPUnit 7.5 spezialisierte Alternativen eingeführt, die nur auf Strings operieren. In PHPUnit 8 wurden die optionalen Parameter $checkForObjectIdentity, $checkForNonObjectIdentity und $ignoreCase abgekündigt. Darüber hinaus wurde die Verwendung von assertContains() mit String-Haystacks ebenfalls abgekündigt. Die genannten Parameter sowie die Möglichkeit, assertContains() mit String-Haystacks zu verwenden, wurden nun in PHPUnit 9 entfernt.

assertContains() wurde so geändert, dass immer ein typsicherer Vergleich (mit dem ===- Operator) durchgeführt wird. Ist ein Vergleich gewünscht, der nicht typsicher (mit dem ==- Operator) ist, so ist die neue assertContainsEquals()-Methode zu verwenden. Hier sind einige Beispiele:

  • assertContains(‚bar‘, ‚barbara‘, “, false) wird zu assertStringContainsString(‚bar‘, ‚barbara‘);
  • assertContains(‚bar‘, ‚barbara‘, “, true) wird zu assertStringContainsStringIgnoringCase(‚bar‘, ‚barbara‘);
  • assertContains(1, [1], “, false, true, false) wird zu assertContainsEquals(1, [1]);
  • assertContains(1, [1], “, false, true, true) wird zu assertContains(1, [1]);

Der Vollständigkeit halber sei erwähnt, dass alles, was oben ausgeführt wurde, auch für assertNotContains(), das Inverse zu assertContains(), gilt.

Die Zusicherungsmethode assertInternalType() konnte benutzt werden, um sicherzustellen, dass eine Variable einen Wert von einem bestimmten Typ enthält, der nicht benutzerdefiniert ist. Hier ist ein Beispiel, das zeigt, wie man sicherstellen konnte, dass eine Variable einen Wert vom Typ Array enthält: $this->assertInternalType(‚array‘, $variable);

Ein wichtiger Aspekt der oben gezeigten Zusicherung ist in einem Parameter, ‚array‘, versteckt. Das ist problematisch. Beispielsweise kann eine IDE keine automatische Vervollständigung für das Wort ‚array‘ anbieten. Darüber hinaus gibt es keinen Schutz vor Tippfehlern im String ‚array‘. Es ist ja schließlich nur ein String.

Um dieses Problem zu beheben, wurden in PHPUnit 7.5 spezialisierte Alternativen eingeführt. Diese neuen Zusicherungsmethoden verstecken keine wesentliche Information mehr in einem String-Parameter sondern machen ihre Verantwortlichkeit explizit in ihrem Methodennamen: $this->assertIsArray($variable);

Natürlich bedeutet eine explizitere API, dass es mehr Methoden gibt. Allerdings ist jede dieser Methoden einfacher, da sie nur genau einen Use Case implementiert. Dies führt zu Code, der einfacher zu verstehen ist. Er ist darüber hinaus einfacher zu schreiben, da die IDE nun automatische Vervollständigung bieten kann.

Der Vollständigkeit halber sei erwähnt, dass alles, was oben ausgeführt wurde, auch für assertNotInternalType(), das Inverse zu assertInternalType(), gilt.

assertArraySubset() in PHPUnit 9.0 entfernt

Die Methode assertArraySubset() war eine konstante Quelle von Verwirrung und Frustration, was man in vielen Tickets im Issue-Tracker von PHPUnit nachlesen kann.

Diese Situation war entstanden, weil ich den ursprünglichen Pull Request nicht gründlich genug geprüft hatte. Ich selbst hatte keine Verwendung für die vorgeschlagene Zusicherung. Auf den ersten Blick sah die Implementierung so aus, als würde sie den Use Case des Entwicklers, der die Zusicherung vorschlug, erfüllen. Im Laufe der Jahre habe ich immer wieder Pull Requests akzeptiert, von denen ich dachte, dass sie nur Fehler in der Implementierung von assertArraySubset() beheben. Allerdings fügten einige dieser Pull Requests neue Funktionalität hinzu, die teilweise im Konflikt zu anderen, bereits existierenden und unterstützten Anwendungsfällen von assertArraySubset() stand. Dies hätte nicht passieren dürfen. Allerdings konnte diese zusätzliche Funktionalität auch nicht mehr entfernt werden, ohne dass es zu einem Bruch der Abwärtskompatibilität gekommen wäre.

Während der Arbeit an PHPUnit 8 bin gelangte ich zu der Erkenntnis, dass die Probleme von assertArraySubset() nicht behoben werden können, ohne die Abwärtskompatibilität zu brechen. Ich beschloss daher, assertArraySubset() abzukündigen und die Methode in PHPUnit 9 zu entfernen. Dies führt zu einem Bruch der Abwärtskompatibilität, der explizit und offensichtlich ist. Jegliche Änderung am Verhalten von assertArraySubset() wäre auch ein Bruch der Abwärtskompatibilität, allerdings wäre dieser dann implizit und nicht offensichtlich, gewesen.

Wenn man die Funktionalität von assertArraySubset() benötigt, dann kann man diese durch Installation einer Erweiterung für PHPUnit von Rafael Dohms wiederherstellen.

Zu große Objekte mit problematischen Abhängigkeiten sind in Legacy Code üblich. Solche Objekte müssen häufig indirekt getestet werden, indem man ihren nicht öffentlichen Zustand betrachtet. In der Vergangenheit waren Zusicherungen wie assertAttributeEquals() eingeführt worden, die auf nicht öffentlichen Attributen arbeiten. Diese Zusicherungen waren ausschlie߬lich für das Testen von Legacy Code eingeführt worden. Ihre Verwendung war nie als Best Practice, schon gar nicht für neuen Code, empfohlen.

Leider wurden diese Zusicherungen allzu oft missbraucht, um neuen Code zu testen, bei dem man die Testbarkeit vernachlässigt hat. Es ist ein Fehler, den Inhalt von nicht öffentlichen Attributen testen zu wollen. Anstatt den Zustand eines Objektes testen zu wollen, sollte vielmehr das Verhalten eines Objekts getestet werden.

assertAttributeEquals() führte zu schlechten Testpraktiken

Es hat sich im Laufe der Jahre gezeigt, dass die Bereitstellung von Zusicherungen wie assertAttributeEquals() zu schlechten Testpraktiken geführt hat. Für PHPUnit 8 hatte ich mich daher entschlossen, diese Zusicherungen abzukündigen und in PHPUnit 9 wurden sie nun entfernt.

Nicht öffentliche Methoden dürfen nicht direkt getestet werden, indem man ihre Sichtbarkeit unter Zuhilfenahme der Reflection API umgeht. Der private Zustand eines Objekts darf ebenfalls nicht in einem Test betrachtet werden. Diese beiden Praktiken führen zu einer engen Kopplung von Testcode an den getesteten Code und damit dazu, dass man Implementierungsdetails anstelle der API testet. Sobald sich die Implementierung ändert geht der Test kaputt, da er sich auf private Implementierungsdetails verlässt.

Verwendung @expectedException-Annotations nicht mehr möglich

Lange Zeit galt es als Best Practice, Ausnahmen zu testen, indem man die erwartete Ausnahme mit Hilfe der @expectedException-Annotation am Test dokumentiert. Dieser Ansatz hat zwei fundamentale Probleme:

  • PHP bietet keine native Unterstützung für Annotationen. Stattdessen werden Annotation in Code-Kommentaren verwendet. In einem Code-Kommentar kann man keine unqualifizierten Klassennamen, beispielsweise Example anstatt vendor\project\Example, verwenden, wie man dies im Code tun könnte, nachdem man die Klasse in den aktuellen Namespace importiert hat.
  • Andererseits bleibt PHPUnit nichts anderes übrig, als einen Test als erfolgreich zu bewerten, wenn zu irgendeinem Zeitpunkt seiner Ausführung die über die Annotation angegebene Ausnahme ausgelöst wird. Dies ist nicht immer das, was man will.

Ich glaube mittlerweile, dass die Verwendung von Annotationen für das Erwarten von Ausnahmen mehr schadet als dass sie nutzt. Daher kündigte ich die Verwendung von Annotationen wie @expectedException in PHPUnit 8 ab und die entsprechende Funktionalität wurde nun in PHPUnit 9 entfernt.

Aus…

/**
 * @expectedException vendor\project\MyException
 */
public function testSomething(): void
{
    // ...
}

wird beispielsweise

public function testSomething(): void
{
    $this->expectException(MyException::class);

    // ...
}

expectExceptionMessageMatches() statt expectExceptionMessageRegExp()

Wo wir gerade beim Testen von Ausnahmen sind: in PHPUnit 9 gibt es die Methode expectExceptionMessageRegExp() nicht mehr. Sie wurde bereits in PHPUnit 8 abgekündigt. Stattdessen ist expectExceptionMessageMatches() zu verwenden.

Die Klassen PHPUnit\Framework\Error\Deprecated, PHPUnit\Framework\Error\Error, PHPUnit\Framework\Error\Notice, PHPUnit\Framework\Error\Warning sind interne Implementierungsdetails von PHPUnit, mit denen entsprechende PHP-Fehlersituationen repräsentiert werden. Dennoch musste man diese privaten Details von PHPUnit in seinen Tests bislang verwenden, um beispielsweise testen zu können, dass während eines Tests ein bestimmter PHP-Fehler auftritt (Listing 1).

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Error\Notice;

final class Test extends TestCase
{
    public function testOne()
    {
        $this->expectException(Notice::class);

        $a = $b;
    }
}

Mittlerweile gibt es spezialisierte Methoden, mit denen das erwartete Auftreten eines PHP-Fehlers dokumentiert werden kann:

  • expectDeprecation() für PHP-Fehler vom Typ E_DEPRECATED und E_USER_DEPRECATED
  • expectNotice() für PHP-Fehler vom Typ E_NOTICE, E_USER_NOTICE und E_STRICT
  • expectWarning() für PHP-Fehler vom Typ E_WARNING und E_USER_WARNING
  • expectError() für alle anderen Typen von PHP-Fehlern

Die Verwendung von expectException() mit PHPUnit\Framework\Error\Deprecated, PHPUnit\Framework\Error\Error, PHPUnit\Framework\Error\Notice, PHPUnit\Framework\Error\Warning ist seit PHPUnit 9 abgekündigt und wird mit PHPUnit 10 nicht mehr möglich sein. Das oben gezeigte Beispiel muss nun wie in Listing 2 folgt formuliert werden.

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class Test extends TestCase
{
    public function testOne()
    {
        $this->expectNotice();

        $a = $b;
    }
}

Mit den Methoden getMockBuilder(), createMock(), createConfiguredMock() und createPartialMock() können Objekte erzeugt werden, die anstelle einer echten Abhängigkeit beziehungsweise anstelle eines echten kollaborierenden Objekts in einem Test verwendet werden können. Hierzu genügt es, den Typ des Objekts, entweder in Form einen Schnittstellennamens oder eines Klassennamens, anzugeben: $this->createMock(Service::class) erzeugt ein Objekt, das so aussieht (denselben Typ hat) wie ein Service-Objekt, den Code des echten Objekts aber nicht ausführt.

Nur noch ein Typ für Erzeugnung eines Mock-Objekts erlaubt

Im Laufe der Jahre wurde der Code-Generator, der hinter den Kulissen von PHPUnit dafür sorgt, dass die oben gezeigte API für die Erzeugung von Mock-Objekten funktioniert, dahingehend erweitert, dass mehr als ein Typ für die Erzeugung eines Mock-Objektes angegeben werden kann. Da es fast immer ein Zeichen für schlechtes Softwaredesign ist, wenn man diese Funktionalität benötigt, und weil diese Funktionalität die Implementierung des Code-Generators für Mock-Objekte (unnötig) kompliziert macht, ist die Angabe von mehr als einem Typ für die oben aufgezählten Methoden in PHPUnit 9 abgekündigt. In PHPUnit 10 wird diese Funktionalität nicht mehr zur Verfügung stehen.

Die Möglichkeit, auf der Kommandozeile phpunit ServiceTest.php sowie alternativ phpunit ServiceTest aufrufen zu können, hat zu unnötig kompliziertem Code geführt, der schwer verständlich und sehr anfällig für Fehler geworden war. Der phpunit ServiceTest war daher bereits in PHPUnit 8 abgekündigt worden und wurde nun in PHPUnit 9 entfernt.

Jede Entwicklerin und jeder Entwickler kennt den Wunsch „Lasst uns das alles wegwerfen und auf der grünen Wiese neu anfangen!“. Auch mir ist dieser Wunsch nicht fremd und so habe ich im Laufe der Jahre mehrmals darüber nachgedacht, PHPUnit als Ganzes oder in Teilen (beispielsweise „nur“ der Testrunner) von Grund auf neu zu entwickeln. Zuletzt habe ich darüber vor zwei Jahren nachgedacht und meine Gedanken und Ideen in einem Vortrag geteilt. Ich habe mich bislang aber stets gegen einen solchen revolutionären Ansatz entschieden. Zum einen, weil er sehr viel Arbeit erfordern würde, die dazu noch an einem Stück geleistet werden müsste. Vor allem aber, weil es bei einem solchen Neuanfang fast unausweichlich wäre, dass sämtliche Tests, die PHPUnit verwenden, zumindest minimal – wahrscheinlich aber signifikant – angepasst werden müssten.

Ausblick

Für mich ergibt daher nur ein evolutionärer Ansatz Sinn, bei dem Schritt für Schritt Teile von PHPUnit ausgetauscht oder verbessert werden. Während eines Code Sprints im letzten Jahr hat beispielsweise Marco Pivetta sehr alten und unsauberen Code entfernt, der sich um das Parsen der Annotationen in PHPUnit-Tests kümmert. Der neue Code hat weniger Fehler und ist viel einfacher zu verstehen und anzupassen. Diese Arbeit ist bereits in PHPUnit 8 eingeflossen. Für PHPUnit 9 wurde nun der Code neu geschrieben, der sich um das Laden XML-Konfigurationsdatei kümmert. Für 2020 stehen die Umstellung sämtlicher Erweiterungsmöglichkeiten, insbesondere was das Logging anbelangt, auf dem Plan. Seit dem letzten Code Sprint wird dieses Thema von Ewout Pieter den Ouden, Andreas Möller und Arne Blankerts bearbeitet. Ihre Arbeit wird wahrscheinlich in PHPUnit 9.1 oder PHPUnit 9.2 einfließen.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -