https://d226lax1qjow5r.cloudfront.net/blog/blogposts/converting-your-test-suite-to-pest/shifting-to-pest.png

Konvertierung Ihrer Testsuite in PEST

Zuletzt aktualisiert am December 16, 2021

Lesedauer: 10 Minuten

Die Änderung der Art und Weise, wie ich Code schreibe, durch die testgetriebene Entwicklung hat ganz offen gesagt meine Fähigkeiten als Programmierer verändert. Plötzlich konnte ich selbstbewusst Dienste und Funktionen schreiben - es ist mir ein Rätsel, warum so viele Unternehmen immer noch "Sie haben keine Zeit zum Testen" - und das schon seit langem, PHPUnit das de-facto-Werkzeug der Wahl, wenn man TDD-PHP schreibt.

Vor kurzem ist ein neues Projekt aufgetaucht, das dies ändern könnte. Es gibt gute Dokumentation und eine Meeting-Gemeinschaft die sich um das Projekt herum gebildet hat und sich als attraktive Option für Entwickler erweist. Ich beziehe mich natürlich auf PEST, also dachte ich, ich probiere es mal mit unserem eigenen Vonage PHP SDK.

Die aktuelle Suite

Unser PHP-SDK von Vonage wurde über die Jahre hinweg umfassend gewartet und enthält daher eine vollständige Testsuite. Es ist zwar nicht auf Unternehmensebene angesiedelt, aber dennoch eine nützliche Übung, um PEST zu testen.

Die aktuelle Suite auf diesem Zweig hat 831 bestandene Tests, die 4039 Assertions ausführen. Es gibt 9 übersprungene Tests und 15 unvollständige Tests. Die Gesamtausführungszeit beträgt 13:54 in PHP8.

Screenshot of total tests showing 9 skipped and 15 incomplete tests.Screenshot of total tests showing 9 skipped and 15 incomplete tests.

Für das Protokoll, es läuft ziemlich anständig und einer dieser Tests ist eigentlich ein Timeout-Test, der die Zeit in die Höhe treibt. Das Ziel ist nicht, den Läufer zu verbessern, sondern ihn zu verändern, um zu sehen, was passiert. Unsere erste Anlaufstelle ist PEST installieren zu installieren und auszuführen. Eine der wichtigsten Eigenschaften von PEST ist, dass Es ist vollständig abwärtskompatibel mit PHPUnitkompatibel ist und daher unabhängig von der verwendeten Syntax verwendet werden kann. Dies ermöglicht es uns, PEST zu installieren, es auszuführen, um die Ergebnisse zu sehen und möglicherweise zu versuchen, das neue parallelen Testen Funktion zu implementieren.

Um PEST zu installieren, gebe ich folgendes in die Befehlszeile ein:

composer require pestphp/pest

Es scheint trügerisch einfach zu sein, dass ich einen Composer-Befehl später PEST ausführen kann. Es ist jedoch erwähnenswert, dass dieses Repository, auf dem es laufen wird, bereits Anforderungen hat - eine dieser Anforderungen ist eine minimale PHP-Version von 7.3. PEST hat bereits eine Mindestversion von PHP, die 7.3 und höher sein muss, so dass es nicht nötig ist, sich auf den neuesten Stand zu bringen.

Es ist an der Zeit, PEST auszuführen und zu sehen, was passiert:

./vendor/bin/pest

Das erste, was Sie bemerken werden, ist, dass PEST ein Ausgabeformat verwendet, das dem --testdox Argument, um die Ausgabe von PHPUnit zu formatieren. Die Ausgabe ist ziemlich gut:

Test screenshot, showing a time of 13.21 seconds.Test screenshot, showing a time of 13.21 seconds.

Hmm, also 13,28 Sekunden, was? Nun, das ist tatsächlich schneller, wenn man nur den Läufer allein benutzt. Wie wäre es, wenn wir die Parallelfunktion von PEST nutzen? Sie ist in einem separaten Paket enthalten, also holen wir sie uns:

composer require pestphp/pest-plugin-parallel

Und jetzt wird es ausgeführt:

./vendor/bin/pest -parallel

Und... oh. Nun, es sieht so aus, als ob unser Glück uns verlassen hat:

Screenshot of a PHP bug.Screenshot of a PHP bug.

Ein kurzes Googeln zeigt, dass es dafür einen Fehler in PHP selbst gibt, wie im PHPUnit-Protokoll dokumentiert:

https://github.com/sebastianbergmann/phpunit/issues/4305

Ich denke, das ist der Preis, den wir dafür zahlen, dass wir ein wenig auf der Höhe der Zeit sind.

Photo of frustrated person looking at their laptop screen.Photo of frustrated person looking at their laptop screen.

PHPUnit-Syntax vs. PEST

Ich habe mit dem Test-Runner gespielt, aber nicht den Code gezeigt oder erklärt, was der eigentliche Zweck von PEST ist.

Laravel-Kernmitglied Nuno Madro hat mit PEST ein neues Framework geschaffen, das sich an der Syntax der Jest Javascript-Frameworks. Es entspricht dem aktuellen Trend von PHP (und insbesondere von Laravel), sich zu einer mehr auf Closure basierenden, funktionalen Syntax zu bewegen, ähnlich der Art und Weise, wie Javascript geschrieben wird. Es ist also logisch, dass Ihre PHP-Backend-Tests für Ihre Full-Stack-Webanwendung in einer ähnlichen Syntax geschrieben werden wie Ihre Frontend-Tests. Hier ein "Vorher-Nachher"-Beispiel aus dem Vonage PHP SDK:

class NumberTest extends VonageTestCase  
{  

 /**  
 * @var Number;  
 */
 protected $number;  
  
 public function setUp(): void  
 {  
	$this->number = new Number('14843331212');  
 }  
 
 public function testNumberConstructor(): void  
 {   
	$this->assertEquals('14843331212', $this->number->getNumber());  
 }

Wir verwenden hier ein paar gängige Muster - die magische Methode setUp() läuft, bevor die Tests ausgeführt werden, und dann verwenden wir assertEquals() die eine Hilfsklasse von PHPUnit ist TestCase (in unserem Beispiel, VonageTestCase erweitert von ihr weiter oben).

Nun möchte ich Ihnen denselben Test zeigen, allerdings in der PEST-Syntax geschrieben:

use Vonage\Numbers\Number;  
  
beforeEach(function () {  
   $this->number = new Number();  
});  
  
test('number constructor', function () {  
   expect($this->number->getNumber())->toEqual('14843331212');  
});

Dies ist ein gutes Beispiel dafür, dass sich das PHP-Ökosystem bei neuen Ideen generell an Javascript orientiert - wie Sie sehen können, ist die PEST-Syntax JEST sehr ähnlich. Es zeigt auch einen der Kernwerte von PEST, nämlich eine fließendere Methodenverkettung in der API, um weniger Code zu schreiben, was von der Philosophie her ein sehr Laravel-ähnlicher Ansatz ist. Wir haben jetzt eine höhere Ordnung beforeEach() mit einer Closure darin, die vor jedem Test ausgeführt wird, und die klassischen PHP-Funktionsstrukturen von PHPUnit wurden durch eine funktionalere Syntax ersetzt. Dieses Beispiel zeigt auch, wie die Erwartungs-API entwickelt wurde, um Assertions in einer für den Menschen lesbaren Weise zu verketten, mit Methodennamen wie expect(true)->toBe(value) oder expect($variable)->toBeArray().

OK, also Automatisierung?

Ich will ehrlich sein, das lief nicht so, wie ich es wollte. Ich werde Ihnen aber zeigen, warum.

Ich bin darauf aufmerksam geworden von Twitter dass es tatsächlich möglich sein könnte, ein Tool zu verwenden, das Ihre PHPUnit-Suite automatisch in PEST konvertiert, unabhängig davon, ob der Code in Laravel ist oder nicht. Also machte ich mich auf den Weg zum Pest Konverter und ein Respository und einen Zweig eingerichtet, um es auszuprobieren Wenn es ausgeführt wird, erstellt Shift einen neuen Zweig aus dem Basiszweig, den Sie bereitstellen, und erstellt logische Schritt-Commits, um sich durch die Syntax zu bewegen. Eines der Dinge, die zuerst getan werden mussten, war die Änderung des test/ Ordner in tests/ zu ändern, damit der Konverter weiß, wo er nach Ihren Tests suchen muss.

Bei der Ausführung von PEST nach der Konvertierung:

Screenshot showing PestxceptionsestCaseClarrOrTrailNotFound.Screenshot showing Pest\Exceptions\TestCaseClarrOrTrailNotFound.

Hmm. Also, kein reibungsloser Ablauf also. Es ist erwähnenswert, dass ich aus mehreren Gründen keine Ahnung hatte, was mich erwarten würde:

  • Das PHP-SDK von Vonage ist Framework-unabhängig

  • Es hängt von der Prophesize Bibliothek ab.

  • Es werden eine Reihe von PHP-Traits verwendet, die die Testsuite etwas komplexer machen

PEST verwendet keine traditionelle Komposition, sondern hat ein anderes Konfigurationsmuster. PEST hat eine pest.php Konfigurationsdatei, die es Ihnen ermöglicht, Hilfsfunktionen, Traits und allgemeine Methoden wie RefreshDatabase. Sie können auch angeben, auf welche Ordner die Klassen angewendet werden sollen:

uses(\VonageTest\HTTPTestTrait::class)->in('Secrets');

Der Grund dafür, dass der PEST-Konverter diese nicht auflösen kann, ist eine Reihe von Randfällen. Eine Sache, auf die Laravel Shift's Jason McCreary in unseren Supportgesprächen darauf hingewiesen hat, ist, dass einige Tests einen Anwendungscontainer in $this->appsetzen, was zu Konflikten mit der Anwendungsinfrastruktur von Laravel führt (da es nicht weiß, ob Sie eine Laravel-Anwendung haben oder nicht).

Schlussfolgerungen

OK, auch wenn der PEST-Konverter Schwierigkeiten hatte, die Übertragung der Tests zu automatisieren, führt dies zu zwei Schlussfolgerungen:

  • Laravel Shift, die Schöpfer des Pest-Konverters, schauen sich bereits die Randfälle in unserer Bibliothek an, die ich verwendet habe, und arbeiten daran, wie sie gehandhabt werden können, aber noch wichtiger ist

  • Führen Sie den Konverter nicht aus, wenn Ihre Testsuite komplex oder überentwickelt ist - beheben Sie das zuerst

Wie bei allem gibt es auch bei der Automatisierung eines größeren Refactorings Risiken. In unserem Fall bestand das Risiko darin, dass wir es mit einer reinen PHP-Bibliothek ohne Framework zu tun haben. Shift arbeitet jedoch mit der Aktualisierung über einen Zielzweig und erstellt dann den Shift-Zweig, um das Risiko zu minimieren. Wenn es nicht funktioniert, lassen Sie es einfach bleiben! Sie haben auch die Möglichkeit, den Menschliche Verschiebung Dienst zu verwenden, was unweigerlich zu einer vollständig konvertierten Suite führt.

Was ich empfehlen würde, ist, dass, wenn Sie eine Symfony oder Laravel App haben, dieser Konverter ist absolut mit diesen Fällen im Verstand entworfen, so dass die Shift ziemlich solide sein wird.

Sollten Sie PEST einführen? Das hängt wie immer von Ihnen ab. Wenn Sie immer auf dem neuesten Stand der Dinge sein wollen, die sich in PHP ändern, dann ist dies sicherlich eine attraktive Option. Bedenken Sie aber, dass die Syntax von PEST natürlich mit dem Ansatz von Laravel für API-Flows übereinstimmt, so dass es das Potenzial hat, Ihre Entwickler zu verwirren, wenn Sie etwas anderes Beliebtes wie Symfony, CakePHP oder Drupal verwenden.

Teilen Sie:

https://a.storyblok.com/f/270183/400x385/12b3020c69/james-seconde.png
James SecondeSenior PHP Entwickler Advocate

Als ausgebildeter Schauspieler mit einer Dissertation in Standup-Comedy bin ich über die Meetup-Szene zur PHP-Entwicklung gekommen. Man findet mich, wenn ich über Technik spreche oder schreibe, oder wenn ich seltsame Platten aus meiner Vinylsammlung spiele oder kaufe.