Anzeige
Anzeige
Artikel
Artikel merken

Sauberer Code durch Unit Testing: Green Bar Feeling bei TYPO3-Extensions

Prinzipiell sind TYPO3-Extensions auch „nur“ PHP-Code, der sich deshalb durch Unit Testing überprüfen lässt. Und doch gibt es gewisse Unterschiede zwischen einer eigenständigen Applikation und einer Extension für das TYPO3-Framework. Dieser Artikel zeigt, wie man Extensions effektiv testet und dabei mit den richtigen Tools viel Aufwand spart.

6 Min. Lesezeit
Anzeige
Anzeige

Nach der allgemein gehaltenen Einleitung zu Unit Testing (separater Artikel in diesem Heft) liegt der Fokus dieses Artikels nun speziell auf Unit Testing im Zusammenhang mit TYPO3. Das Testen von Extensions birgt besondere Schwierigkeiten: Extensions sind meist ohne TYPO3 nicht lauffähig. Damit eine Extension getestet werden kann, muss das Testumfeld die Funktionen des TYPO3-Frameworks so drapieren, dass die zu testenden Klassen darauf zugreifen können. Dazu kann beispielsweise die Extension „tx_phpunit“ [1] verwendet werden.

PHPUnit als Extension

Anzeige
Anzeige

Ein erster Anlauf, PHPUnit mit einer brauchbaren Oberfläche in die Extension „tx_t3unit“ zu kapseln, scheiterte vor einiger Zeit am Umfang des Projekts. Im Jahr 2007 begann der Däne Kasper Ligaard mit der Arbeit an seiner „tx_phpunit“ getauften Extension. Dabei baute er die bestehende Extension von Robert Lemke weiter aus und passte die Struktur an die Version 3.x. von PHPUnit an. In den vergangenen Monaten erschienen die neuen Versionen zeitweise im Wochentakt.

Die Extension bietet ein Backend-Modul, in dem Tests aller installierten Extensions insgesamt, pro Extension oder einzeln ausgeführt werden können. Momentan ist dieser Umfang allerdings nur ein Zwischenstand: Kasper Ligaards längerfristiges Ziel ist es, das gesamte TYPO3-Framework testbar zu machen. Da sich die Ausweitung der Testumgebung aber bisher schwieriger gestaltet als erwartet, wurde zunächst die Testbarkeit von Extensions umgesetzt. In Zukunft soll es möglich sein, die Tests nicht nur „live“ im Browser auszuführen, sondern auch auf einem separaten Server. Der Weg führt in Richtung Continous Integration, nach Angaben des Entwicklers wird die Umsetzung aber noch auf sich warten lassen: Schwierigkeiten beim Testen von Extensions gebe es beispielsweise beim gesamten Frontend-Output, bei der TypoScript-Konfiguration und bei ausgehenden Mails. Die Frontend-Ausgabe kann bisher durch ein simuliertes Frontend getestet werden; TypoScript-Setup, ausgehende Mails und weitere Funktionen deckt das Testing-Framework in der Extension „tx_oelib“ ab.

Anzeige
Anzeige

Schritt für Schritt zur getesteten Extension

Um eine bestehende oder gerade neu angelegte Extension mit Unit Tests auszurüsten, sind nur wenige Schritte nötig. Obwohl hier die häufigsten Stolperfallen genannt werden, wird kein Entwickler um ein wenig „Trial & Error“ herumkommen.

Anzeige
Anzeige

Die zu testende Extension braucht ein Verzeichnis „tests“. Falls benötigt, kann darin auch gleich noch ein Unterverzeichnis „fixtures“ angelegt werden. Für jede zu überprüfende Klasse wird ein Test-Case als einzelne PHP-Datei in das erstellte „tests“-Verzeichnis gelegt. Diese Klassen werden später die einzelnen Test-Funktionen beinhalten.

Aufbau eines einfachen Test-Cases
class tx_extensionname_klassenname_testcase extends tx_phpunit_testcase {
protected function setUp() {
		// Für die Fixture – nur wenn benötigt.
	}
	protected function tearDown() {
		// Ebenfalls für die Fixture – nur wenn benötigt.
	}
	public function testSomeFunctionDoesSomething() {
		// Test Funktionalität
	}
	public function testSomeOtherFunctionDoesSomething() {
		// Test Funktionalität
	}
}

Listing 1

Bei diesem Grundgerüst ist darauf zu achten, dass die Klasse sich von „tx_phpunit_testcase“ ableitet. Als Testfunktionen werden ausschließlich die Funktionen erkannt, deren Funktionsname mit „test“ beginnt und die als „public“ markiert sind. Der Aufruf des Backend-Moduls PHPUnit lässt nun bereits die Auswahl und den Durchlauf des Test-Case zu. Das ist natürlich erst dann sinnvoll, wenn die oben gezeigten Testmethoden auf vorhandenen Code, wie beispielsweise eine bestehende Klasse, angewendet werden.

Anzeige
Anzeige

Noch ein Framework

Falls die zu testende Klasse ausschließlich statisch aufrufbare Funktionen zur Verfügung stellt, ist das Testen relativ einfach, da während der Testdurchführung weder Objekte instantiiert werden noch Datensätze aus einer Dantenbank beteiligt sind. Im Gegensatz dazu sind TYPO3-Extensions immer häufiger objektorientiert aufgebaut und greifen zum Großteil auf eine Datenbank zu.

Fixtures [2] bieten einen einfachen Weg, die benötigten Objekte zu instantiieren, und ein kleines Testing-Framework für die benötigten Dummy-Datensätze in der Datenbank erleichtert die Arbeit. Die Framework-Klasse ist in der Extension „tx_oelib“ zu finden und bietet unter anderem folgende Funktionalitäten:

  • Erstellen, Modifizieren und Löschen von Dummy-Datensätzen
  • Erstellen und Löschen von Relationen zwischen Datensätzen
  • Ein- und Ausloggen von Dummy-Usern
  • Automatisiertes Aufräumen aller Dummy-Datensätze
  • Fake-Mailer zum Testen von ausgehenden E-Mails
  • Konfigurations-Proxy zum Abrufen/Überschreiben von Einstellungen aus dem Extension-Manager
  • Header-Proxy, um die Ausgabe von HTTP-Errorcodes zu testen
  • Diverse Hilfsfunktionen

Diese Funktionen erleichtern bereits die Entwicklung von Tests, weitere Features, wie die Erstellung von Dummy-Dateien, sind bereits geplant.

Anzeige
Anzeige

Schreiten wir zur Tat

Das folgende Code-Beispiel zeigt einen realen Ausschnitt aus der „Seminar Manager“-Extension. Das Testobjekt ist die „Places“-Klasse, die einen Veranstaltungsort repräsentiert.

Zur Erzeugung einer Objektinstanz dieser Klasse ist ein Datensatz in der entsprechenden Tabelle nötig, der die Testdaten enthält. Vor dem Anlegen der Dummy-Datensätze bildet der Aufruf der Methode setUp() aber zunächst eine Instanz des Testing-Frameworks. Die Methode createRecord() legt dann einen Dummy-Datensatz an, mit dessen Daten das Testobjekt instantiiert wird und allen folgenden Testfunktionen als „$this->fixture“ zur Verfügung steht.

Aufbaufunktion setUp()
	private $fixture;
	private $testingFramework;
	public function setUp() {
		$this->testingFramework = new tx_oelib_testingFramework('tx_seminars');
		$uid = $this->testingFramework->createRecord(
			'tx_seminars_sites',
			array(
				'title' => 'TEST Place 1',
				'city' => 'Tokyo',
				'country' => 'JP'
			)
		);
		$this->fixture = new tx_seminars_place($uid);
	}

Listing 2

Genau wie für den Aufbau der Testumgebung existiert auch eine Methode für deren Beendigung: Ziel der Funktion „tearDown()“ ist das Aufräumen nach dem Testen. Nach der Initialisierung des Aufräumvorgangs für das Testing-Framework zerstört die Methode unset() dann die erzeugten Objekte.

Anzeige
Anzeige
Aufräumfunktion tearDown()
	public function tearDown() {
		$this->testingFramework->cleanUp();
		unset($this->testingFramework);
		unset($this->fixture);
	}

Listing 3

Nachdem das Grundgerüst nun aufgebaut wurde, fehlen in dem Beispiel noch einige Testfunktionen. Im folgenden Code ist zu erkennen, wie in den Tests auf die vorbereitete Fixture zugegriffen wird.

Zwei Test-Funktionen
	public function testGetCity() {
		$this->assertEquals(
			'Tokyo',
			$this->fixture->getCity()
		);
	}
	public function testGetCountryIsoCode() {
		$this->assertEquals(
			'JP',
			$this->fixture->getCountryIsoCode()
		);
	}

Listing 4

Bei nur zwei Tests wird der Vorteil der zentralen Erstellung von Fixtures nicht ganz so deutlich. Bei Klassen mit mehr als 100 Tests fällt es hingegen stark ins Gewicht, ob jeder einzelne Test selbst Dummy-Datensätze erstellen und Objekte instantiieren muss oder ob diese Funktionen an zentraler Stelle geregelt werden.

TYPO3 und Unit Testing – eine Bestandsaufnahme

Bei den TYPO3-Extensions ist eine klare Bestandsaufnahme nicht möglich. Man kann aber davon ausgehen, dass nur die wenigsten Extensions mit Unit Tests „abgesichert“ sind. Bei den Entwicklerteams, die getestete Extensions veröffentlichen, können einzelne Extensions mehr als 500 Einzeltests beinhalten.

Anzeige
Anzeige

Den beiden Teamleitern von TYPO3 zufolge wird für den 4.x-Branch über die Einführung von Unit Tests nachgedacht – der einzige Hinderungsgrund ist der erwartete Initialaufwand bei der Einführung.
In der ersten Ausgabe des T3N Magazins 2005 schrieb Robert Lemke in einem Artikel zu Unit Testing: „Am besten verwendet man Unit Tests bereits bei der Entwicklung neuen Codes und nicht erst beim Refactoring.“ Der Satz bringt kurz und knapp auf den Punkt, dass nachträgliche Tests meistens mit erheblichem Aufwand einhergehen; wird von Anfang an jede Funktion getestet, hält sich der Zusatzaufwand dagegen in Grenzen.

Bei der Entwicklung von TYPO3 5.x und FLOW3 wurde von Beginn an konsequent auf Test Driven Development (TDD) gesetzt, dadurch erreichten die Entwickler eine hohe Code Coverage von über 70 Prozent. Laut Robert Lemke hat das Team ausschließlich positive Erfahrungen mit diesem Vorgehen gemacht und traf auf keine Akzeptanzprobleme bei den Entwicklern. Dafür dominierte das Green Bar Feeling, das die Entwicklung saubereren Codes und eine erhöhte Testfrequenz mit sich brachte.

Mehr zu diesem Thema
Fast fertig!

Bitte klicke auf den Link in der Bestätigungsmail, um deine Anmeldung abzuschließen.

Du willst noch weitere Infos zum Newsletter? Jetzt mehr erfahren

Anzeige
Anzeige
Schreib den ersten Kommentar!
Bitte beachte unsere Community-Richtlinien

Wir freuen uns über kontroverse Diskussionen, die gerne auch mal hitzig geführt werden dürfen. Beleidigende, grob anstößige, rassistische und strafrechtlich relevante Äußerungen und Beiträge tolerieren wir nicht. Bitte achte darauf, dass du keine Texte veröffentlichst, für die du keine ausdrückliche Erlaubnis des Urhebers hast. Ebenfalls nicht erlaubt ist der Missbrauch der Webangebote unter t3n.de als Werbeplattform. Die Nennung von Produktnamen, Herstellern, Dienstleistern und Websites ist nur dann zulässig, wenn damit nicht vorrangig der Zweck der Werbung verfolgt wird. Wir behalten uns vor, Beiträge, die diese Regeln verletzen, zu löschen und Accounts zeitweilig oder auf Dauer zu sperren.

Trotz all dieser notwendigen Regeln: Diskutiere kontrovers, sage anderen deine Meinung, trage mit weiterführenden Informationen zum Wissensaustausch bei, aber bleibe dabei fair und respektiere die Meinung anderer. Wir wünschen Dir viel Spaß mit den Webangeboten von t3n und freuen uns auf spannende Beiträge.

Dein t3n-Team

Melde dich mit deinem t3n Account an oder fülle die unteren Felder aus.

Bitte schalte deinen Adblocker für t3n.de aus!
Hallo und herzlich willkommen bei t3n!

Bitte schalte deinen Adblocker für t3n.de aus, um diesen Artikel zu lesen.

Wir sind ein unabhängiger Publisher mit einem Team von mehr als 75 fantastischen Menschen, aber ohne riesigen Konzern im Rücken. Banner und ähnliche Werbemittel sind für unsere Finanzierung sehr wichtig.

Schon jetzt und im Namen der gesamten t3n-Crew: vielen Dank für deine Unterstützung! 🙌

Deine t3n-Crew

Anleitung zur Deaktivierung
Artikel merken

Bitte melde dich an, um diesen Artikel in deiner persönlichen Merkliste auf t3n zu speichern.

Jetzt registrieren und merken

Du hast schon einen t3n-Account? Hier anmelden

oder
Auf Mastodon teilen

Gib die URL deiner Mastodon-Instanz ein, um den Artikel zu teilen.

Anzeige
Anzeige