Unit-Tests
Die Unit Tests befinden sich im Verzeichnis tests
. Um sie auszuführen kann man z.B.
folgende Kommandos verwenden.
$ cd tests
$ ../vendor/bin/phpunit . | tee testresult.txt
Mit “../vendor/bin/phpunit .
” wird die durch Composer installierte Version von PHPUnit
verwendet und sämtliche Tests ausgeführt. Durch “| tee testresult.txt
” werden die Ausgaben während des Tests
zusätzlich in die Datei testresult.txt
geschrieben.
Folgende Zeile würde nur die Tests für Opus_Document
ausführen.
$ ../vendor/bin/phpunit Opus/DocumentTest
Am Ende des Testdurchlaufs werden die Tests mit Fehlern aufgelistet. Mit der Option --debug
werden bereits während der Ausführung die Namen der Tests aufgelistet.
$ ../vendor/bin/phpunit --debug .
Die Unit-Tests lassen sich auch mit ant
ausführen. Im Root-Verzeichnis von OPUS 4 liegt
die Datei build.xml
, die verschiedene Targets für die Ausführung definiert. Mit folgendem
Kommando lassen sich alle Tests ausführen.
$ ant phpunit-fast
Dabei werden die Zwischenergebnisse immer erst am Ende einer Zeile ausgegeben. Ant wird auch vom CI-System für die Ausführung der Tests verwendet.
Testdaten
Die Tests der OPUS 4 Application setzen Testdaten voraus. Nach einem Durchlauf der Tests sind diese Daten unter Umständen nicht mehr in ihrem ursprünglichen Zustand. Für einen sauberen Test müssen daher die Testdaten vorher zurückgesetzt werden. Aufgrund des Zeitaufwands passiert dies nicht automatisch vor jedem Test.
Mit folgendem Kommando werden die Datenbank und die Volltextdateien zurückgesetzt und eine neue Indizierung durchgeführt.
$ ant reset-testdata
Um die ausführlichen Information zum Kopieren der Testdateien zu sehen, kann -Dverbose=1
verwendet werden.
$ ant reset-testdata -Dverbose=1
Manipulation der Zend_Config
innerhalb von Tests
Bei der Manipulation oder dem Hinzufügen von Werten in der Zend_Config
sollte
darauf geachtet werden, dass beim Setzen von Booleschen Werten ausschließlich
die Konstanten CONFIG_VALUE_TRUE
bzw. CONFIG_VALUE_FALSE
aus der Klasse
ControllerTestCase
verwendet werden. Die Konstanten repräsentieren die Werte,
die Zend beim Auslesen von booleschen Werten aus ini
-Dateien setzt. In ZF1
ist das '1'
für true
und ''
(Leerstring) für false
.
Ein Zurücksetzen von Änderungen in Zend_Config
am Ende eines Tests ist nicht
erforderlich. Die Zend_Config
wird bei jedem Test neu geladen, so dass zuvor
geänderte oder neu hinzugefügte Werte nicht mehr vorhanden sind.
XHTML/XML-Schema-Dateien lokal cachen
Während der Tests werden die Ausgaben von OPUS 4 unter anderem auf korrektes XHTML geprüft. Für das XHTML-Schema wird normalerweise auf Ressourcen auf den Servern von www.w3.org zugegriffen. Der Zugriff auf diese Server ist gedrosselt, so dass Anfragen manchmal sehr lange dauern. Manche Unit-Tests benötigen dadurch Minuten anstelle von Sekunden. Um die Tests zu beschleunigen kann die Verwendung lokaler Kopien der Schema-Dateien konfiguriert werden.
Die notwendigen XML-Schema-Dateien befinden sich in folgendem Verzeichnis:
tests/resources
und sind in eine XML-Katalog-Datei aufgelistet:
tests/resources/opus4-catalog.xml
Damit der XML-Katalog verwendet wird muss die Environmentvariable XML_CATALOG_FILES
gesetzt werden, z.B. in der .bashrc
Datei.
export XML_CATALOG_FILES=~/projects/opus4/tests/resources/opus4-catalog.xml
Sollen die Unit-Tests in einer IDE ausgeführt werden, sollte die Variable auch dort für die Ausführung von PHPUnit konfiguriert werden. Wie das genau passiert ist für jede IDE etwas anders.
In IntelliJ IDEA kann die Konfiguration der Variable unter Run->Edit Configurations...
für die PHPUnit-Default-Einstellungen erfolgen.
Code-Coverage
Die Code-Coverage gibt an wieviel vom Code durch die Tests abgedeckt wird. Insbesondere
die Controller-Tests sind aber keine Unit Tests, sondern Integrationstest. Mindestens für
die Tests sollte die Coverage eingeschränkt werden. Dafür kann @covers
verwendet werden.
/**
* IndexControllerTest class for testing IndexController.
*
*
* @covers IndexController
*/
Dadurch wird nur die Tests erzeugte Coverage für den IndexController berücksichtigt und nicht für die Klassen, die bei der Ausführung evtl. auch noch berührt werden. Es gibt noch weitere Wege, um die Coverage einzuschränken und ein ehrlicheres Bild der Abdeckung zu bekommen. Für genauere Information bitte die PHPUnit Dokumentation hinzuziehen.
Performanz
Die Geschwindigkeit der Tests wird unter anderem durch den Speicherverbrauch beeinflusst. Leider ist es schwierig nach jedem Tests den Speicher wieder komplett aufzuräumen. Dadurch steigt der Speicherverbrauch mit jedem Test etwas an. Bei 3500+ Tests für die Application kommt dabei einiges zusammen und die Laufzeit verlängert sich beträchtlich. Um diesen Effekt abzumildern wurden einige Massnahmen getroffen.
Tests in Blöcken
Die Tests sind für Travis in Blöcke eingeteilt, die nach einander ausgeführt werden. Dadurch
reduziert sich der maximale Speicherverbrauch und Tests laufen schneller durch. Die Blöcke
sind als Testsuites in tests/phpunit.xml
definiert.
- library
- modules (ohne Admin-Modul)
- admin (nur Admin-Modul)
- security
- scripts
Selektives Laden der Ressourcen
Jede Testklasse sollte nur die Ressourcen laden die notwendig sind. Folgendes Beispiel sorgt dafür, dass die Datenbank und die Übersetzungen verfügbar sind. Insbesondere die Übersetzungen beeinflussen die Laufzeit von Tests beträchtlich.
protected $additionalResources = ['database', 'translation'];
Die verfügbaren Ressourcen entsprechen, den _initXXX
-Funktionen im Bootstrap von OPUS, also
in Application_Bootstrap
und Opus_Bootstrap_Base
. Die folgenden Ressourcen werden
automatisch geladen.
- configuration
- logging
Gibt man für $additionalResources
den Wert all
an wird der gesamte Bootstrap ausgeführt.
Mit folgender Option kann man dafür sorgen, dass die Konfiguration in einem Test manipulierbar ist.
protected $configModifiable = true;
Memory-Leak reduzieren
Bei den Tests wird das Übersetzungsobjekt, Application_Translate
, wiederverwendet.
Dadurch sinkt der Speicherverbrauch beträchtlich. Für den produktiven Betrieb hat das keine
Auswirkungen, da dort nach jedem Request, der Speicher wieder freigegeben wird.
Es gibt noch weitere Objekte durch die mit jedem Test der Speicherverbrauch steigt, unter
anderem vermutlich Zend_Acl
. Momentan haben wir den Verbrauch aber auf etwa 300 MB gesenkt
und die Laufzeit mit Travis beträgt etwa 27 Minuten. Das ist für den Augenblick gut genug.