Unittest erstellen

PHPUnit installieren

Sehr einfach ist die Installation unter Ubuntu. Dort kann phpunit einfach über aptitude installiert werden:

Oops, an error occurred! Code: 201904230354432c90c4d8

Eine weitere Möglichkeit ist die Installation von phpunit über pear:

Oops, an error occurred! Code: 20190423035443419f64b0

Nachdem eine Methode zur Installtion genutzt wurde, sollte man phpunit auf der Shell ausführen können.

Oops, an error occurred! Code: 2019042303544385103dff

Testfälle mit PHPUnit erstellen

Da Testfälle nicht mit dem Produkt ausgeliefert werden sollen macht es Sinn diese in einem eigenen Verzeichnis zu speichern. Ich verwenden bei diesem Projekt folgende Struktur:

  1. Project/Classes zum speichern der Klassen

  2. Project/Tests zum speichern der Testfälle


Wir beginnen zunächst mit einem einfachen Beispiel:

Wir haben eine „PersonCollection“ mit einer Sammlung von Personen. Für diese Collection möchten wir eine Methode implementieren, die uns alle Personen liefert, deren Nachname mit einem einem bestimmten Text beginnt.

Anmerkung: Diese Implementierung ist nur gedacht für kleine Collections die man alle im Speicher halten kann, bei größeren Collections würde man hier natürlich anders vorgehen ;)

Wir beginnen mit einem ersten Wurf des Testfalles und der Klassenstrutkur.

Zunächst der Testfall (Tests/PersonCollectionTest.php):

Oops, an error occurred! Code: 20190423035443010a262a

Ein Testfall hat folgenden Aufbau:

  1. Die Testklasse muss erben von „PHPUnit_Framework_TestCase“ dies ist die Basisklasse im PHPUnit Framework.

  2. In der Testklasse können Testfälle definiert werden, indem man der Methode the Annotation @test gibt, oder indem der Methodenname mit „test“ beginnt.

  3. Es gibt „assert*“ Methoden, mit denen man eigene Erwartungen formulieren kann. Werden alle Erwartungen erfüllt ist der Test grün. Wird eine Erwartung nicht erfüllt, so ist der Test rot. In unserem Fall erwarten wir das zwei Personen gefunden werden, die mit „Sch“ beginnen und drei Personen die mit „S“ beginnen. Sollte dies nicht der Fall sein, schlägt der Test fehl.

  4. Die Methode „setUp“ wir vor jedem Testfall ausgeführt. Also bevor jeder einzele Testmethode ausgeführt wird. Diese Methode ist dazu gedacht die Rahmenbedingungen für den Testfall herzustellen. In diesem Fall wird nur im Attribut „collection“ die Instanz der zu testenden Collection erstellt.

  5. Die Methode „tearDown“ ist das Gegenstück zu „setUp“ sie wird nach jedem Testfall ausgeführt. Im oberen Fall wurde sie nicht benötigt.


Damit der Test zunächst einmal genutzt werden kann. Müssen die verwendeten zu testenden Klassen angelegt werden.

Die Klasse Person(Classes/Person.php), sieht wie folgt aus :

Oops, an error occurred! Code: 201904230354439c401771

Die Klasse PersonCollection(Classes/PersonCollection) hat folgenden Aufbau:


Oops, an error occurred! Code: 20190423035443cf5ead28

Zunächst wurde nur die Strutkur angelegt und die Methode getLastnameStartingWith() hat noch keine Funktionalität. Diese Funktionalität soll nun Schritt für Schritt entwickelt werden.

Zunächst führen wir den Testfall aus und stellen fest, dass er fehlschlägt:



Oops, an error occurred! Code: 201904230354431078a927

Der Ausgabe kann entnommen werden, dass die Methode keine Collection zurückgibt. Der nächste Schritt ist die Implementierung der Methode.

Der nächste Versuch sieht so aus:


Oops, an error occurred! Code: 20190423035443aa346e52

Zugegebnermaßen enstand dies nicht beim erten Testlauf, denn Tippfehler etc. passieren immer wieder. Wenn wir die Funktionalität aber so umsetzen. So wird unser Testfall grün:

Oops, an error occurred! Code: 20190423035443e2fb8822

Refactoring - Getesteten Code anpassen

Nun ist einige Zeit vergangen und wir haben eine Idee wie die Funktion verbessert werden kann.

Mit der PHP Funktion iterator_apply und einer Closure erwarten wir eine schnellere Ausführung. Dank unseres Testfalles können wir sicherstellen, dass der Code noch unseren Erwartungen entspricht:

Folgendermaßen passen wir die Methode an:

Oops, an error occurred! Code: 20190423035443c6efe31f

Der PHPUnit Testcase stellt sicher, dass wir für unsere automatisierten Testfälle noch korrekte Ergebnisse bekommen. Ob die Änderun sich tatsächlich positiv auf die Performance auswirkt, muss anders ermittelt werden und wird später im Abschnitt „Performancetunning“ noch genauer beschrieben.


Tipps:

  1. Erstelle für deine Testfälle immer einer eigene Basistestklasse, die von PHPUnit_Testcase erbt. Dort kannst du zentrale Methoden implementieren, die du in allen Testfällen brauchst und kannst dort Änderungen durchführen wenn sich etwas in PHPUnit ändert (das ist selten notwendig.)


Ich hoffe dieser Artikel konnte einen Einstieg in die testgetriebene Entwicklung bieten. Das Ziel eines Testfalles ist es, nur die Funktionalität zu testen, für die der Testfall geschrieben wurde.

Im vorherigen Beispiel wurde jedoch mehr getestet. Neben der Funktionalität der „PersonCollection“ wurde indirekt auch die Funktionalität der „Person“ Klasse getestet. Bei einem so einfachen Beispiel ist das noch ok. Bei größeren Klassen jedoch nicht. Zu diesem Zweck gibt es „Mock“ Objekte. Ein „Mock“ Objekt dient dazu ein andere Objekt zu simulieren.

Im oberen Beispiel würde dies bedeuten. Das wir der Collection keine Personen Objekte übergeben, sondern Mock Objekte, die sich wie ein Personen Objekt verhalten.

Für den Beispieltestfall reicht es auch dass das Mock Objekt die Methode „getFirstName“ simuliert.



Mehr zum Thema Mock Objekte folgt im nächsten Abschnitt.


Navigation