Testen Sie Ihre PHP-Codebase mit EnhancePHP

Du weißt es; Ich weiß es. Wir sollten unseren Code mehr testen als wir. Ich denke, dass wir zum Teil nicht genau wissen, wie. Nun, ich werde diese Entschuldigung heute los: Ich lehre Sie, PHP mit dem EnhancePHP-Framework zu testen.


Lernen Sie EnhancePHP kennen

Ich werde nicht versuchen, Sie zu überzeugen, Ihren Code zu testen. und wir werden auch nicht über Test Driven Development sprechen. Das wurde schon vorher auf Nettuts + gemacht. In diesem Artikel erklärt Nikko Bautista genau, warum das Testen eine gute Sache ist, und skizziert einen TDD-Workflow. Lesen Sie das manchmal, wenn Sie mit TDD nicht vertraut sind. Er verwendet auch die SimpleTest-Bibliothek für seine Beispiele. Wenn Sie also das Aussehen von EnhancePHP nicht mögen, können Sie SimpleTest als Alternative ausprobieren.

Wie gesagt, wir werden den EnhancePHP verwenden. Es ist eine großartige kleine PHP-Bibliothek - eine einzige Datei -, die viele Testfunktionen bietet.

Beginnen Sie, indem Sie zu ihrer Download-Seite gehen und sich die neueste Version des Frameworks holen.

Wir werden eine wirklich einfache Validierungsklasse zum Testen erstellen. Es wird nicht zu viel tun: einfach zurückkehren wahr wenn der Artikel die Validierung besteht oder falsch wenn nicht Richten Sie also ein wirklich einfaches kleines Projekt ein:

Wir machen das auf eine halb-TDD-Mode, also schreiben wir zunächst ein paar Tests.


Tests schreiben

In unserer kleinen Klasse werden drei Dinge geprüft: E-Mail-Adressen, Benutzernamen und Telefonnummern.

Aber bevor wir tatsächliche Tests schreiben können, müssen wir unsere Klasse einrichten:

  val = new Validation (); 

Dies ist unser Start. Beachten Sie, dass wir die Klasse erweitern \ Enhance \ TestFixture. Dadurch teilen wir EnhancePHP mit, dass alle öffentlichen Methoden dieser Klasse Tests sind, mit Ausnahme von Methoden Konfiguration und niederreissen. Wie Sie sich vorstellen können, laufen diese Methoden vor und nach allen Tests (nicht vor und nach jedem Test). In diesem Fall unser Konfiguration Methode erstellt eine neue Validierung Instanz und ordnen Sie es einer Eigenschaft in unserer Instanz zu.

Übrigens, wenn Sie mit PHP noch relativ neu sind, sind Sie damit vielleicht nicht vertraut \ Enhance \ TestFixture Syntax: Was ist mit den Schrägstrichen? Das ist PHP-Namensraum für Sie. Schauen Sie sich die Dokumente an, wenn Sie nicht damit vertraut sind.

Also die Tests!

E-mailadressen

Beginnen wir mit der Überprüfung der E-Mail-Adressen. Wie Sie sehen werden, ist es ganz einfach, einen einfachen Test durchzuführen:

 öffentliche Funktion validates_a_good_email_address () $ result = $ this-> val-> validate_email ("[email protected]"); \ Enhance \ Assert :: isTrue ($ result); 

Wir nennen einfach die Methode, die wir testen möchten, übergibt eine gültige E-Mail-Adresse und speichert die $ Ergebnis. Dann reichen wir $ Ergebnis zum ist wahr Methode. Diese Methode gehört zum \ Verbessern \ Assert Klasse.

Wir möchten sicherstellen, dass unsere Klasse keine E-Mail-Adressen ablehnt. Also lassen Sie uns das testen:

 öffentliche Funktion reject_bad_email_addresses () $ val_wrapper = \ Enhance \ Core :: getCodeCoverageWrapper ('Validation'); $ val_email = $ this-> get_scenario ('validate_email'); $ address = array ("john", "[email protected]", "john @ doe.", "jo*[email protected]"); foreach ($ address as $ addr) $ val_email-> mit ($ addr) -> expect (false);  $ val_email-> verifyExpectations (); 

Dies führt eine ziemlich coole Funktion von EnhancePHP ein: Szenarien. Wir möchten einige Nicht-E-Mail-Adressen testen, um sicherzustellen, dass unsere Methode zurückgegeben wird falsch. Durch das Erstellen eines Szenarios packen wir eine Instanz unserer Klasse in etwas EnhancePHP-Güte. Sie schreiben viel weniger Code, um alle unsere Nicht-Adressen zu testen. Das ist, was $ val_wrapper ist: eine modifizierte Instanz unseres Validierung Klasse. Dann, $ val_email ist das Szenarioobjekt, eine Art Verknüpfung zu E-Mail validieren Methode.

Dann haben wir eine Reihe von Zeichenfolgen, die nicht als E-Mail-Adressen validiert werden sollten. Wir werden dieses Array mit einem Loop durchlaufen für jeden Schleife. Beachten Sie, wie wir den Test ausführen: Wir rufen das an mit Methode in unserem Szenarioobjekt, übergeben Sie die Parameter für die zu testende Methode. Dann rufen wir die an erwarten von Methode darauf und geben Sie es weiter, was wir erwarten, zurück zu kommen.

Zum Schluss nennen wir das Szenario verifyExpectations Methode.

So werden die ersten Tests geschrieben; Wie lassen wir sie laufen??


Tests ausführen

Bevor wir die Tests tatsächlich ausführen, müssen wir unsere erstellen Validierung Klasse. Innerhalb lib.validation.php, fange damit an:

  

Jetzt in test.php, Wir ziehen alles zusammen:

  

Zuerst benötigen wir alle erforderlichen Dateien. Dann rufen wir die an runTests Methode, die unsere Tests findet.

Als nächstes kommt der ordentliche Teil. Starten Sie einen Server und Sie erhalten eine schöne HTML-Ausgabe:

Sehr schön, richtig? Wenn Sie PHP in Ihrem Terminal installiert haben, führen Sie Folgendes aus:

EnhancePHP stellt fest, dass Sie sich in einer anderen Umgebung befinden, und passt die Ausgabe entsprechend an. Ein Nebeneffekt davon ist, dass wenn Sie eine IDE wie PhpStorm verwenden, die Gerätetests ausführen kann, Sie die Ausgabe dieses Terminals direkt in der IDE anzeigen können.

Sie können auch XML- und TAP-Ausgaben erhalten. Wenn Sie dies bevorzugen, übergeben Sie einfach \ Enhance \ TemplateType :: Xml oder \ Erweitern \ TemplateType :: Tippen Sie auf zum runTests Methode, um die entsprechende Ausgabe zu erhalten. Wenn Sie das Programm im Terminal ausführen, werden auch Befehlszeilenergebnisse generiert, unabhängig davon, an was Sie übergeben werden runTests.

Die Tests bestehen

Lassen Sie uns die Methode schreiben, durch die unsere Tests bestanden werden. Wie Sie wissen, ist es das E-Mail validieren. An der Spitze der Validierung Klasse, definieren wir eine öffentliche Eigenschaft:

 public $ email_regex = '/^[\w+-_\.!+@[\w\.(++\.\w+$/';

Ich stelle dies in eine öffentliche Eigenschaft, damit der Benutzer es durch seinen eigenen Regex ersetzen kann. Ich verwende diese einfache Version einer E-Mail-Regex, aber Sie können sie durch Ihren bevorzugten Regex ersetzen, wenn Sie möchten.

Dann gibt es die Methode:

 öffentliche Funktion validate_email ($ address) return preg_match ($ this-> email_regex, $ address) == 1

Jetzt führen wir die Tests erneut durch und:


Weitere Tests schreiben

Zeit für weitere Tests:

Benutzernamen

Lassen Sie uns jetzt einige Tests für Benutzernamen erstellen. Unsere Anforderungen sind einfach, dass es sich um eine Zeichenfolge von 4 bis 20 Zeichen handeln muss, die nur aus Wortzeichen oder Punkten besteht. So:

 öffentliche Funktion validates_a_good_username () $ result = $ this-> val-> validate_username ("some_user_name.12"); \ Enhance \ Assert :: isTrue ($ result); 

Wie wäre es mit ein paar Benutzernamen, die nicht bestätigt werden sollten:

 public function rejects_bad_usernames () $ val_username = $ this-> get_scenario ('validate_username'); $ usernames = array ("Name mit Leerzeichen", "Nein! Ausruf! Markieren", "ts", "thisUsernameIsTooLongItShouldBeBetweenFourAndTwentyCharacters"); foreach ($ usernames als $ name) $ val_username-> mit ($ name) -> expect (false);  $ val_username-> verifyExpectations (); 

Dies ist unserem sehr ähnlich reject_bad_email_addresses Funktion. Beachten Sie jedoch, dass wir das nennen get_scenario Methode: Woher kommt das? Ich abstrahiere die Szenarioerstellungsfunktionalität in private Methoden am Ende unserer Klasse:

 private Funktion get_scenario ($ method) $ val_wrapper = \ Verbesserung \ Core :: getCodeCoverageWrapper ('Validation'); return \ Enhance \ Core :: getScenario ($ val_wrapper, $ -Methode); 

Wir können das in unserem verwenden reject_bad_usernames und ersetzen Sie die Szenarioerstellung in reject_bad_email_addresses auch. Da dies eine private Methode ist, versucht EnhancePHP nicht, sie als normalen Test auszuführen, wie es bei öffentlichen Methoden der Fall ist.

Wir machen diese Tests ähnlich wie beim ersten Set-Pass:

 # An der Spitze… public $ username_regex = '/^[\w\.(4,20$/'; # und die Methode… public function validate_username ($ username) return preg_match ($ this-> username_regex, $ username) == 1; 

Das ist natürlich ziemlich einfach, aber das ist alles, was nötig ist, um unser Ziel zu erreichen. Wenn wir im Fehlerfall eine Erklärung zurückgeben möchten, können Sie Folgendes tun:

 öffentliche Funktion validate_username ($ username) $ len = strlen ($ username); if ($ len < 4 || $len > 20) return "Der Benutzername muss aus 4 bis 20 Zeichen bestehen";  elseif (preg_match ($ this-> username_regex, $ username) == 1) return true;  else return "Der Benutzername darf nur Buchstaben, Zahlen, Unterstriche oder Punkte enthalten."; 

Natürlich möchten Sie auch prüfen, ob der Benutzername bereits existiert.

Führen Sie nun die Tests aus und Sie sollten alle sehen, wie sie bestanden.

Telefonnummern

Ich denke, Sie haben jetzt den Dreh raus, also beenden wir unser Validierungsbeispiel mit der Überprüfung der Telefonnummern:

 öffentliche Funktion validates_good_phonenumbers () $ val_phonenumber = $ this-> get_scenario ("validate_phonenumber"); $ numbers = array ("1234567890", "(890) 123-4567"), "123-456-7890", "123456 7890", "(123) 456 7890"); foreach ($ zahlen als $ num) $ val_phonennummer-> mit ($ num) -> expect (true);  $ val_phonennummer-> verifyExpectations ();  public function rejects_bad_phonenumnbers () $ result = $ this-> val-> validate_phonenumber ("123456789012"); \ Enhance \ Assert :: isFalse ($ result); 

Sie können das wahrscheinlich herausfinden Validierung Methode:

 public $ phonumber_regex = '/ ^ \ d 10 $ | ^ (\ (? \ d 3 \)? [| -] \ d 3 [| -] \ d 4) $ /'; öffentliche Funktion validate_phonennummer ($ number) return preg_match ($ this-> phonenumber_regex, $ number) == 1; 

Jetzt können wir alle Tests zusammen ausführen. So sieht das in der Befehlszeile aus (meiner bevorzugten Testumgebung):


Andere Testfunktionalität

Natürlich kann EnhancePHP viel mehr als das, was wir uns in diesem kleinen Beispiel angesehen haben. Schauen wir uns jetzt einiges an.

Wir haben den sehr kurz getroffen \ Verbessern \ Assert Klasse in unserem ersten Test. Ansonsten haben wir es nicht wirklich verwendet, weil es bei Szenarien nicht sinnvoll ist. Hier sind jedoch alle Assertionsmethoden. Das Schöne an ihnen ist, dass ihre Namen ihre Funktionalität unglaublich offensichtlich machen. Die folgenden Testbeispiele würden bestehen:

  • \ Enhance \ Assert :: areIdentical ("Nettuts +", "Nettuts +")
  • \ Enhance \ Assert :: areNotIdentical ("Nettuts +", "Psdtuts +")
  • \ Enhance \ Assert :: isTrue (true)
  • \ Enhance \ Assert :: isFalse (false)
  • \ Enhance \ Assert :: enthält ("Net", "Nettuts +")
  • \ Enhance \ Assert :: isNull (null)
  • \ Enhance \ Assert :: isNotNull ('Nettust +')
  • \ Enhance \ Assert :: isInstanceOfType ('Exception', neue Exception (""))
  • \ Enhance \ Assert :: isNotInstanceOfType ('String', neue Ausnahme (""))

Es gibt auch einige andere Assertionsmethoden; Sie können in den Dokumenten nach einer vollständigen Liste und Beispielen suchen.

Mocks

EnhancePHP kann auch Mocks und Stubs ausführen. Haben Sie noch nie von Spott und Stummeln gehört? Nun, sie sind nicht zu kompliziert. Ein Mock ist ein Wrapper für object, der verfolgt, welche Methoden aufgerufen werden, mit welchen Eigenschaften sie aufgerufen werden und welche Werte zurückgegeben werden. Ein Mock muss noch getestet werden, wie wir sehen werden.

Hier ist ein kleines Beispiel eines Spottes. Beginnen wir mit einer sehr einfachen Klasse, die zählt:

 num = $ this-> num + $ num; $ this-> num zurückgeben; 

Wir haben eine Funktion: Zuwachs, das akzeptiert einen Parameter (aber standardmäßig 1) und erhöht den Wert $ num Eigenschaft durch diese Nummer.

Wir könnten diese Klasse verwenden, wenn wir eine Anzeigetafel bauen würden:

 Klassenanzeigetafel public $ home = 0; public $ away = 0; öffentliche Funktion __construct ($ home, $ away) $ this-> home_counter = $ home; $ this-> away_counter = $ away;  public function score_home () $ this-> home = $ this-> home_counter-> increment (); $ this-> home zurückgeben;  public function score_away () $ this-> away = $ this-> away_counter-> increment (); $ this-> home zurückgeben; 

Nun wollen wir testen, ob das stimmt Zähler Instanzmethode Zuwachs funktioniert einwandfrei, wenn die Anzeigetafel Instanzmethoden nennen es. Also erstellen wir diesen Test:

 class ScoreboardTest erweitert \ Enhance \ TestFixture öffentliche Funktion score_home_calls_increment () $ home_counter_mock = \ Enhance \ MockFactory :: createMock ("Counter"); $ away_counter = new Counter (); $ home_counter_mock-> addExpectation (\ Enhance \ Expect :: method ('increment')); $ Scoreboard = neues Scoreboard ($ home_counter_mock, $ away_counter); $ scoreboard-> score_home (); $ home_counter_mock-> verifyExpectations ();  \ Enhance \ Core :: runTests ();

Beachten Sie, dass wir mit dem Erstellen beginnen $ home_counter_mock: Wir verwenden die EnhancePHP-Scheinfabrik und geben ihr den Namen der Klasse, die wir verspotten. Dies gibt eine "umschlossene" Instanz von zurück Zähler. Dann fügen wir mit dieser Zeile eine Erwartung hinzu

 $ home_counter_mock-> addExpectation (\ Enhance \ Expect :: method ('increment'));

Unsere Erwartung sagt nur, dass wir das erwarten Zuwachs zu rufende Methode.

Danach erstellen wir das Anzeigetafel Instanz und rufen Sie an score_home. Dann sind wir verifyExpectations. Wenn Sie dies ausführen, werden Sie feststellen, dass unser Test erfolgreich ist.

Wir können auch angeben, mit welchen Parametern eine Methode für das Scheinobjekt mit aufgerufen werden soll, welcher Wert zurückgegeben wird oder wie oft die Methode aufgerufen werden soll.

 $ home_counter_mock-> addExpectation (\ Enhance \ Expect :: method ('increment') -> with (10)); $ home_counter_mock-> addExpectation (\ Enhance \ Expect :: method ('increment') -> times (2)); $ home_counter_mock-> addExpectation (\ Enhance \ Expect :: method ('increment') -> Returns (1)); $ home_counter_mock-> addExpectation (\ Enhance \ Expect :: method ('increment') -> mit (3) -> times (1)); $ home_counter_mock-> addExpectation (\ Enhance \ Expect :: method ('increment') -> with (2) -> Returns (2));

Ich sollte das erwähnen, während mit und mal zeigt fehlgeschlagene Tests an, wenn die Erwartungen nicht gemeint sind, kehrt zurück tut nicht Sie müssen den Rückgabewert speichern und dazu eine Assertion verwenden. Ich bin nicht sicher, warum das so ist, aber jede Bibliothek hat ihre Macken :). (Ein Beispiel dafür finden Sie in den Bibliotheksbeispielen in Github.)

Stubs

Dann gibt es Stubs. Ein Stub füllt ein reales Objekt und eine Methode aus und gibt genau das zurück, was Sie ihm sagen. Nehmen wir also an, wir wollen sicherstellen, dass unser Anzeigetafel Die Instanz verwendet den von ihr erhaltenen Wert korrekt Zuwachs, wir können ein stummeln Zähler So können wir kontrollieren, was Zuwachs wird zurückkehren:

 class ScoreboardTest erweitert \ Enhance \ TestFixture öffentliche Funktion score_home_calls_increment () $ home_counter_stub = \ Enhance \ StubFactory :: createStub ("Counter"); $ away_counter = new Counter (); $ home_counter_stub-> addExpectation (\ Enhance \ Expect :: method ('increment') -> Returns (10)); $ Scoreboard = neues Scoreboard ($ home_counter_stub, $ away_counter); $ result = $ scoreboard-> score_home (); \ Enhance \ Assert :: areIdentical ($ result, 10);  \ Enhance \ Core :: runTests ();

Hier verwenden wir \ Enhance \ StubFactory :: createStub um unseren Stub-Counter zu erstellen. Dann fügen wir eine Erwartung hinzu, dass die Methode Zuwachs wird zurückkehren 10. Wir können sehen, dass das Ergebnis das ist, was wir angesichts unseres Codes erwarten würden.

Weitere Beispiele für Mocks und Stub mit der EnhancePHP-Bibliothek finden Sie im Github Repo.


Fazit

Nun, das ist ein Blick auf das Testen in PHP mit dem EnhancePHP-Framework. Es ist ein unglaublich einfaches Framework, aber es bietet alles, was Sie für ein paar einfache Unit-Tests Ihres PHP-Codes benötigen. Selbst wenn Sie sich für eine andere Methode / ein anderes Framework für das Testen Ihres PHP entscheiden (oder vielleicht Ihr eigenes machen!), Hoffe ich, dass dieses Tutorial ein Interesse daran hat, Ihren Code zu testen, und wie einfach er sein kann.

Aber vielleicht testen Sie Ihr PHP bereits. Lassen Sie uns alle wissen, was Sie in den Kommentaren verwenden. Wir sind alle hier, um voneinander zu lernen! Vielen Dank für Ihren Besuch!