SlideShare ist ein Scribd-Unternehmen logo
1 von 11
Downloaden Sie, um offline zu lesen
PHPUnit Tests mit Magento
Ist der Einsatz der Magento 2 Testsuite in Magento möglich? Und wie läuft die Portierung?
Index:
Mögliche Testverfahren
Portierung der Testsuite
Anlegen von Testdaten
Probleme beim Einsatz der Testsuite
Fazit
www.techdivision.com
1TechDivision GmbH PHPUnit Tests mit Magento
Magento stellt seinen Entwicklungspartnern
künftig die Testsuite und den Magento
Automated Testing Guide [1] zur Verfügung.
Eine der größten Schwächen von Magento, wenn man im
Vergleich zu anderen Shopsystemen überhaupt von
Schwächen sprechen kann, besteht sicherlich im Fehlen
einer PHPUnit-Testsuite analog der, die mit Magento 2
eingeführt wird. Da seitens Magento momentan kein finaler
Fertigstellungstermin für Magento 2 genannt wurde, wird
Magento sicherlich noch länger als ursprünglich erwartet für
Projekte zum Einsatz kommen. Anscheinend wird dem auch
seitens Magento Rechnung getragen, da sich seit Version
CE 1.7.x sowie EE 1.12.x auch hinsichtlich der Testbarkeit
mit PHPUnit einiges getan hat.
Jeder Entwickler, der mit Magento arbeitet, vermisst
sicherlich schmerzlich eine Testsuite, die die
Basisfunktionalität von Magento mit Unit- und
Integrationsstest automatisiert testbar macht. Zusätzlich
sollen natürlich auch die eigenen Entwicklungen für sich
sowie in Abhängigkeit der Basisfunktionalität testbar sein.
Sieht man sich die Testsuite von Magento 2 etwas
detaillierter an, ist gut erkennbar, in welche Richtung
Magento hier künftig gehen wird. Nachdem die Qualität für
die Solution Partner als eines der zentralen Kriterien in die
Bewertung des Partners mit einfließt, stellt Magento seinen
Entwicklungspartnern künftig mit der Testsuite und dem
Magento Automated Testing Guide [1] die Tools für die
notwendige Verbesserung der Qualität, und somit auch der
Partnerbewertung durch Magento, zur Verfügung.
Dieser Artikel beschreibt die notwendigen Schritte zur
Migration der Testsuite von Magento 2 auf Magento und
zeigt anhand von Beispielen diverse Einsatzmöglichkeiten
sowie die mögliche Integration in einen Build- und
Deploymentprozess.
von Tim Wagner
Die Testsuite bringt Tests für die gängigsten vier
Testverfahren mit. So werden Unit-, Integrations- und
Performancetests ausgeliefert. Zusätzlich enthält die Suite
Tests für die statische Code-Analyse. Bis auf die
Performance Tests bauen alle Tests auf PHPUnit [2] von
Sebastian Bergmann auf. Dieser Artikel beschäftigt sich
hauptsächlich mit den Unit- und den Integrationstests, da
diese für die meisten Entwickler die größte Bedeutung
haben. Durch die Integration dieser beiden Testverfahren
wird die Qualität und somit die auch Wartbarkeit von
Magento-Projekten mittel- und langfristig erheblich steigen.
Auf die statische Code-Analyse möchte ich in diesem Artikel
nicht näher eingehen, da diese im Rahmen des Build- und
Deploymentprozesses separat abgehandelt werden kann,
und sie zum anderen zum Migrationszeitpunkt nur sehr
rudimentär seitens Magento implementiert war. Auch auf
die Performancetests wird nicht näher eingegangen, da
diese über JMeter umgesetzt und ebenfalls separat
aufgerufen werden müssen.
Mögliche Testverfahren
2TechDivision GmbH PHPUnit Tests mit Magento
Portierung der Testsuite
Aufbauend auf unserem Build- und Deploymentprozess, bei
dem der Entwickler die Möglichkeit hat, über das
eingesetzte Buildtool, in unserem Fall ANT [3], jederzeit
automatisiert eine neue Magento-Instanz zu erstellen, war,
neben einer spürbaren Steigerung der Qualität, eines der
Primärziele der Portierung, dass beim Erstellen einer neuen
Entwicklungsinstanz dem Entwickler die Tests umgehend
zur Verfügung stehen und diese somit nahtlos in alle
Entwicklungsprozesse integriert sind. Die Portierung erfolgte
in drei Schritten und begann im April 2012.
Schritt 1: Testsuite als Extension bereitstellen
Im ersten Schritt wurden die zum Portierungszeitpunkt
aktuellen Sourcen von Magento 2 aus dem GIT Repository
geclont. Anschließend wurde die Testsuite im Rahmen einer
eigenen Extension so aufgesetzt, dass sie zum einen in
jedem Magento-Shop ab Version CE 1.7.x/EE 1.12.x
installiert, und zum anderen über einen automatisierten
Prozess für jede zukünftige Magento-Version ein um die
Testsuite erweitertes Installationspaket erstellt und auf
einem Buildserver bereitgestellt werden kann.
Die Extension enthält somit, wie in Illustration 1 dargestellt,
neben der notwendigen Konfiguration und den Helper-
Klassen im app-Verzeichnis den Bootstrapper (1), die
Verzeichnisse dev (2), das aus den Magento-2-Sourcen
übernommen wurde, sowie die Verzeichnisse lib +
downloader (5 + 3).
Das lib-Verzeichnis enthält einige für Magento 2 spezifische
Klassen, die die Testsuite jedoch für die Initialisierung
benötigt. Im downloader-Verzeichnis befinden sich die von
früheren Magento-1-Versionen benötigten Dateien für den
Downloader. Dieser wird zwar mit aktuellen Magento-
Versionen nicht mehr ausgeliefert, jedoch für das
erfolgreiche Erstellen des Code-Coverage-Reports benötigt.
Magento referenziert hier in einigen Dateien immer noch
fälschlicherweise PEAR-Klassen (4), die für den Betrieb
eigentlich nicht mehr benötigt werden. Bei der statischen
Code-Analyse mit PHPUnit tritt jedoch ein Fatal Error auf,
falls diese Klassen nicht im downloader-Verzeichnis
gefunden werden können. Optional könnte auch über die
Whitelist in der phpunit.xml.dist auf die Prüfung der
entsprechenden Sourcen durch PHPUnit beim Erstellen des
CodeCoverage Reports verzichtet werden.
Schritt 2: Anpassen der Testsuite an Magento
Im zweiten Schritt musste die mit Magento 2 ausgelieferte
Testsuite an Magento angepasst werden. Zu Beginn der
Migration hatten wir Magento CE 1.6.x/EE 1.11.x als
Zielversion vorgegeben. Es stellte sich jedoch relativ schnell
heraus, dass hierbei für den Einsatz des Testframeworks
Anpassungen an den Magento-Core-Klassen notwendig
wären. Ab Version CE 1.7.x/EE 1.12.x wurden die
notwendigen Anpassungen bereits von Magento direkt im
Core vorgenommen, was Anpassungen für den Einsatz der
Testsuite überflüssig macht.
Illustration 1: Verzeichnisstruktur Testsuite
3TechDivision GmbH PHPUnit Tests mit Magento
Überarbeitung der Tests
Zu den notwendigen Anpassungen zählten die
Überarbeitung des Bootstrappings, auf das wir später noch
näher eingehen werden, sowie Anpassungen der
eigentlichen Tests, wobei Letzteres aufgrund von
Einschränken in Magento zu den wesentlich aufwändigeren
Arbeiten gehörte.
Aufgrund von Anpassungen der Architektur, hauptsächlich
hinsichtlich Design und Layout, konnten viele Tests aus
Magento 2 nicht 1:1 übernommen werden, da entweder
Verzeichnisse und Dateien schlichtweg nicht vorhanden
waren, Methoden sich geändert hatten, oder gänzlich neu
hinzugekommen waren.
Eine unschöne Einschränkung von Magento hat sich bereits
beim Überarbeiten der Tests gezeigt. So können die
Annotations zum Anlegen von Testdaten (siehe ) in Magento
2 entweder auf Klassen- oder Methodenebene angegeben
werden. Beim Einsatz mit Magento traten hierbei jedoch in
vielen Fällen Probleme hinsichtlich inkonsistenter Testdaten
auf, die wohl auf Anpassungen in Magento 2 im Bereich der
Datenbankschicht hindeuten. Die betroffenen Testfälle
musste bei der Migration entsprechend überarbeitet, also
die entsprechenden Annotationen auf Methodenebene
gesetzt oder gar deaktiviert werden.
Betroffene Testfälle, aktuell ca. 630, wurden nicht gelöscht,
sondern vielmehr geskippt und werden nach und nach
geprüft und überarbeitet. Weiterhin wurden zum Zeitpunkt
der Portierung 27 Testfälle durch Magento als incomplete
deklariert. Auch diese werden, falls sinnvoll, in künftigen
Versionen der Testsuite fertiggestellt.
Anpassen des Bootstrappings
Für das Ausführen der Unit- und der Integrationstest wird
die Testsuite über einen Bootstrapper initialisiert. Der
Bootstrapper wird, wie in Listing 1 dargestellt, in der
PHPUnit-Konfigurationsdatei phpunit.xml.dist registriert, er
initialisiert die Laufzeitumgebung zum Ausführen der
Testsuite.
01
…
50
<phpunit bootstrap="./framework/bootstrap.php">
...
</phpunit>
Listing 1: Konfiguration PHPUnit Bootstrapper
Im Fall der Unittests werden hier lediglich die Includepfade
gesetzt, der Autoloader initialisiert und das Verzeichnis zur
Speicherung von temporären Dateien geleert.
Für die Integrationstests ist hier wesentlich mehr Aufwand
notwendig, da eine Magento-Sandbox auf Basis der
aktuellen Shopkonfiguration, sowie eine Testdatenbank
erstellt werden muss. Außerdem erweitert Magento PHPUnit
um zusätzliche Profilingmöglichkeiten und einige Observer,
die das Schreiben von Tests für den Entwickler erheblich
vereinfachen.
So stehen über die durch die Testsuite zusätzliche
bereitgestellten Annotations
@magentoAppIsolation
@magentoDataFixture
@magentoConfigFixture
dem Entwickler Funktionen zum automatisierten Anlegen
von Test- und Konfigurationsdaten sowie zur Ausführung
eines einzelnen Tests in einer isolierten (zurückgesetzten)
Instanz zur Verfügung.
4TechDivision GmbH PHPUnit Tests mit Magento
Die Testsuite erzeugt vor dem Ausführen der Tests eine
Sandbox. Hierzu werden alle globalen sowie die in den
Extensions enthaltenen Konfigurationsdateien in ein
temporäres Sandbox-Verzeichnis unterhalb der jeweiligen
Testsuite kopiert. Auf Basis der dort erstellten
Verzeichnisstruktur wird der Shop während des
Bootstrappings initialisiert. Da für die Tests Anpassungen an
den Konfigurationsdateien notwendig sind, stellt dieses
Verfahren sicher, dass für die Ausführung der Tests keinerlei
Veränderungen am Shop vorgenommen und diese
vollkommen isoliert und ohne Nebeneffekte vom Livesystem
ausgeführt werden.
Local- vs. Distributiontesting
Während der Einführungsphase hat sich gezeigt, dass es
aus Zeitgründen in der Praxis nicht möglich ist, bei jedem
lokalen Build alle Tests laufen zu lassen. Auf einem gut
ausgestatteten Entwicklungsrechner dauert der Durchlauf
der gesamten Testsuite einschließlich des Code Coverage
Reports bereits über 15 Minuten. Hinzu kommen noch die
Tests der jeweilige Extension. Für die lokale Entwicklung und
für die Erstellung einer neuen Paketversion steht neben der
Standard-Konfigurationsdatei phpunit.xml.dist, die alle Tests
ausführt (Distributiontesting), noch eine Konfigurationsdatei
phpunit.xml.local zur Verfügung, die nur die Tests im
Namespace der aktuellen Extension ausführt (Localtesting).
Heißt die Extension z. B. TechDivision_GermanTax, so
werden beim Aufruf der Tests unter Verwendung der
Konfigurationsdatei phpunit.xml.local alle Tests unterhalb
des Verzeichnisses dev/tests/integration/testsuite/
TechDivision durchlaufen und der Code Coverage Report
ausschließlich für alle Dateien der jeweiligen Extension
erstellt, was, abhängig von der Anzahl der Tests, zu einer
erheblichen Zeiteinsparung führt.
Schritt 3: Integration in den Entwicklungsprozess
Mit die größte Herausforderung der Portierung war der dritte
und somit letzte Schritt: Die Integration in den
Entwicklungsprozess. Mit Magento 2 werden die Testsuite
und die Tests standardmäßig ausgeliefert. Die Sourcen von
Magento hingegen kommen natürlich ohne Testsuite. Um
eine möglichst nahtlose und einfache Integration zu
gewährleisten, wurden zur lokalen Entwicklung eingesetzte
Magento-Pakete um die Testsuite erweitert. So können die
Tests zum einen über ein ANT-Target jederzeit aus der
lokalen Entwicklungsumgebung heraus gestartet werden,
zum anderen kann beim Build noch vor dem Erstellen des
Pakets sichergestellt werden, dass das Paket erst dann
erstellt wird, wenn alle Tests fehlerfrei durchlaufen wurden.
Hierbei kann der Entwickler durch Aufruf der verschiedenen
ANT-Targets zu jedem Zeitpunkt entscheiden, welche
Testfälle, also Unit- und/oder Integrationstests, ausgeführt
werden sollen. Zusätzlich besteht die Möglichkeit, über Build
Properties zu definieren, ob nur die jeweiligen Tests der
aktuell zu entwickelnden Extension oder zusätzlich auch die
Core Tests ausgeführt werden sollen.
Für den Build- und Deployment Prozess können Tools wie
Phing oder, wie in unserem Fall, ANT verwendet werden.
Zum Ausführen der Test stehen die in Listing 2 aufgeführten
Targets zur Verfügung.
01
02
03
phpunit-run-all-tests
phpunit-run-unit-tests
phpunit-run-integration-tests
Listing 2: ANT Targets zur Ausführung der Unit Tests
Das ANT-Target phpunit-run-integration-tests startet, wie
der Name schon sagt, die Integrationtests der Testsuite. In
der aktuellen Version werden derzeit 1.950 Tests
ausgeführt, wobei davon, wie bereits zuvor beschreiben,
wegen Inkompatibilitäten mit Magento noch 628 geskippt
werden und 27 incomplete sind. Die aktuelle Testsuite mit
2.990 Assertions deckt ca. 11 % der Magento-Core-
Klassen ab, sprich noch knapp 90 % des Magento-
Quelltexts sind nicht durch Tests abgedeckt.
Diese Targets können entweder direkt aus der lokalen
Entwicklungsumgebung oder automatisch während des
Builds durch den CI Server ausgeführt werden. Über die
Build Properties (siehe Listing 3) kann konfiguriert werden,
ob und welche (Distribution oder Local) Tests während des
Builds ausgeführt werden sollen. Zusätzlich kann
konfiguriert werden, welche Datenbank für die Ausführung
der Integrationstest verwendet werden soll, standardmäßig
wird eine zusätzliche leere Datenbank erzeugt.
5TechDivision GmbH
Testen in der Sandbox
PHPUnit Tests mit Magento
Illustration 2: Integrationstests auf Kommandozeile starten
6TechDivision GmbH
Laufen die Tests ohne Fehler durch, wird das Paket erstellt
und automatisch im PEAR Channel hinterlegt.
Selbstverständlich muss nicht zwingend PEAR für das
Paketmanagement verwendet werden, PEAR hat sich
allerdings in den letzten Jahren in unserem Fall bewährt.
Aktuell wird ein Ersatz durch Composer geprüft.
Um sicherzustellen, dass jede Extension für sich selbst,
sowie im Zusammenspiel mit allen anderen Extensions im
Rahmen eines Projekts lauffähig ist, wird pro Extension und
zusätzlich pro Projekt ein eigener Job im CI Server angelegt.
Wird eine Änderung durch den Entwickler in das GIT
Repository der Extension gepusht, wird automatisch durch
den CI Server der Build gestartet, die extensionspezifische
Testsuite ausgeführt und nach erfolgreichem Durchlauf ein
neues PEAR Paket mit der aktuellsten Version gebaut und
auf dem Channel Server zur Verfügung gestellt. Vor dem
Release eines Projekts werden alle Extensions in der
aktuellsten Version installiert und alle Tests – Core und
Extension – ausgeführt. Erst, wenn alle Tests über ein
Projekt erfolgreich durchlaufen, wird das neue Release zum
Deployment freigegeben.
Über das Jenkins Frontend (Illustration 3) haben Scrum
Master und Product Owner bereits während des Sprints die
Möglichkeit, die verschiedene Metriken, sowie die Anzahl
der erstellten Unit- und Integrationstests im Auge zu
behalten. Nach Abschluss des Sprints gewährleisten die
Tests, dass auch bei der Weiterentwicklung der Extension
oder des Shops die Qualität einfach und effektiv
sichergestellt werden kann.
01
02
03
phpunit.tests.execute = false
phpunit.database = ${mysql.database}_tests
phpunit.testsuite = dist
Listing 3: Build Properties zur Konfiguration der ANT-Targets
Illustration 2 zeigt die Ausgabe der Kommandozeile nach
dem Durchlauf der Integrationstests der aktuellen Version
der Testsuite.
PHPUnit Tests mit Magento
Illustration 3: Jenkins Frontend
7TechDivision GmbH
PHPUnit bietet bereits standardmäßig über sogenannte Data Providers [4] die Möglichkeit, einen Test mit unterschiedlichen
Datenstrukturen auszuführen. Hierzu kann über die Annotation @dataProvider eine Methode deklariert werden, die ein Array
oder einen Iterator mit den zu testenden Daten zurückgibt. Die Signatur der zu testenden Methode muss dann analog Listing 4
abhängig von der Datenstruktur die entsprechenden Parameter enthalten.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
/**
* @dataProvider getHelperDataProvider
*/
public function testGetHelper($inputHelperName, $expectedClass) {
$this->assertInstanceOf($expectedClass, $this->_model->getHelper($inputHelperName));
}
/**
* Data provider to run test with several data sets.
*
* @return void
*/
public function getHelperDataProvier() {
return array(
'class name' => array('core/data', 'Mage_Core_Helper_Data'),
'module name' => array('core', 'Mage_Core_Helper_Data')
);
}
Listing 4: Data Provider per Annotation
Anlegen von Testdaten
PHPUnit Tests mit Magento
8TechDivision GmbH
Speziell für das Ausführen der Integrationstests sind jedoch
fast immer Testdaten notwendig, die sich nicht einfach über
eine CSV-Datei oder ein Array darstellen lassen. Wie bereits
zuvor erwähnt, stellt die Testsuite hierfür über die
zusätzlichen Annotations auf Methodenebene
@magentoDataFixture
@magentoConfigFixture
Funktionen zur Verfügung, mit denen die für jeweiligen Test
erforderlichen Daten bequem angelegt und nach dem Test
automatisch wieder gelöscht werden. Somit ist
sichergestellt, dass die Datenbank vor jedem Test in ihren
Ausgangszustand zurückversetzt wird. Um dies so effizient
wie möglich zu gestalten, werden die über die jeweilige
Annotation spezifizierten Daten im Rahmen einer
Transaktion angelegt, dann der Test ausgeführt und die
Transaktion mit einem Rollback zurückgesetzt. Die
Datenbank wird somit zu keinem Zeitpunkt verändert, da
tatsächlich nie ein Commit für die Transaktion erfolgt.
Für die Annotation @magentoDataFixture muss, wie in
Listing 5 gezeigt, ein relativer Pfad zur Datei ausgehend vom
Basisverzeichnis der jeweiligen Testsuite angegeben
werden, z. B.
01
02
03
04
…
20
/**
* @magentoDataFixture Mage/Catalog/_files/product_simple.php
*/
public function testSomething() {
…
}
Listing 5: Annotation zum Anlegen von Testdaten
Innerhalb dieser Skripte kann die Anlage von Testdaten, wie in Listing 6 dargestellt, analog der Implementierung innerhalb
eines Models vorgenommen werden.
01
02
03
04
…
50
$product = new Mage_Catalog_Model_Product();
$product->setTypeId(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE)
->setId(1)
->setAttributeSetId(4)
…
->save();
Listing 6: Skript zum Anlegen von Testdaten
PHPUnit Tests mit Magento
9TechDivision GmbH
Lokalisierungen
Ein weiteres Problem ergibt sich aufgrund der Lokalisierung von Projekten. Die von Magento erstellte Testsuite für Magento 2
geht, wie in Listing 7 gezeigt, davon aus, dass die Testdatenbank für die USA lokalisiert ist. So wird in diversen Tests auf fest
hinterlegte Werte wie z. B. auf Preise in USD geprüft.
1 $this->assertEquals('<span class="price">$10.00</span>', $this->_model->getFormatedPrice());
Listing 7: Fest hinterlegte Werte in Magento 2 Tests
Nachdem Extensions wie z. B. TechDivision_GermanTax über die Installations- und Datenskripte die Lokalisierung der
Datenbank entsprechend anpassen, schlagen diese Tests fehl. Um dieses Problem zu lösen, müssen, wie in Listing 8 gezeigt,
die fest hinterlegten Werte entsprechend der im jeweiligen Shop konfigurierten Locale lokalisiert und erst dann geprüft werden.
01
02
$formattedPrice = Mage::app()->getStore()->formatPrice(0.00, false);
$this->assertEquals('<span class="price">' . $formattedPrice . '</span>', $this->_model->getFormatedPrice());
Listing 8: Auf lokalisierte Werte testen
Beim Einsatz der Testsuite im täglichen Entwicklungsprozess
hat sich eine Vielzahl von Problemen gezeigt, die ohne deren
Einsatz nicht auffallen würden. Während der Überarbeitung
hat sich gezeigt, dass sich die Entwickler der Testsuite, auf
jeden Fall bis zum Zeitpunkt der Portierung, noch nicht mit
allen Aspekten des Testens auseinandergesetzt hatten.
Nachfolgend möchte ich auf die, aus meiner Sicht, größten
Probleme bei der Portierung etwas detaillierter eingehen.
Aufteilung von Installations- und Datenskripten
So werden z. B. häufig die Installations- und Datenskripte
nicht entsprechend den von Magento gemachten Vorgaben
– Installationskripte im Verzeichnis sql, Datenskripte im
Verzeichnis data – getrennt abgelegt. Erfolgt keine
Trennung, so kommt es, da Magento im ersten Schritt nur
die Tabellen anlegt und keine Daten einspielt, bei Erstellung
der Testdatenbank durch die Testsuite zu Fehlern. So treten
z. B. bei Installation einer Extension ohne diese Trennung,
bei der Verknüpfungen der Daten zur Steuertabelle angelegt
werden sollen, zwangsläufig CONSTRAINT-Probleme auf,
da die Steuerdaten zu diesem Zeitpunkt eben aufgrund der
Trennung noch nicht existieren.
Die Trennung in Installations- und Datenskripten alleine trägt
zwar an sich bereits zur Vermeidung von Problemen bei,
reicht jedoch noch nicht aus. Zusätzlich ist es zwingend
erforderlich, in der entsprechenden Konfigurationsdatei
unter app/etc/modules Abhängigkeiten zu anderen
Extensions, auch zu Core-Modulen, zu hinterlegen. Anhand
dieser Abhängigkeiten wird bei der Installation der
Testdatenbank durch die Testsuite die Reihenfolge, in der
die Installations- und Datenskripte ausgeführt werden,
festgelegt. Nur so kann sichergestellt werden, dass eine
benötigte Tabelle oder deren Daten vor dem Ausführen des
Installations- oder Datenskripts auch tatsächlich vorhanden
ist.
Probleme beim Einsatz der Testsuite
PHPUnit Tests mit Magento
10TechDivision GmbH
Integration von Drittanbieter-Extensions
DER FOLGENDE SATZ IST AUCH KAPUTT, DAS MIT DEM
NEBEN FUNKTIONIERT SO NICHT Neben Abhängigkeiten von
Extensions hat sich im Laufe der Einführung gezeigt, dass
bei der Integration von Drittanbieter-Extensions die Magento
Core Tests in vielen Fällen fehlschlagen, da diese durch das
Überschreiben von Core-Klassen die ursprüngliche
Funktionalität verändern. Grundsätzlich lässt sich diese
Problem auf drei Arten lösen.
Die erste und beste Möglichkeit ist natürlich der gänzliche
Verzicht auf Rewrites, das Problem stellt sich somit gar nicht
erst.
Die zweite Möglichkeit, die immer dann verwendet werden
sollte, wenn die Verwendung eines Rewrites unumgänglich
ist, erlaubt dem Entwickler, die Extension per Konfiguration
über die Systemsteuerung zu aktivieren. Die Core Tests
schlagen somit nicht fehl, da die Extension zuerst über die
Annotation @magentoConfigFixture aktiviert werden muss.
Die dritte und letzte Möglichkeit erlaubt dem Entwickler,
einen Core Test durch die zusätzlich eingeführte Annotation
@magentoRewriteTestMethod zu ersetzten. So würde die
Methode des in Listing 9 gezeigten DocBlocks z. B. den
Core Test MageTest::testGetModel() ersetzen.
Abhängigkeiten von Extensions
Lokalisierung und Drittanbieter-Extensions stellen sicherlich
nicht zu unterschätzende Probleme dar, die jedoch relativ
leicht in den Griff zu bekommen sind. Als deutlich
komplizierteres Problem hat sich die Abhängigkeit von
Extensions beim Ausführen der Testsuite gezeigt.
Abhängigkeiten zum Magento Core spielen natürlich nur
eine untergeordnete Rolle (siehe ). Hat eine Extension jedoch
eine oder gar mehrere Abhängigkeit zu anderen oder
Drittanbieter-Extensions, so müssen beim Aufruf der
Testsuite diese ebenfalls vorhanden sein. Magento hat zwar
einen Mechanismus, einer Extension mitzuteilen, dass diese
von einer oder mehreren anderen abhängig ist, allerdings
werden bei der Installation abhängige Extensions nicht
automatisch mitinstalliert. Die Lösung dieses Problems ist in
diesem Fall abhängig vom eingesetzten Buildtool und vom
Paketmanagement, in unserem Fall also ANT und PEAR [5].
Für jedes PEAR-Paket lassen sich Abhängigkeiten
definieren, die bei der Installation sicherstellen, dass
benötigte Pakete auf jeden Fall vorhanden sind.
Beim Aufruf eines der ANT Targets (siehe ) zum Ausführen
der Testsuite wird, falls nicht bereits vorhanden,
automatisiert eine neue Magento-Instanz angelegt und ein
für jede Instanz separater PEAR Channel initialisiert.
Anschließend wird lokal ein PEAR-Paket aus der aktuellsten
Version der Sourcen erzeugt und über den zuvor
initialisierten PEAR Channel installiert. Benötigt das Paket
andere Pakete, so werden diese über die im PEAR-Paket
definierten Abhängigkeiten ebenfalls mitinstalliert. Somit
wird vor dem Aufruf der Testsuite eine konsistente
Testumgebung aufgebaut, die sicherstellt, dass alle zur
Ausführung der Tests benötigten Sourcen in der Testinstanz
vorhanden sind.
Vielleicht haben Sie sich zuvor gefragt, warum wir auch
Drittanbieter-Extensions im Rahmen von Projekten in
unseren Build- und Deploymentprozess integrieren. Die
Antwort darauf lautet, dass in vielen Projekten aus Effizienz-
und Konstengründen Drittanbieter-Extensions verwendet
werden, deren Funktionalität jedoch fast immer erweitert
werden muss. In den meisten Fällen wird hierzu, eine
weitere, abhängige Extension implementiert, um bei einem
Update der Extension Probleme zu vermeiden. Wie zuvor
beschrieben, ist es für den Einsatz der Testsuite notwendig,
die Drittanbieter-Extension ebenfalls zu installieren, genau
das lässt sich jedoch nur erreichen, wenn diese auch in den
eigenen Build- und Deploymentprozess integriert ist.
01
02
03
04
...
20
/**
* @magentoRewriteTestMethod MageTest::testGetModel()
*/
public function testGetModel() {
...
}
Listing 9: Ersetzen eines Core Tests
PHPUnit Tests mit Magento
11TechDivision GmbH
Links & Literatur
[1] https://wiki.magento.com/display/MAGE2DOC/Magento+Automated+Testing+Guide
[2] http://www.phpunit.de
[3] http://ant.apache.org
[4] http://www.phpunit.de/manual/3.6/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers
[5] http://pear.php.net
[6] http://www.github.com/techdivision/TechDivision_MagentoUnitTesting
Trotz der aktuell noch relativ geringen Testabdeckung, hat
bereits die Einführung der Testsuite zu einer erheblichen
Verbesserung der Qualität beigetragen. So konnten schon
während der Migration zahlreiche im herkömmlichen Betrieb
nicht sichtbare Probleme erkannt und beseitigt werden.
Durch die Einführung und die tägliche Arbeit mit der
Testsuite und die Umstellung auf SCRUM wurden die
Entwickler fast über Nacht zur Änderung ihrer Arbeitsweise
hin zu TDD gezwungen. Hierdurch entstanden zwar im
ersten Schritt zusätzliche Aufwände in Form von
Einarbeitung, Workshops und dem Schreiben von Tests,
jedoch zeigt sich bereits nach kurzer Zeit, dass die Qualität
und damit auch die Kundenzufriedenheit proportional zu den
Aufwänden steigt.
Der aktuelle Stand der Testsuite kann über das Github
Repository [6] der TechDivision GmbH heruntergeladen und
kostenfrei in eigenen Projekte eingesetzt werden. Da aus
Kompatibilitätsgründen derzeit noch zahlreiche Tests
deaktiviert wurden, freuen wir uns natürlich über
Unterstützung aus der Community, um alle sinnvollen Tests
aus Magento 2 zu portieren und eine möglichst große
Testabdeckung zu erreichen.
Fazit
Über uns:
TechDivision ist ein etablierter E-Commerce Solution Partner und unterstützt seit vielen Jahren nationale und
internationale Kunden in der integrierten Planung, Design und Implementierung von komplexen E-Commerce-
Lösungen. Als Magento Gold Partner von Anfang an, gehört TechDivision zu den führenden Magento Solution Partner
in Europa. Mittelgroße Kunden und internationale Unternehmen wie WMF oder Ritter-Sport, vertrauen in die
Kompetenz und Erfahrung von TechDivision.
Derzeit hat TechDivision zwei Standorte in Rosenheim / Kolbermoor und München.
Weitere Informationen über TechDivision: www.techdivision.com
TechDivision GmbH
Spinnereiinsel 3a
83059 Kolbermoor
Telefon +49 8031 2210 55 - 0
Telefax +49 8031 2210 55 - 22
Redaktionell Verantwortlicher:
Josef Willkommer
E-Mail: info@techdivision.com
www.techdivision.com
PHPUnit Tests mit Magento

Weitere ähnliche Inhalte

Mehr von TechDivision GmbH

Warum ein traditioneller Ausschreibungsprozess (RFP) nicht mehr zeitgemäß ist.
Warum ein traditioneller Ausschreibungsprozess (RFP) nicht mehr zeitgemäß ist.Warum ein traditioneller Ausschreibungsprozess (RFP) nicht mehr zeitgemäß ist.
Warum ein traditioneller Ausschreibungsprozess (RFP) nicht mehr zeitgemäß ist.TechDivision GmbH
 
Alles Wichtige zu Scrum in 4 Minuten
Alles Wichtige zu Scrum in 4 MinutenAlles Wichtige zu Scrum in 4 Minuten
Alles Wichtige zu Scrum in 4 MinutenTechDivision GmbH
 
TechDivision Daten & Fakten 2019
TechDivision Daten & Fakten 2019TechDivision Daten & Fakten 2019
TechDivision Daten & Fakten 2019TechDivision GmbH
 
Ausgabe 04/2019 des eStrategy-Magazins
Ausgabe 04/2019 des eStrategy-MagazinsAusgabe 04/2019 des eStrategy-Magazins
Ausgabe 04/2019 des eStrategy-MagazinsTechDivision GmbH
 
eStrategy-Magazin - Ausgabe #2/2019
eStrategy-Magazin - Ausgabe #2/2019eStrategy-Magazin - Ausgabe #2/2019
eStrategy-Magazin - Ausgabe #2/2019TechDivision GmbH
 
Meet Magento Germany 2019 - Agenda
Meet Magento Germany 2019 - AgendaMeet Magento Germany 2019 - Agenda
Meet Magento Germany 2019 - AgendaTechDivision GmbH
 
The Road of Migration - Hallhuber´s migration von Magento 1 to Magento 2
The Road of Migration - Hallhuber´s migration von Magento 1 to Magento 2The Road of Migration - Hallhuber´s migration von Magento 1 to Magento 2
The Road of Migration - Hallhuber´s migration von Magento 1 to Magento 2TechDivision GmbH
 
B2B eCommerce is far more than the existing selling over the Web
B2B eCommerce is far more than the existing selling over the WebB2B eCommerce is far more than the existing selling over the Web
B2B eCommerce is far more than the existing selling over the WebTechDivision GmbH
 
The real seamless commerce experience - Imagine Conference 2018
The real seamless commerce experience - Imagine Conference 2018The real seamless commerce experience - Imagine Conference 2018
The real seamless commerce experience - Imagine Conference 2018TechDivision GmbH
 
HALLHUBER shoprelaunch based on Magento 2
HALLHUBER shoprelaunch based on Magento 2HALLHUBER shoprelaunch based on Magento 2
HALLHUBER shoprelaunch based on Magento 2TechDivision GmbH
 
Magento 2 B2B Shop-Portal für die Julius Zorn GmbH
Magento 2 B2B Shop-Portal für die Julius Zorn GmbHMagento 2 B2B Shop-Portal für die Julius Zorn GmbH
Magento 2 B2B Shop-Portal für die Julius Zorn GmbHTechDivision GmbH
 
Magento Order Management (MOM)
Magento Order Management (MOM)Magento Order Management (MOM)
Magento Order Management (MOM)TechDivision GmbH
 
Neue Schritte zum Schutz der Privatsphäre - Die DSGVO und Magento
Neue Schritte zum Schutz der Privatsphäre - Die DSGVO und MagentoNeue Schritte zum Schutz der Privatsphäre - Die DSGVO und Magento
Neue Schritte zum Schutz der Privatsphäre - Die DSGVO und MagentoTechDivision GmbH
 
TechDivision Kennzahlen 2017
TechDivision Kennzahlen 2017TechDivision Kennzahlen 2017
TechDivision Kennzahlen 2017TechDivision GmbH
 
eStrategy-Magazin - Ausgabe 04/2017 (Leseprobe)
eStrategy-Magazin - Ausgabe 04/2017 (Leseprobe)eStrategy-Magazin - Ausgabe 04/2017 (Leseprobe)
eStrategy-Magazin - Ausgabe 04/2017 (Leseprobe)TechDivision GmbH
 
Magento Commerce Cloud Edition
Magento Commerce Cloud EditionMagento Commerce Cloud Edition
Magento Commerce Cloud EditionTechDivision GmbH
 
WHITEPAPER: AUS E-COMMERCE WIRD COMMERCE – OMNICHANNEL & CO.
WHITEPAPER: AUS E-COMMERCE WIRD COMMERCE – OMNICHANNEL & CO.WHITEPAPER: AUS E-COMMERCE WIRD COMMERCE – OMNICHANNEL & CO.
WHITEPAPER: AUS E-COMMERCE WIRD COMMERCE – OMNICHANNEL & CO.TechDivision GmbH
 
Kann man im Web wirklich alles (ver)kaufen? - Wir analysieren den Matratzen-H...
Kann man im Web wirklich alles (ver)kaufen? - Wir analysieren den Matratzen-H...Kann man im Web wirklich alles (ver)kaufen? - Wir analysieren den Matratzen-H...
Kann man im Web wirklich alles (ver)kaufen? - Wir analysieren den Matratzen-H...TechDivision GmbH
 
Magento Order Management (MOM)
Magento Order Management (MOM) Magento Order Management (MOM)
Magento Order Management (MOM) TechDivision GmbH
 
Führende B2B-Shopsoftware für den Mittelstand
Führende B2B-Shopsoftware für den MittelstandFührende B2B-Shopsoftware für den Mittelstand
Führende B2B-Shopsoftware für den MittelstandTechDivision GmbH
 

Mehr von TechDivision GmbH (20)

Warum ein traditioneller Ausschreibungsprozess (RFP) nicht mehr zeitgemäß ist.
Warum ein traditioneller Ausschreibungsprozess (RFP) nicht mehr zeitgemäß ist.Warum ein traditioneller Ausschreibungsprozess (RFP) nicht mehr zeitgemäß ist.
Warum ein traditioneller Ausschreibungsprozess (RFP) nicht mehr zeitgemäß ist.
 
Alles Wichtige zu Scrum in 4 Minuten
Alles Wichtige zu Scrum in 4 MinutenAlles Wichtige zu Scrum in 4 Minuten
Alles Wichtige zu Scrum in 4 Minuten
 
TechDivision Daten & Fakten 2019
TechDivision Daten & Fakten 2019TechDivision Daten & Fakten 2019
TechDivision Daten & Fakten 2019
 
Ausgabe 04/2019 des eStrategy-Magazins
Ausgabe 04/2019 des eStrategy-MagazinsAusgabe 04/2019 des eStrategy-Magazins
Ausgabe 04/2019 des eStrategy-Magazins
 
eStrategy-Magazin - Ausgabe #2/2019
eStrategy-Magazin - Ausgabe #2/2019eStrategy-Magazin - Ausgabe #2/2019
eStrategy-Magazin - Ausgabe #2/2019
 
Meet Magento Germany 2019 - Agenda
Meet Magento Germany 2019 - AgendaMeet Magento Germany 2019 - Agenda
Meet Magento Germany 2019 - Agenda
 
The Road of Migration - Hallhuber´s migration von Magento 1 to Magento 2
The Road of Migration - Hallhuber´s migration von Magento 1 to Magento 2The Road of Migration - Hallhuber´s migration von Magento 1 to Magento 2
The Road of Migration - Hallhuber´s migration von Magento 1 to Magento 2
 
B2B eCommerce is far more than the existing selling over the Web
B2B eCommerce is far more than the existing selling over the WebB2B eCommerce is far more than the existing selling over the Web
B2B eCommerce is far more than the existing selling over the Web
 
The real seamless commerce experience - Imagine Conference 2018
The real seamless commerce experience - Imagine Conference 2018The real seamless commerce experience - Imagine Conference 2018
The real seamless commerce experience - Imagine Conference 2018
 
HALLHUBER shoprelaunch based on Magento 2
HALLHUBER shoprelaunch based on Magento 2HALLHUBER shoprelaunch based on Magento 2
HALLHUBER shoprelaunch based on Magento 2
 
Magento 2 B2B Shop-Portal für die Julius Zorn GmbH
Magento 2 B2B Shop-Portal für die Julius Zorn GmbHMagento 2 B2B Shop-Portal für die Julius Zorn GmbH
Magento 2 B2B Shop-Portal für die Julius Zorn GmbH
 
Magento Order Management (MOM)
Magento Order Management (MOM)Magento Order Management (MOM)
Magento Order Management (MOM)
 
Neue Schritte zum Schutz der Privatsphäre - Die DSGVO und Magento
Neue Schritte zum Schutz der Privatsphäre - Die DSGVO und MagentoNeue Schritte zum Schutz der Privatsphäre - Die DSGVO und Magento
Neue Schritte zum Schutz der Privatsphäre - Die DSGVO und Magento
 
TechDivision Kennzahlen 2017
TechDivision Kennzahlen 2017TechDivision Kennzahlen 2017
TechDivision Kennzahlen 2017
 
eStrategy-Magazin - Ausgabe 04/2017 (Leseprobe)
eStrategy-Magazin - Ausgabe 04/2017 (Leseprobe)eStrategy-Magazin - Ausgabe 04/2017 (Leseprobe)
eStrategy-Magazin - Ausgabe 04/2017 (Leseprobe)
 
Magento Commerce Cloud Edition
Magento Commerce Cloud EditionMagento Commerce Cloud Edition
Magento Commerce Cloud Edition
 
WHITEPAPER: AUS E-COMMERCE WIRD COMMERCE – OMNICHANNEL & CO.
WHITEPAPER: AUS E-COMMERCE WIRD COMMERCE – OMNICHANNEL & CO.WHITEPAPER: AUS E-COMMERCE WIRD COMMERCE – OMNICHANNEL & CO.
WHITEPAPER: AUS E-COMMERCE WIRD COMMERCE – OMNICHANNEL & CO.
 
Kann man im Web wirklich alles (ver)kaufen? - Wir analysieren den Matratzen-H...
Kann man im Web wirklich alles (ver)kaufen? - Wir analysieren den Matratzen-H...Kann man im Web wirklich alles (ver)kaufen? - Wir analysieren den Matratzen-H...
Kann man im Web wirklich alles (ver)kaufen? - Wir analysieren den Matratzen-H...
 
Magento Order Management (MOM)
Magento Order Management (MOM) Magento Order Management (MOM)
Magento Order Management (MOM)
 
Führende B2B-Shopsoftware für den Mittelstand
Führende B2B-Shopsoftware für den MittelstandFührende B2B-Shopsoftware für den Mittelstand
Führende B2B-Shopsoftware für den Mittelstand
 

PHP Unit Tests mit Magento

  • 1. PHPUnit Tests mit Magento Ist der Einsatz der Magento 2 Testsuite in Magento möglich? Und wie läuft die Portierung? Index: Mögliche Testverfahren Portierung der Testsuite Anlegen von Testdaten Probleme beim Einsatz der Testsuite Fazit www.techdivision.com 1TechDivision GmbH PHPUnit Tests mit Magento
  • 2. Magento stellt seinen Entwicklungspartnern künftig die Testsuite und den Magento Automated Testing Guide [1] zur Verfügung. Eine der größten Schwächen von Magento, wenn man im Vergleich zu anderen Shopsystemen überhaupt von Schwächen sprechen kann, besteht sicherlich im Fehlen einer PHPUnit-Testsuite analog der, die mit Magento 2 eingeführt wird. Da seitens Magento momentan kein finaler Fertigstellungstermin für Magento 2 genannt wurde, wird Magento sicherlich noch länger als ursprünglich erwartet für Projekte zum Einsatz kommen. Anscheinend wird dem auch seitens Magento Rechnung getragen, da sich seit Version CE 1.7.x sowie EE 1.12.x auch hinsichtlich der Testbarkeit mit PHPUnit einiges getan hat. Jeder Entwickler, der mit Magento arbeitet, vermisst sicherlich schmerzlich eine Testsuite, die die Basisfunktionalität von Magento mit Unit- und Integrationsstest automatisiert testbar macht. Zusätzlich sollen natürlich auch die eigenen Entwicklungen für sich sowie in Abhängigkeit der Basisfunktionalität testbar sein. Sieht man sich die Testsuite von Magento 2 etwas detaillierter an, ist gut erkennbar, in welche Richtung Magento hier künftig gehen wird. Nachdem die Qualität für die Solution Partner als eines der zentralen Kriterien in die Bewertung des Partners mit einfließt, stellt Magento seinen Entwicklungspartnern künftig mit der Testsuite und dem Magento Automated Testing Guide [1] die Tools für die notwendige Verbesserung der Qualität, und somit auch der Partnerbewertung durch Magento, zur Verfügung. Dieser Artikel beschreibt die notwendigen Schritte zur Migration der Testsuite von Magento 2 auf Magento und zeigt anhand von Beispielen diverse Einsatzmöglichkeiten sowie die mögliche Integration in einen Build- und Deploymentprozess. von Tim Wagner Die Testsuite bringt Tests für die gängigsten vier Testverfahren mit. So werden Unit-, Integrations- und Performancetests ausgeliefert. Zusätzlich enthält die Suite Tests für die statische Code-Analyse. Bis auf die Performance Tests bauen alle Tests auf PHPUnit [2] von Sebastian Bergmann auf. Dieser Artikel beschäftigt sich hauptsächlich mit den Unit- und den Integrationstests, da diese für die meisten Entwickler die größte Bedeutung haben. Durch die Integration dieser beiden Testverfahren wird die Qualität und somit die auch Wartbarkeit von Magento-Projekten mittel- und langfristig erheblich steigen. Auf die statische Code-Analyse möchte ich in diesem Artikel nicht näher eingehen, da diese im Rahmen des Build- und Deploymentprozesses separat abgehandelt werden kann, und sie zum anderen zum Migrationszeitpunkt nur sehr rudimentär seitens Magento implementiert war. Auch auf die Performancetests wird nicht näher eingegangen, da diese über JMeter umgesetzt und ebenfalls separat aufgerufen werden müssen. Mögliche Testverfahren 2TechDivision GmbH PHPUnit Tests mit Magento
  • 3. Portierung der Testsuite Aufbauend auf unserem Build- und Deploymentprozess, bei dem der Entwickler die Möglichkeit hat, über das eingesetzte Buildtool, in unserem Fall ANT [3], jederzeit automatisiert eine neue Magento-Instanz zu erstellen, war, neben einer spürbaren Steigerung der Qualität, eines der Primärziele der Portierung, dass beim Erstellen einer neuen Entwicklungsinstanz dem Entwickler die Tests umgehend zur Verfügung stehen und diese somit nahtlos in alle Entwicklungsprozesse integriert sind. Die Portierung erfolgte in drei Schritten und begann im April 2012. Schritt 1: Testsuite als Extension bereitstellen Im ersten Schritt wurden die zum Portierungszeitpunkt aktuellen Sourcen von Magento 2 aus dem GIT Repository geclont. Anschließend wurde die Testsuite im Rahmen einer eigenen Extension so aufgesetzt, dass sie zum einen in jedem Magento-Shop ab Version CE 1.7.x/EE 1.12.x installiert, und zum anderen über einen automatisierten Prozess für jede zukünftige Magento-Version ein um die Testsuite erweitertes Installationspaket erstellt und auf einem Buildserver bereitgestellt werden kann. Die Extension enthält somit, wie in Illustration 1 dargestellt, neben der notwendigen Konfiguration und den Helper- Klassen im app-Verzeichnis den Bootstrapper (1), die Verzeichnisse dev (2), das aus den Magento-2-Sourcen übernommen wurde, sowie die Verzeichnisse lib + downloader (5 + 3). Das lib-Verzeichnis enthält einige für Magento 2 spezifische Klassen, die die Testsuite jedoch für die Initialisierung benötigt. Im downloader-Verzeichnis befinden sich die von früheren Magento-1-Versionen benötigten Dateien für den Downloader. Dieser wird zwar mit aktuellen Magento- Versionen nicht mehr ausgeliefert, jedoch für das erfolgreiche Erstellen des Code-Coverage-Reports benötigt. Magento referenziert hier in einigen Dateien immer noch fälschlicherweise PEAR-Klassen (4), die für den Betrieb eigentlich nicht mehr benötigt werden. Bei der statischen Code-Analyse mit PHPUnit tritt jedoch ein Fatal Error auf, falls diese Klassen nicht im downloader-Verzeichnis gefunden werden können. Optional könnte auch über die Whitelist in der phpunit.xml.dist auf die Prüfung der entsprechenden Sourcen durch PHPUnit beim Erstellen des CodeCoverage Reports verzichtet werden. Schritt 2: Anpassen der Testsuite an Magento Im zweiten Schritt musste die mit Magento 2 ausgelieferte Testsuite an Magento angepasst werden. Zu Beginn der Migration hatten wir Magento CE 1.6.x/EE 1.11.x als Zielversion vorgegeben. Es stellte sich jedoch relativ schnell heraus, dass hierbei für den Einsatz des Testframeworks Anpassungen an den Magento-Core-Klassen notwendig wären. Ab Version CE 1.7.x/EE 1.12.x wurden die notwendigen Anpassungen bereits von Magento direkt im Core vorgenommen, was Anpassungen für den Einsatz der Testsuite überflüssig macht. Illustration 1: Verzeichnisstruktur Testsuite 3TechDivision GmbH PHPUnit Tests mit Magento
  • 4. Überarbeitung der Tests Zu den notwendigen Anpassungen zählten die Überarbeitung des Bootstrappings, auf das wir später noch näher eingehen werden, sowie Anpassungen der eigentlichen Tests, wobei Letzteres aufgrund von Einschränken in Magento zu den wesentlich aufwändigeren Arbeiten gehörte. Aufgrund von Anpassungen der Architektur, hauptsächlich hinsichtlich Design und Layout, konnten viele Tests aus Magento 2 nicht 1:1 übernommen werden, da entweder Verzeichnisse und Dateien schlichtweg nicht vorhanden waren, Methoden sich geändert hatten, oder gänzlich neu hinzugekommen waren. Eine unschöne Einschränkung von Magento hat sich bereits beim Überarbeiten der Tests gezeigt. So können die Annotations zum Anlegen von Testdaten (siehe ) in Magento 2 entweder auf Klassen- oder Methodenebene angegeben werden. Beim Einsatz mit Magento traten hierbei jedoch in vielen Fällen Probleme hinsichtlich inkonsistenter Testdaten auf, die wohl auf Anpassungen in Magento 2 im Bereich der Datenbankschicht hindeuten. Die betroffenen Testfälle musste bei der Migration entsprechend überarbeitet, also die entsprechenden Annotationen auf Methodenebene gesetzt oder gar deaktiviert werden. Betroffene Testfälle, aktuell ca. 630, wurden nicht gelöscht, sondern vielmehr geskippt und werden nach und nach geprüft und überarbeitet. Weiterhin wurden zum Zeitpunkt der Portierung 27 Testfälle durch Magento als incomplete deklariert. Auch diese werden, falls sinnvoll, in künftigen Versionen der Testsuite fertiggestellt. Anpassen des Bootstrappings Für das Ausführen der Unit- und der Integrationstest wird die Testsuite über einen Bootstrapper initialisiert. Der Bootstrapper wird, wie in Listing 1 dargestellt, in der PHPUnit-Konfigurationsdatei phpunit.xml.dist registriert, er initialisiert die Laufzeitumgebung zum Ausführen der Testsuite. 01 … 50 <phpunit bootstrap="./framework/bootstrap.php"> ... </phpunit> Listing 1: Konfiguration PHPUnit Bootstrapper Im Fall der Unittests werden hier lediglich die Includepfade gesetzt, der Autoloader initialisiert und das Verzeichnis zur Speicherung von temporären Dateien geleert. Für die Integrationstests ist hier wesentlich mehr Aufwand notwendig, da eine Magento-Sandbox auf Basis der aktuellen Shopkonfiguration, sowie eine Testdatenbank erstellt werden muss. Außerdem erweitert Magento PHPUnit um zusätzliche Profilingmöglichkeiten und einige Observer, die das Schreiben von Tests für den Entwickler erheblich vereinfachen. So stehen über die durch die Testsuite zusätzliche bereitgestellten Annotations @magentoAppIsolation @magentoDataFixture @magentoConfigFixture dem Entwickler Funktionen zum automatisierten Anlegen von Test- und Konfigurationsdaten sowie zur Ausführung eines einzelnen Tests in einer isolierten (zurückgesetzten) Instanz zur Verfügung. 4TechDivision GmbH PHPUnit Tests mit Magento
  • 5. Die Testsuite erzeugt vor dem Ausführen der Tests eine Sandbox. Hierzu werden alle globalen sowie die in den Extensions enthaltenen Konfigurationsdateien in ein temporäres Sandbox-Verzeichnis unterhalb der jeweiligen Testsuite kopiert. Auf Basis der dort erstellten Verzeichnisstruktur wird der Shop während des Bootstrappings initialisiert. Da für die Tests Anpassungen an den Konfigurationsdateien notwendig sind, stellt dieses Verfahren sicher, dass für die Ausführung der Tests keinerlei Veränderungen am Shop vorgenommen und diese vollkommen isoliert und ohne Nebeneffekte vom Livesystem ausgeführt werden. Local- vs. Distributiontesting Während der Einführungsphase hat sich gezeigt, dass es aus Zeitgründen in der Praxis nicht möglich ist, bei jedem lokalen Build alle Tests laufen zu lassen. Auf einem gut ausgestatteten Entwicklungsrechner dauert der Durchlauf der gesamten Testsuite einschließlich des Code Coverage Reports bereits über 15 Minuten. Hinzu kommen noch die Tests der jeweilige Extension. Für die lokale Entwicklung und für die Erstellung einer neuen Paketversion steht neben der Standard-Konfigurationsdatei phpunit.xml.dist, die alle Tests ausführt (Distributiontesting), noch eine Konfigurationsdatei phpunit.xml.local zur Verfügung, die nur die Tests im Namespace der aktuellen Extension ausführt (Localtesting). Heißt die Extension z. B. TechDivision_GermanTax, so werden beim Aufruf der Tests unter Verwendung der Konfigurationsdatei phpunit.xml.local alle Tests unterhalb des Verzeichnisses dev/tests/integration/testsuite/ TechDivision durchlaufen und der Code Coverage Report ausschließlich für alle Dateien der jeweiligen Extension erstellt, was, abhängig von der Anzahl der Tests, zu einer erheblichen Zeiteinsparung führt. Schritt 3: Integration in den Entwicklungsprozess Mit die größte Herausforderung der Portierung war der dritte und somit letzte Schritt: Die Integration in den Entwicklungsprozess. Mit Magento 2 werden die Testsuite und die Tests standardmäßig ausgeliefert. Die Sourcen von Magento hingegen kommen natürlich ohne Testsuite. Um eine möglichst nahtlose und einfache Integration zu gewährleisten, wurden zur lokalen Entwicklung eingesetzte Magento-Pakete um die Testsuite erweitert. So können die Tests zum einen über ein ANT-Target jederzeit aus der lokalen Entwicklungsumgebung heraus gestartet werden, zum anderen kann beim Build noch vor dem Erstellen des Pakets sichergestellt werden, dass das Paket erst dann erstellt wird, wenn alle Tests fehlerfrei durchlaufen wurden. Hierbei kann der Entwickler durch Aufruf der verschiedenen ANT-Targets zu jedem Zeitpunkt entscheiden, welche Testfälle, also Unit- und/oder Integrationstests, ausgeführt werden sollen. Zusätzlich besteht die Möglichkeit, über Build Properties zu definieren, ob nur die jeweiligen Tests der aktuell zu entwickelnden Extension oder zusätzlich auch die Core Tests ausgeführt werden sollen. Für den Build- und Deployment Prozess können Tools wie Phing oder, wie in unserem Fall, ANT verwendet werden. Zum Ausführen der Test stehen die in Listing 2 aufgeführten Targets zur Verfügung. 01 02 03 phpunit-run-all-tests phpunit-run-unit-tests phpunit-run-integration-tests Listing 2: ANT Targets zur Ausführung der Unit Tests Das ANT-Target phpunit-run-integration-tests startet, wie der Name schon sagt, die Integrationtests der Testsuite. In der aktuellen Version werden derzeit 1.950 Tests ausgeführt, wobei davon, wie bereits zuvor beschreiben, wegen Inkompatibilitäten mit Magento noch 628 geskippt werden und 27 incomplete sind. Die aktuelle Testsuite mit 2.990 Assertions deckt ca. 11 % der Magento-Core- Klassen ab, sprich noch knapp 90 % des Magento- Quelltexts sind nicht durch Tests abgedeckt. Diese Targets können entweder direkt aus der lokalen Entwicklungsumgebung oder automatisch während des Builds durch den CI Server ausgeführt werden. Über die Build Properties (siehe Listing 3) kann konfiguriert werden, ob und welche (Distribution oder Local) Tests während des Builds ausgeführt werden sollen. Zusätzlich kann konfiguriert werden, welche Datenbank für die Ausführung der Integrationstest verwendet werden soll, standardmäßig wird eine zusätzliche leere Datenbank erzeugt. 5TechDivision GmbH Testen in der Sandbox PHPUnit Tests mit Magento
  • 6. Illustration 2: Integrationstests auf Kommandozeile starten 6TechDivision GmbH Laufen die Tests ohne Fehler durch, wird das Paket erstellt und automatisch im PEAR Channel hinterlegt. Selbstverständlich muss nicht zwingend PEAR für das Paketmanagement verwendet werden, PEAR hat sich allerdings in den letzten Jahren in unserem Fall bewährt. Aktuell wird ein Ersatz durch Composer geprüft. Um sicherzustellen, dass jede Extension für sich selbst, sowie im Zusammenspiel mit allen anderen Extensions im Rahmen eines Projekts lauffähig ist, wird pro Extension und zusätzlich pro Projekt ein eigener Job im CI Server angelegt. Wird eine Änderung durch den Entwickler in das GIT Repository der Extension gepusht, wird automatisch durch den CI Server der Build gestartet, die extensionspezifische Testsuite ausgeführt und nach erfolgreichem Durchlauf ein neues PEAR Paket mit der aktuellsten Version gebaut und auf dem Channel Server zur Verfügung gestellt. Vor dem Release eines Projekts werden alle Extensions in der aktuellsten Version installiert und alle Tests – Core und Extension – ausgeführt. Erst, wenn alle Tests über ein Projekt erfolgreich durchlaufen, wird das neue Release zum Deployment freigegeben. Über das Jenkins Frontend (Illustration 3) haben Scrum Master und Product Owner bereits während des Sprints die Möglichkeit, die verschiedene Metriken, sowie die Anzahl der erstellten Unit- und Integrationstests im Auge zu behalten. Nach Abschluss des Sprints gewährleisten die Tests, dass auch bei der Weiterentwicklung der Extension oder des Shops die Qualität einfach und effektiv sichergestellt werden kann. 01 02 03 phpunit.tests.execute = false phpunit.database = ${mysql.database}_tests phpunit.testsuite = dist Listing 3: Build Properties zur Konfiguration der ANT-Targets Illustration 2 zeigt die Ausgabe der Kommandozeile nach dem Durchlauf der Integrationstests der aktuellen Version der Testsuite. PHPUnit Tests mit Magento
  • 7. Illustration 3: Jenkins Frontend 7TechDivision GmbH PHPUnit bietet bereits standardmäßig über sogenannte Data Providers [4] die Möglichkeit, einen Test mit unterschiedlichen Datenstrukturen auszuführen. Hierzu kann über die Annotation @dataProvider eine Methode deklariert werden, die ein Array oder einen Iterator mit den zu testenden Daten zurückgibt. Die Signatur der zu testenden Methode muss dann analog Listing 4 abhängig von der Datenstruktur die entsprechenden Parameter enthalten. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 /** * @dataProvider getHelperDataProvider */ public function testGetHelper($inputHelperName, $expectedClass) { $this->assertInstanceOf($expectedClass, $this->_model->getHelper($inputHelperName)); } /** * Data provider to run test with several data sets. * * @return void */ public function getHelperDataProvier() { return array( 'class name' => array('core/data', 'Mage_Core_Helper_Data'), 'module name' => array('core', 'Mage_Core_Helper_Data') ); } Listing 4: Data Provider per Annotation Anlegen von Testdaten PHPUnit Tests mit Magento
  • 8. 8TechDivision GmbH Speziell für das Ausführen der Integrationstests sind jedoch fast immer Testdaten notwendig, die sich nicht einfach über eine CSV-Datei oder ein Array darstellen lassen. Wie bereits zuvor erwähnt, stellt die Testsuite hierfür über die zusätzlichen Annotations auf Methodenebene @magentoDataFixture @magentoConfigFixture Funktionen zur Verfügung, mit denen die für jeweiligen Test erforderlichen Daten bequem angelegt und nach dem Test automatisch wieder gelöscht werden. Somit ist sichergestellt, dass die Datenbank vor jedem Test in ihren Ausgangszustand zurückversetzt wird. Um dies so effizient wie möglich zu gestalten, werden die über die jeweilige Annotation spezifizierten Daten im Rahmen einer Transaktion angelegt, dann der Test ausgeführt und die Transaktion mit einem Rollback zurückgesetzt. Die Datenbank wird somit zu keinem Zeitpunkt verändert, da tatsächlich nie ein Commit für die Transaktion erfolgt. Für die Annotation @magentoDataFixture muss, wie in Listing 5 gezeigt, ein relativer Pfad zur Datei ausgehend vom Basisverzeichnis der jeweiligen Testsuite angegeben werden, z. B. 01 02 03 04 … 20 /** * @magentoDataFixture Mage/Catalog/_files/product_simple.php */ public function testSomething() { … } Listing 5: Annotation zum Anlegen von Testdaten Innerhalb dieser Skripte kann die Anlage von Testdaten, wie in Listing 6 dargestellt, analog der Implementierung innerhalb eines Models vorgenommen werden. 01 02 03 04 … 50 $product = new Mage_Catalog_Model_Product(); $product->setTypeId(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) ->setId(1) ->setAttributeSetId(4) … ->save(); Listing 6: Skript zum Anlegen von Testdaten PHPUnit Tests mit Magento
  • 9. 9TechDivision GmbH Lokalisierungen Ein weiteres Problem ergibt sich aufgrund der Lokalisierung von Projekten. Die von Magento erstellte Testsuite für Magento 2 geht, wie in Listing 7 gezeigt, davon aus, dass die Testdatenbank für die USA lokalisiert ist. So wird in diversen Tests auf fest hinterlegte Werte wie z. B. auf Preise in USD geprüft. 1 $this->assertEquals('<span class="price">$10.00</span>', $this->_model->getFormatedPrice()); Listing 7: Fest hinterlegte Werte in Magento 2 Tests Nachdem Extensions wie z. B. TechDivision_GermanTax über die Installations- und Datenskripte die Lokalisierung der Datenbank entsprechend anpassen, schlagen diese Tests fehl. Um dieses Problem zu lösen, müssen, wie in Listing 8 gezeigt, die fest hinterlegten Werte entsprechend der im jeweiligen Shop konfigurierten Locale lokalisiert und erst dann geprüft werden. 01 02 $formattedPrice = Mage::app()->getStore()->formatPrice(0.00, false); $this->assertEquals('<span class="price">' . $formattedPrice . '</span>', $this->_model->getFormatedPrice()); Listing 8: Auf lokalisierte Werte testen Beim Einsatz der Testsuite im täglichen Entwicklungsprozess hat sich eine Vielzahl von Problemen gezeigt, die ohne deren Einsatz nicht auffallen würden. Während der Überarbeitung hat sich gezeigt, dass sich die Entwickler der Testsuite, auf jeden Fall bis zum Zeitpunkt der Portierung, noch nicht mit allen Aspekten des Testens auseinandergesetzt hatten. Nachfolgend möchte ich auf die, aus meiner Sicht, größten Probleme bei der Portierung etwas detaillierter eingehen. Aufteilung von Installations- und Datenskripten So werden z. B. häufig die Installations- und Datenskripte nicht entsprechend den von Magento gemachten Vorgaben – Installationskripte im Verzeichnis sql, Datenskripte im Verzeichnis data – getrennt abgelegt. Erfolgt keine Trennung, so kommt es, da Magento im ersten Schritt nur die Tabellen anlegt und keine Daten einspielt, bei Erstellung der Testdatenbank durch die Testsuite zu Fehlern. So treten z. B. bei Installation einer Extension ohne diese Trennung, bei der Verknüpfungen der Daten zur Steuertabelle angelegt werden sollen, zwangsläufig CONSTRAINT-Probleme auf, da die Steuerdaten zu diesem Zeitpunkt eben aufgrund der Trennung noch nicht existieren. Die Trennung in Installations- und Datenskripten alleine trägt zwar an sich bereits zur Vermeidung von Problemen bei, reicht jedoch noch nicht aus. Zusätzlich ist es zwingend erforderlich, in der entsprechenden Konfigurationsdatei unter app/etc/modules Abhängigkeiten zu anderen Extensions, auch zu Core-Modulen, zu hinterlegen. Anhand dieser Abhängigkeiten wird bei der Installation der Testdatenbank durch die Testsuite die Reihenfolge, in der die Installations- und Datenskripte ausgeführt werden, festgelegt. Nur so kann sichergestellt werden, dass eine benötigte Tabelle oder deren Daten vor dem Ausführen des Installations- oder Datenskripts auch tatsächlich vorhanden ist. Probleme beim Einsatz der Testsuite PHPUnit Tests mit Magento
  • 10. 10TechDivision GmbH Integration von Drittanbieter-Extensions DER FOLGENDE SATZ IST AUCH KAPUTT, DAS MIT DEM NEBEN FUNKTIONIERT SO NICHT Neben Abhängigkeiten von Extensions hat sich im Laufe der Einführung gezeigt, dass bei der Integration von Drittanbieter-Extensions die Magento Core Tests in vielen Fällen fehlschlagen, da diese durch das Überschreiben von Core-Klassen die ursprüngliche Funktionalität verändern. Grundsätzlich lässt sich diese Problem auf drei Arten lösen. Die erste und beste Möglichkeit ist natürlich der gänzliche Verzicht auf Rewrites, das Problem stellt sich somit gar nicht erst. Die zweite Möglichkeit, die immer dann verwendet werden sollte, wenn die Verwendung eines Rewrites unumgänglich ist, erlaubt dem Entwickler, die Extension per Konfiguration über die Systemsteuerung zu aktivieren. Die Core Tests schlagen somit nicht fehl, da die Extension zuerst über die Annotation @magentoConfigFixture aktiviert werden muss. Die dritte und letzte Möglichkeit erlaubt dem Entwickler, einen Core Test durch die zusätzlich eingeführte Annotation @magentoRewriteTestMethod zu ersetzten. So würde die Methode des in Listing 9 gezeigten DocBlocks z. B. den Core Test MageTest::testGetModel() ersetzen. Abhängigkeiten von Extensions Lokalisierung und Drittanbieter-Extensions stellen sicherlich nicht zu unterschätzende Probleme dar, die jedoch relativ leicht in den Griff zu bekommen sind. Als deutlich komplizierteres Problem hat sich die Abhängigkeit von Extensions beim Ausführen der Testsuite gezeigt. Abhängigkeiten zum Magento Core spielen natürlich nur eine untergeordnete Rolle (siehe ). Hat eine Extension jedoch eine oder gar mehrere Abhängigkeit zu anderen oder Drittanbieter-Extensions, so müssen beim Aufruf der Testsuite diese ebenfalls vorhanden sein. Magento hat zwar einen Mechanismus, einer Extension mitzuteilen, dass diese von einer oder mehreren anderen abhängig ist, allerdings werden bei der Installation abhängige Extensions nicht automatisch mitinstalliert. Die Lösung dieses Problems ist in diesem Fall abhängig vom eingesetzten Buildtool und vom Paketmanagement, in unserem Fall also ANT und PEAR [5]. Für jedes PEAR-Paket lassen sich Abhängigkeiten definieren, die bei der Installation sicherstellen, dass benötigte Pakete auf jeden Fall vorhanden sind. Beim Aufruf eines der ANT Targets (siehe ) zum Ausführen der Testsuite wird, falls nicht bereits vorhanden, automatisiert eine neue Magento-Instanz angelegt und ein für jede Instanz separater PEAR Channel initialisiert. Anschließend wird lokal ein PEAR-Paket aus der aktuellsten Version der Sourcen erzeugt und über den zuvor initialisierten PEAR Channel installiert. Benötigt das Paket andere Pakete, so werden diese über die im PEAR-Paket definierten Abhängigkeiten ebenfalls mitinstalliert. Somit wird vor dem Aufruf der Testsuite eine konsistente Testumgebung aufgebaut, die sicherstellt, dass alle zur Ausführung der Tests benötigten Sourcen in der Testinstanz vorhanden sind. Vielleicht haben Sie sich zuvor gefragt, warum wir auch Drittanbieter-Extensions im Rahmen von Projekten in unseren Build- und Deploymentprozess integrieren. Die Antwort darauf lautet, dass in vielen Projekten aus Effizienz- und Konstengründen Drittanbieter-Extensions verwendet werden, deren Funktionalität jedoch fast immer erweitert werden muss. In den meisten Fällen wird hierzu, eine weitere, abhängige Extension implementiert, um bei einem Update der Extension Probleme zu vermeiden. Wie zuvor beschrieben, ist es für den Einsatz der Testsuite notwendig, die Drittanbieter-Extension ebenfalls zu installieren, genau das lässt sich jedoch nur erreichen, wenn diese auch in den eigenen Build- und Deploymentprozess integriert ist. 01 02 03 04 ... 20 /** * @magentoRewriteTestMethod MageTest::testGetModel() */ public function testGetModel() { ... } Listing 9: Ersetzen eines Core Tests PHPUnit Tests mit Magento
  • 11. 11TechDivision GmbH Links & Literatur [1] https://wiki.magento.com/display/MAGE2DOC/Magento+Automated+Testing+Guide [2] http://www.phpunit.de [3] http://ant.apache.org [4] http://www.phpunit.de/manual/3.6/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers [5] http://pear.php.net [6] http://www.github.com/techdivision/TechDivision_MagentoUnitTesting Trotz der aktuell noch relativ geringen Testabdeckung, hat bereits die Einführung der Testsuite zu einer erheblichen Verbesserung der Qualität beigetragen. So konnten schon während der Migration zahlreiche im herkömmlichen Betrieb nicht sichtbare Probleme erkannt und beseitigt werden. Durch die Einführung und die tägliche Arbeit mit der Testsuite und die Umstellung auf SCRUM wurden die Entwickler fast über Nacht zur Änderung ihrer Arbeitsweise hin zu TDD gezwungen. Hierdurch entstanden zwar im ersten Schritt zusätzliche Aufwände in Form von Einarbeitung, Workshops und dem Schreiben von Tests, jedoch zeigt sich bereits nach kurzer Zeit, dass die Qualität und damit auch die Kundenzufriedenheit proportional zu den Aufwänden steigt. Der aktuelle Stand der Testsuite kann über das Github Repository [6] der TechDivision GmbH heruntergeladen und kostenfrei in eigenen Projekte eingesetzt werden. Da aus Kompatibilitätsgründen derzeit noch zahlreiche Tests deaktiviert wurden, freuen wir uns natürlich über Unterstützung aus der Community, um alle sinnvollen Tests aus Magento 2 zu portieren und eine möglichst große Testabdeckung zu erreichen. Fazit Über uns: TechDivision ist ein etablierter E-Commerce Solution Partner und unterstützt seit vielen Jahren nationale und internationale Kunden in der integrierten Planung, Design und Implementierung von komplexen E-Commerce- Lösungen. Als Magento Gold Partner von Anfang an, gehört TechDivision zu den führenden Magento Solution Partner in Europa. Mittelgroße Kunden und internationale Unternehmen wie WMF oder Ritter-Sport, vertrauen in die Kompetenz und Erfahrung von TechDivision. Derzeit hat TechDivision zwei Standorte in Rosenheim / Kolbermoor und München. Weitere Informationen über TechDivision: www.techdivision.com TechDivision GmbH Spinnereiinsel 3a 83059 Kolbermoor Telefon +49 8031 2210 55 - 0 Telefax +49 8031 2210 55 - 22 Redaktionell Verantwortlicher: Josef Willkommer E-Mail: info@techdivision.com www.techdivision.com PHPUnit Tests mit Magento