Apache Ant - Department of Information Systems
Transcrição
Apache Ant - Department of Information Systems
Westfälische Wilhelms-Universität Münster Ausarbeitung Apache Ant Im Rahmen des Seminars „Software Engineering“ Robin Trenkner Themensteller: Prof. Dr. Herbert Kuchen Betreuer: Christian Hermanns Institut für Wirtschaftsinformatik Praktische Informatik in der Wirtschaft Inhaltsverzeichnis 1 Einleitung ................................................................................................................... 1 2 Grundlagen ................................................................................................................ 1 3 4 5 2.1 Bulid-Tools ........................................................................................................ 1 2.2 Apache Ant......................................................................................................... 2 Basiselemente von Apache Ant ................................................................................. 3 3.1 Project ................................................................................................................ 4 3.2 Target ................................................................................................................. 5 3.3 Task .................................................................................................................... 7 3.4 Property .............................................................................................................. 8 3.5 Fileset ................................................................................................................. 9 3.6 Kommandozeilenoptionen von Ant ................................................................. 11 Erweiterte Funktionalitäten und Vergleich mit anderen Build-Werkzeugen .......... 12 4.1 JUnit Testing mit Apache Ant.......................................................................... 12 4.2 Vergleich mit dem Build-Tool Make ............................................................... 16 4.3 Vergleich mit dem Build-Tool Maven ............................................................. 18 Fazit und Ausblick ................................................................................................... 19 Literaturverzeichnis ........................................................................................................ 21 II Kapitel 1: Einleitung 1 Einleitung Die Software-Entwicklung gestaltet sich immer mehr zu einer komplexen und im Gesamten unübersichtlichen Aufgabe. Selbst kleine Anwendungen bestehen aus Abhängigkeitsbäumen mit mehreren hundert Methoden. Zur Vereinfachung der Prozesse der Kompilierung, der Wartung, des Testens, des Deployens und vielen anderen, werden Build-Tools eingesetzt. Um die Verwendung von Build-Tools führt heute schon bei kleineren Projekten kein Weg mehr vorbei, andernfalls wäre die Effektivität des Entwicklungsprozesses deutlich gefährdet. Ein, in der Praxis, weit verbreitetes Build-Tool nennt sich „Ant“ und wird von der Apache Software Foundation als Open-Source-Software vertreiben. Im 2. Kapitel dieser Ausarbeitung wird zunächst der Begriff des Build-Tools beschrieben und erläutert, im weiteren Verlauf wird auf das Build-Tool Ant eingegangen. Im dritten Abschnitt wird das Kernthema vertieft, indem das Java-basierte Tool Ant genauer beschrieben wird. Hier wird vereinzelt auf die Basiselemente von Ant eingegangen, die teilweise mit ausgewählten Beispielen erklärt werden sollen. Nachdem die wichtigsten Elemente von Ant bekannt sind, wird sich dem JUnit-Testen als eines der zentralen, erweiterbaren von Funktionalitäten von Ant, gewidmet. Mit dem Bezug auf die agilen Methoden der heutigen Softwareentwicklung ist ein starker Bezug zur Realität gegeben. Im weiteren Verlauf des 4. Kapitels wird Ant mit dem alten BuildTool Make und seinem designierten Nachfolger Maven verglichen. Diese Ausarbeitung schließt mit einem Fazit und Ausblick in Kapitel 5. 2 Grundlagen 2.1 Bulid-Tools Generell kann unter einem Build-Tool ein Werkzeug verstanden werden, das den vorhandenen Quellcode mit minimalem Aufwand in eine Zielsprache überführt. Gerade bei komplexen Programmieraufgaben ist dieses Überführen keine triviale Aufgabe, die der Anwender effizient und ohne hohen Aufwand selbst durchführen kann. Oft genügt es beispielsweise, wenn nur einzelne (von Änderungen betroffene) Module eines 1 Kapitel 2: Grundlagen Softwareprojekts re-kompiliert werden. In der Regel bestehen zwischen verschiedenen Modulen (z.B. Klassen) Abhängigkeiten, was bei einer Änderung gegebenenfalls dazu führen kann, dass Anpassungen notwendig sind. Dies manuell durchzuführen würde bei komplexen Programmierprojekten ein nur sehr schwer zu bewältigender Vorgang darstellen, der sehr fehleranfällig wäre. Aus dieser Motivation heraus entstand die Idee Build-Tools zu erstellen. Im optimalen Fall ist ein gutes Build-Tool in der Lage Abhängigkeiten aufzulösen und zu erkennen, welche Dateien bzw. Klassen neu kompiliert werden müssen. Des Weiteren kann es Dokumentationen erzeugen, Units testen, das Produkt packen, deployen und dynamischen Quellcode erzeugen. Im Laufe der Zeit und mit der Entwicklung mächtigerer Build-Tools stellten Build-Tools weitere Aktionen zur Verfügung, wofür insbesondere Apaches Ant ein gutes Beispiel ist. Um den Zweck und Nutzen von Build-Tools zu verdeutlichen, vergleichen HATCHER und LOUGHRAN das Build-Tool mit einer modernen, automatischen Auto-Fabrik und den selbst geschriebenen Quellcode mit dem Rohmaterial [HL04, S.34]. Auch wenn dieser Vergleich auf dem ersten Blick sehr oberflächig erscheint, so ist er im Prinzip doch anwendbar: Autos wurden in den Anfangsjahren der Entwicklung größtenteils manuell gefertigt, heute werden diese automatisch von Werkzeugen (Robotern) effizient und erfolgreich realisiert, genauso wie es Build-Tools mit den komplexen Softwareprojekten handhaben. 2.2 Apache Ant Bei Ant handelt es sich um ein etabliertes Build-Tool, das in Java geschrieben wurde. Entwickelt wurde das Programm ursprünglich als Build-Tool für den Tomcat Server im Jahre 1998 von James Duncan Davidson. Der Name „Ant“ steht für die Abkürzung „Another Neat Tool“ (dt.: „Noch ein hübsches Werkzeug“). Im Laufe der Zeit verlor die eigentliche Bedeutung dieser Abkürzung an Bedeutung und die Analogie zu dem Insekt Ameise (engl.: „Ant“) wurde prägend für das Build-Tool. Der Vergleich des Tools mit dem Insekt kommt nicht von ungefähr, denn [HL04, S.33]: • Ameisen suchen den kürzesten Weg, um Hindernisse zu umgehen • Ameisen könnten das 50-fache ihres eigenen Gewichts tragen • Ameisen arbeiten rund um die Uhr; aufgeteilt in Schichten All diese Eigenschaften können auch auf das Build-Tool sinngemäß übertragen werden. 2 Kapitel 3: Basiselemente von Apache Ant Apache Ant dient zur automatischen Generierung von Programmen aus Quelltext und erweitert die Funktionalität von Entwicklungsumgebungen. Die aktuellste Version von Ant ist 1.7.1.1 Wie bei der Apache Software Foundation üblich, handelt es sich bei Ant um ein Open-Source Projekt. Durch die Realisierung in Java benötigt Ant in jedem Fall eine (aktuelle) Java-Laufzeitumgebung (JDK, damit alle Möglichkeiten genutzt werden können), hierdurch ergibt sich ein großer Vorteil von Ant: Die PlattformUnabhängigkeit. Der Einsatz von Ant lohnt sich, ähnlich wie bei anderen Build-Tools erst wenn der Programmieraufwand entsprechend hoch ist und eine Komplexität an Programmieraufgaben gegeben ist [Ma05, S.1]. Dies begründet sich unter Anderem darin, dass ein relativ großer Einarbeitungsaufwand notwendig ist, um Ant effektiv und im großen Umfang nutzen zu können. In der (Java-) Praxis hat Ant weitestgehend das Build-Tool „make“ abgelöst [ES06, S.7]. Ant hat sich innerhalb weniger Jahre zum De-facto-Standard nicht nur für OpenSource-Java-Projekte entwickelt, sondern wurde auch in eine große Anzahl kommerzieller Produkte eingebaut. Sogar für Microsofts Entwicklungsumgebung .NET existiert ein erfolgreicher Clone [HL04, S. 19]. Als Gründe für den Erfolg kann unter anderem das Leistungsverhalten, die Community, die Abwärtskompatibilität, sowie erweiterbare Architektur angesehen werden. Beispielsweise stellt die Einbindung des Java-Test-Tools JUnit einen Vorteil von Ants Erweiterbarkeit dar, auf die im späteren Verlauf noch eingegangen wird. Als „Nachfolger“ von Ant ist Apache Maven zu verstehen, welches versucht den Build-Prozess etwas abstrakter zu beschreiben. 3 Basiselemente von Apache Ant Die Aufgaben, die Ant erfüllen kann, bestehen darin Gruppen von Dateien zu spezifizieren und auf diese bestimmte Kommandos und/oder Operationen anzuwenden. Beispiele hierfür wären: Den Java-Compiler aufrufen, Dateien kopieren, Archive erstellen, Dateien deployen, usw.. Ant ist somit geeignet, um aus gegebenen JavaQuellcode eine komplette, installierbare Anwendung zu generieren. Anhand des Funktionsumfangs wird deutlich, dass auch Einsatzszenarien bestehen, bei denen Ant 1 Stand: Oktober 2008. Aktuelle Version kann auf der Homepage des Apache Ant Projekts eingesehen und heruntergeladen werden: http://ant.apache.org/. 3 Kapitel 3: Basiselemente von Apache Ant ohne Programmierung eingesetzt werden kann: Bspw. um effektiv Dateien zu kopieren. Die Build-Language von Apache Ant ist XML-basiert, die Konfiguration eines Projektes wird entsprechend in der Datei build.xml festgelegt (die Build-Datei kann einen beliebigen Dateinamen besitzen, build.xml ist lediglich die Standardbezeichnung). Um einen groben Überblick von Ant zu bekommen bietet es sich an, die Grundlegenden Basiselemente des Build-Tools zu betrachten. Properties Properties Properties Properties Task Task Task Task Task Task Task Task Task Task Task Task Target Target Target Abbildung 1: Grundlegende Elemente einer Build-Datei Die Abbildung 1 veranschaulicht die grundlegenden Elemente einer Build-Datei von Ant, auf die in den folgenden Unterkapiteln im Einzelnen näher eingegangen wird. 3.1 Project Jede XML-Build-Datei beschreibt wie ein Projekt erstellt wird. Es besteht die Möglichkeit größere Projekte aus mehreren kleinen Projekten zusammenzusetzen, hierbei besitzen die Unterprojekte jeweils eine eigene Build-Datei. Bei dem Projekt handelt es sich somit um das umfassende Objekt, das die Ablaufumgebung für die Kommandos darstellt [HL04, S.36; Ma05, S.6f.]. Beispiel-Deklaration eines Projekts: <?xml version="1.0" encoding="UTF-8"?> <project name="testproject" default="main" basedir="."> … </project> 4 Kapitel 3: Basiselemente von Apache Ant Bei der ersten Zeile, die am Anfang jeder Build-Datei zu finden ist, handelt es sich um eine XML-typische Anweisung, in der hauptsächlich die Zeichenkodierung festgelegt wird (hier: UTF-8). In der zweiten Zeile mit dem <project>-Tag beginnt das eigentliche Projekt innerhalb der Build-Datei. Mit der Hilfe des Attributs default wird das zu startende Target definiert, wenn kein anderes beim Aufruf der Build-Datei explizit angegeben wird. Das Attribut basedir definiert das Arbeitsverzeichnis des Skriptes, für den Fall dass vom Standard (Verzeichnis in dem sich das Skript befindet) abgewichen werden soll, kann hier eine Zuweisung erfolgen [ES06, S.14; Ma05, S.8f.]. 3.2 Target Ein Target umfasst ein oder mehrere Tasks und bildet den Container für die eigentlichen Operationen, die mit den Tasks ausgeführt werden. Targets besitzen einen eindeutigen Namen innerhalb der Build-Datei des Projekts, dieser dient zur späteren Identifizierung. Mit Hilfe der Targets lässt sich die Build-Datei übersichtlich strukturieren, es ist die einzig echte Modularisierungseinheit, die Ant kennt. [Ma05, S.17]. Um die gewünschte Ablaufsteuerung zu realisieren verfügt das <target>-Tag über verschiedene Attribute: Attribut name depends if unless description Beschreibung Name des Targets. Target wird erst gestartet, wenn die Targets aus der Liste erfolgreich ausgeführt wurden. Targets innerhalb der Liste werden durch Kommas getrennt. Wenn das angegebene Property existiert wird das Target ausgeführt, andernfalls nicht. Pendant zu if: Wenn das angegebene Property nicht existiert wird das Target ausgeführt. Kurze Beschreibung der Funktion des Targets. Wird angegeben wenn Ant mit entsprechender Kommandozeilenoption aufgerufen wird („projecthelp“) erforderlich Ja Nein Nein Nein Nein Tabelle 1: Attribute für das <target>-Tag [AA08] Mit der Hilfe des depends Attributes können statische Abhängigkeiten definiert werden. Erfolgreiche Ausführung bedeutet nicht, dass das Target wirklich etwas getan haben muss, vielmehr ist hiermit der Umstand gemeint, dass keine Exception während 5 Kapitel 3: Basiselemente von Apache Ant der Ausführung auftrat [Ma05, S.18]. Das folgende Beispiel zeigt mögliche statische Abhängigkeiten: <project name="demo_abhaenigkeiten" default="target1"> <target name="target1" depends="target 2,target4"> <echo message="Target1 ausgeführt"/> </target> <target name="target2" depends="target3"> <echo message="Target2 ausgeführt"/> </target> <target name="target3" depends="target4"> <echo message="Target3 ausgeführt"/> </target> <target name="target4"> <echo message="Target4 ausgeführt"/> </target> </project> Der Aufruf dieses Projektes ohne weitere Parameter liefert folgende Ausgabe: Target4 Target3 Target2 Target1 ausgeführt ausgeführt ausgeführt ausgeführt Die Abhängigkeiten der Targets innerhalb dieses Mini-Projektes können wie folgt dargestellt werden. Abbildung 2: Abhängigkeiten der Targets untereinander Ant führt jedes Target nur einmal aus und prüft vorher die Abhängigkeiten, die das depends-Attribut überliefert. Target4 besitzt keine Vorbedingungen (vgl. Abbildung 1) und wird somit als erstes abgearbeitet. Hiernach sind Target3, Target2 und schließlich Target1 an der Reihe. Hierbei wird deutlich, dass das depends –Attribut lediglich Voraussetzungen definiert. Das Beispiel zeigt dass die Targets nicht gezwungenermaßen in der Reihenfolge abgearbeitet werden müssen, in der sie bei depends aufgezählt wurden. An dieser Stelle sei erwähnt dass Targets mit 6 Kapitel 3: Basiselemente von Apache Ant entsprechenden Kommandozeilenoptionen direkt angesprochen werden können. Beispiel: „ant –f demo_abhaengigkeiten.xml target2“. Hier ignoriert Ant das defaultAttribut des Projektes und versucht direkt Target2 auszuführen. Aufgrund der Abhängigkeiten werden zunächst Target4 und Target3 aufgerufen, Target1 wird nicht mehr berücksichtigt/ausgeführt. Ein weiteres kleines Beispiel illustriert die bedingten Wahrscheinlichkeiten, die mit den beiden Attributen if und unless realisiert werden können. <project name="unlessif" default="main" basedir="."> <target name="main" depends="target1, target2, target3"/> <target name="target1" if="prop1"> <echo message="Property1 existiert"/> </target> <target name="target2" unless="prop1"> <echo message="Property1 existiert nicht"/> </target> <target name="target3" if="prop1" unless="prop2"> <echo message="Property1 existiert und Property2 nicht"/> </target> </project> Target1 wird nur ausgeführt, wenn das Property prop1 existiert, Target2 hingegen nur wenn Property1 nicht existiert. Target3 wird nur ausgeführt, wenn Property1 definiert und Property2 nicht definiert wurde. Entsprechend gibt es mehrere mögliche Kommandozeilen-Aufrufe dieser unlessif.xml: Kommando ant-f unlessif.xml ant-f unlessif.xml –Dprop1=x ant-f unlessif.xml –Dprop1=x –Dprop2=x ant-f unlessif.xml –Dprop2=x echo-Ausgabe Property1 existiert nicht Property1 existiert, Property1 existiert und Property2 nicht Property1 existiert Property1 existiert nicht Tabelle 2: Verschiedene Kommandos und Ausgaben fürs obere Beispiel 3.3 Task Wie schon bei den Targets beschrieben, handelt es sich bei den Tasks um die eigentlichen, ausführbaren Operationen. Ant stellt bereits vorgefertigte Tasks für unterschiedliche Aufgaben zur Verfügung. Für den Fall, dass der Benutzer einen Task benötigt, der standardmäßig nicht in Ant vorhanden ist, so kann dieser leicht in Java programmiert werden und Ant um diesen Task erweitert werden, was zu den 7 Kapitel 3: Basiselemente von Apache Ant Hauptstärken von dem Build-Tool Ant zählt. Tabelle 3 enthält eine Auswahl grundlegender Ant-Tasks. Zu den vordefinierten Tasks gehören jeweils verschiedene Attribute bzw. Parameter um die Aufgabe einzugrenzen und steuern zu können. Diese sind in der folgenden Tabelle nicht enthalten. Task ant antcall copy, delete, move echo exec get jar, java, javac, rmic, war javadoc/javadoc2 mail mkdir property sql sync waitfor gzip,gunzip, tar, untar, zip, unzip Bedeutung Separater Aufruf einer Build-Datei. Target aus aktueller Build-Datei aufrufen. Datei/Verzeichnis-Operationen: Kopieren, Löschen, Verschieben. Nachricht während der Skript-Ausführung ausgeben (an Logger / Listener). Systemaufruf (z.B. .Batch-Dateien). Datei von URL herunterladen. Operationen für Java. Dokumentation mit dem Javadoc-Tool erstellen. Versenden einer E-Mail (z.B.: Statusbericht). Verzeichnis erstellen. Property (Variable) im Projekt setzen. SQL Statements mittels JDBC auf eine Datenbank anwenden. Synchronisation eines Verzeichnisses. Operationen blockieren (z.B. für eine bestimmte Zeit). Archivoperationen. Tabelle 3: Auswahl grundlegender Ant-Tasks [AA08] Im Regelfall werden Tasks immer Targets zugeordnet, um einen geregelten Ablauf zu gewähren. Einen Sonderfall stellen Tasks dar, die außerhalb platziert sind (innerhalb des <projects>-Tags und somit immer ausgeführt werden, wenn die Build-Datei mit Ant gestartet wird. 3.4 Property Properties stellen in Ant einen Platzhalter für einen Wert dar. Es existieren verschiedene Wege, um einem Property einen Wert zuzuweisen (z.B.: Aufruf einer Build-Datei mit entsprechendem Parameter oder direkt in der Build-Datei). Properties können Zeichenketten aufnehmen, deren Länge theoretisch unbegrenzt ist und können zu einem beliebigen Zeitpunkt im Build-Prozess erzeugt werden. Wurde einem Property ein Wert 8 Kapitel 3: Basiselemente von Apache Ant zugewiesen, so kann dieser später nicht mehr verändert werden sondern bleibt während des Build-Prozesses zwangsläufig unverändert. Das Löschen eines Properties wird ebenfalls nicht zugelassen. Properties sind vor allem dafür zuständig die Ablaufumgebung einer Build-Datei zu generieren, meistens werden sie aus separaten Property-Dateien erzeugt. Beispiel für eine Property-Definition innerhalb einer Build-Datei: <property name="dir.build" value="./classes"/> Mit der Hilfe des <property> - Tags werden Properties definiert, value weist dem Property einen Wert zu. Hier handelt es sich um ein Property, das den Pfad für die kompilierten Klassen bereit stellt. Der Zugriff auf Properties erfolgt immer in folgernder Form: ${Property-Name} <mkdir dir="${dir.build}"/> Dieser Task beispielsweise erstellt ein Verzeichnis mit dem Namen „classes“. Neben der Möglichkeit Properties innerhalb der Build-Datei zu erzeugen, gibt es weitere Mechanismen zur Definition von Properties [Ma05, S. 24]. Beispielsweise können Properties aus einer Datei ausgelesen werden, des Weiteren erzeugen diverse Tags Properties um Statusinformationen bereit zu stellen. Ant bzw. die JVM stellt ebenfalls einige allgemein gültige Properties zur Verfügung (Beispiele: java.version, os.name, ant.version). <property file=“my.properties“ prefix=“my“ /> Mit der obigen Zeile werden Properties aus der Datei „my.properties“ in dem aktuellen Arbeitsverzeichnis eingelesen. Selbstverständlich könnte hier anstelle des Dateinamens auch ein Property stehen. Mit der Hilfe von prefix erhalten alle Properties den prefix „my“ womit verhindert werden soll, dass Konflikte auftreten weil bereits Properties mit dem gleichen Namen wie in der Property-Datei bestehen. Innerhalb der Property-Datei sind die Properties wie folgt zu definieren: „<key>=<value>“. 3.5 Fileset Wie in Abschnitt 2.2 beschrieben, besteht die eigentliche Aufgabe von Ant darin, Dateien mit bestimmten Operationen zu bearbeiten. Mit der Hilfe von Filesets können Listen von einer oder mehreren Dateien spezifiziert werden, dies macht sie zu einen der 9 Kapitel 3: Basiselemente von Apache Ant wichtigsten Elemente von Ant überhaupt [Ma05, S. 40]. Bei dem <fileset>-Tag handelt es sich nicht um kein separat ausführbares Kommando, vielmehr wird es immer von anderen Kommandos als eigebettetes Tag benutzt. Zur Auswahl der Dateien stehen zwei unterschiedliche Methoden bereit: • Selektion von Dateien über Muster, die sich auf Pfad und Dateinamen beziehen • Auswählen der Dateien durch Selektoren, die Dateien anhand bestimmter Eigenschaften selektieren (z.B.: Datum, Länge, bestimmter Text ist in der Datei vorhanden) In der nachfolgenden Tabelle 4 sind die Attribute des <fileset>-Tags aufgelistet und kurz erläutert: Attribut dir file defaultexcludes includes Beschreibung erforderlich Wurzelverzeichnis des Filesets. entweder Benötigt für ein Fileset mit nur einer Datei. oder Legt fest, ob spezielle Dateien automatisch Nein ausgeschlossen werden. Default=true. Dateien die beachtet werden sollen (durch Nein Komma oder Leerzeichen getrennt), Muster können angegeben werden. Default= alle Dateien werden betrachtet. includesfile Datei, mit Liste der zu betrachtenden Nein Dateinamen, Muster können angegeben werden. excludes Dateien, die auszuschließen sind (durch Komma Nein oder Leerzeichen getrennt), Muster können angegeben werden. excludesfile Datei, mit Liste der nicht zu betrachtenden Nein Dateinamen. caseGroß-/Kleinschreibung berücksichtigen? Nein sensetive Default=true. followSollen Symlinks verfolgt werden? Default=true. Nein symlinks Symlinks sind auf UNIX-Systemen bereits länger bekannt und ab Vista auch auf WindowsPlattformen verfügbar. Nicht zu verwechseln mit normalen Verknüpfungen! errormissing- Spezialisiert, was passiert wenn das Nein dir Arbeitsverzeichnis nicht existiert. True: Build Error, false: Fileset wird ignoriert / ist leer. Default seit Ant 1.7.1= true. Tabelle 4: Attribute des Fileset-Tags [AA08] Beispiel Fileset: <copy todir=”${target.dir}”> <fileset id=”copytest” dir=“${source.dir}“> <includes=”**/*.java”/> 10 Kapitel 3: Basiselemente von Apache Ant <eclude=”**/*Test”/> </fileset> </copy> In dem genannten Beispiel werden alle Dateien mit der Endung „.java“, die im Text nicht „Test“ enthalten, kopiert. Der Quell- und Ziel-Ordner sind in den Properties source.dir und target.dir zuvor definiert worden (bspw. durch einen entsprechenden Aufruf der Build-Datei). Durch die zugewiesene ID kann das Fileset später an anderer Stelle referenziert werden. 3.6 Kommandozeilenoptionen von Ant In Abschnitt 3.3 wurde beim Beispiel für bedingte Wahrscheinlichkeiten für Targets (if- und unless-Attribute) eine Kommandozeilenoption von Ant gezeigt, mit deren Hilfe Properties durch den Aufruf gesetzt werden können. Nachdem in den vorausgegangenen Kapiteln wichtige Basiselemente von Ant betrachtet wurden, ergibt es Sinn einen Überblick über die Startparameter von Ant zu bekommen, weil sich diese konkret auf den Build-Prozess auswirken können (siehe das Beispiel für bedingte Wahrscheinlichkeiten). In Tabelle 1 sind einige wichtige Kommandozeilenoperationen von Ant aufgelistet und zusammengefasst (die komplette Liste findet sich in der Ant Benutzer-Dokumentation [AA08]). Option -help, -h -projecthelp, -p -quiet, -q -verbose, -v -lib <path> -logfile <file> -l <file> -buildfile/file <file> -f <file> -D<property>=<value> -keep-going -k -propertyfile <name> Bedeutung Zeigt die kompletten Kommandozeilenoptionen von Ant an. Zeigt Informationen übr das aktuelle Projekt an. Extra wenige Meldungen ausgeben. Extra viele Meldungen ausgeben. Pfad, auf dem nach Jar-Dateien und Klassen gesucht werden soll. Log in eine bestimmte Datei schreiben. Die angegebene Build-Datei verwenden (ohne Angabe: build.xml). <property> auf den Wert <value> setzen. Alle Targets ausführen, die nicht von gescheiterten Targets abhängig sind. Properties aus einer Datei laden. Mit „-D“ definierte Properties besitzen Vorrang! Tabelle 5: Einige Kommandozeilenoperationen von Ant [AA08] 11 Kapitel 4: Erweiterte Funktionalitäten und Vergleich mit anderen Build-Werkzeugen 4 Erweiterte Funktionalitäten und Vergleich mit anderen Build-Werkzeugen 4.1 JUnit Testing mit Apache Ant Software-Fehler verursachen in der Praxis erhebliche Kosten. Daher ist es sinnvoll laufend neue Testfälle zu erstellen und auszuführen, bevor eine lokale Entwicklungsumgebung überhaupt verlassen wird. Die Idee der „Testgetriebenen Entwicklung“ beschreibt das Vorgehen, dass fehlerarmer Code erzeugt wird, indem nichts implementiert wird, was nicht zuvor getestet wurde. Dies wird in den agilen Verfahren der Software-Entwicklung wie beispielsweise „Extreme Programming (XP)“ berücksichtigt. Innerhalb der Java-Entwicklung hat sich das JUnit-Test-Framework zu einem De-factoStandard entwickelt um eine Testgetriebene Entwicklung zu realisieren. JUnit, ursprünglich entwickelt von Kent Beck und Erich Gamma, eignet sich besonders um automatisierte Unit-Tests (z.B. Tests von Klassen oder Methoden) durchzuführen. Aus diesem Grund ist JUnit in Ant integriert worden, somit können Tests als Teil des BuildProzesses ausgeführt und die Ergebnisse verarbeitet werden. Der Benutzer erhält die Möglichkeit Informationen darüber zu bekommen, ob sein Code innerhalb eines bestimmten Kontextes funktioniert. Erwartete und tatsächliche Ergebnisse lassen sich durch zahlreiche Zusicherungsfunktionen von JUnit vergleichen. Entsprechend der Hauptgrundsätze des Extreme Programmings sollte das Schreiben sowie Ausführen von Tests simpel sein, aus diesem Grund ist es mit keinem großen Aufwand verbunden einen JUnit-Test zu schreiben, es sind drei Schritte notwendig [HL04, S.123]: • Erstellung einer Unterklasse von junit.framework.TestCase. • Konstruktor zur Verfügung stellen, der einen einzelnen name-String-Prarmeter entgegennimmt und super(name) aufruft. • Implementierung einer oder mehrerer void-Methoden, die keine Argumente haben und deren Namen das Wort „test“ vorangestallt wird. Code-Beispiel: 12 Kapitel 4: Erweiterte Funktionalitäten und Vergleich mit anderen Build-Werkzeugen import junit.framework.TestCase; public class SimpleTest extends TestCase { public SimpleTest (String name) { super(name); } public void testMe(){ assertTrue(9 == (3 * 3)); } public void testMeToo(){ assertTrue(8 == (5 + 3)); } } In diesem kleinen Beispiel für einen Testfall ist der Konstruktor zu sehen sowie zwei void-Test-Methoden. JUnit stellt TestRunner-Klassen zur Verfügung, mit denen alle Tests ausgeführt werden können, die durch das vorgestellte „test“ gekennzeichnet sind. Es existieren zwei verschiedene TestRunner: Ein textbasierter und ein Swing-basierter. Der SwingTestRunner von JUnit gibt die Ergebnisse in einem entsprechenden Fenster aus, Erfolge werden grün, Fehler rot visualisiert. Vorteil der Swing-Variante des TestRunners: Er kann Klassen dynamisch neu laden, kann somit geöffnet bleiben wenn der Code neu kompiliert wird. Damit JUnit zusammen mit Ant genutzt werden kann muss JUnit zunächst in der aktuellen Version heruntergeladen werden (http://www.junit.org). Ant muss die Möglichkeit besitzen die Datei junit.jar zu finden, deswegen muss die Datei in dem Ordner %ANT_HOME%/lib gespeichert werden (das Speichern im SystemKlassenpfad ist z.B. ebenfalls möglich, die Dokumentation empfiehlt jedoch alle Libraries, die Ant benötigt, in das Ant-lib-Verzeichnis einzufügen, damit eventuelle Komplikationen bei verschiedenen Ant Versionen nicht auftreten können). Apache Ant bietet mit dem optionalen <junit>-Task die Möglichkeit einen oder mehrere JUnit-Test(s) auszuführen. Die Testergebnisse werden gesammelt und in der gewünschten Form angezeigt. Zusätzlich bietet der Task die Möglichkeit einen Build abzubrechen oder fortzusetzen, wenn ein Test scheitert [HL04, S. 130]. Getestet wurde der <junit>-Task mit der JUnit Version 3.0 – 3.8.2. Mit älteren Versionen als 3.0 ist keine Funktionalität gegeben. Zwar funktioniert der Task auch mit JUnit Version 4.0, jedoch nur begrenzt, es wird somit die Nutzung der Version 3.8.2 empfohlen [AA08]. 13 Kapitel 4: Erweiterte Funktionalitäten und Vergleich mit anderen Build-Werkzeugen Tabelle 6 zeigt eine Auswahl an Attributen des <junit>-Tasks und erläutert diese kurz (alle Attribute sind optional anzugeben). Attribut Beschreibung printsummary Es werden einzeilige Statistiken für jeden Testfall ausgegeben. Mögliche Werte: on, off, withOutAndErr (das gleiche wie on, inkl. der Ausgabe der Tests die mittels System.out und System.err überliefert werden). fork Führt den Test in einer separaten Virtual Machine (VM) aus. forkmode Legt fest, wieviele Java VMs erstellt werden. Mögliche Werte: perTest, perBatch, once. haltonerror Stoppt den Build-Vorgang wenn ein Fehler beim Durchlaufen eines Tests auftritt. errorproperty Name einen Properties, das beim Auftreten eines Fehlers gesetzt wird. haltonfailure Stoppt den Build-Vorgang wenn ein Test fehlschlägt. timeout Bricht den einzelnen Test ab, wenn dieser nicht in einer bestimmten Zeit beendet wird (Millisekunden). Wird ignoriert wenn fork deaktiviert ist. maxmemory Maximale Größe des Arbeitsspeichers, die die VM belegen darf. Wird ignoriert wenn fork deaktiviert ist. showoutput Schickt jede Ausgabe die von Tests erzeugt wird auch an Ants Logging-System. tempdir Verzeichnis für temporäre Dateien (ansonsten wird wie gehabt das Projekt-Hauptverzeichnis hierfür genutzt) Default off off perTest off off - - Tabelle 6: Auswahl an Attributen des <junit>-Tasks [AA08] Die Tests in einen Ant-Build-Vorgang einzufügen stellt sich als nicht sehr kompliziert dar: Es müssen einige wenige Targets hinzugefügt werden, die Verzeichnisstruktur für die Tests initialisiert werden, der Test-Code kompiliert werden, der Test ausgeführt werden und schließlich die Testberichte generiert werden. Abbildung 3 zeigt das Refactoring eines Build-Vorgangs mit Unit-Test-Targets. 14 Kapitel 4: Erweiterte Funktionalitäten und Vergleich mit anderen Build-Werkzeugen <target> init <target> compile <target> test-init <target> test Weitere Tests <test>-Target Abbildung 3: Build-Vorgang mit Uni-Test-Targets [HL04, S.132] Es empfiehlt sich die Test-Targets sauber in die Build-Datei einzupflegen. Hierzu sollten mehrere Properties und Datentypengenutzt werden, damit fest eincodierte Pfade vermieden werden und der Testprozess flexibel kontrolliert werden kann: <property name="test.dir" location="${build.dir}/test"/> Weitere Properties (tst.data.dir, test.report.dir, usw.) sind analog zu erstellen. Gegebenenfalls muss für das Ausführen und vorherigem Kompilieren ein separater Klassenpfad definiert werden. Mit der Hilfe des <junit>-Tasks bestehen mehrere Möglichkeiten, die Testergebnisdaten zu sammeln, hierfür werden so genannte Formatierer benutzt, die mittels <formatter>-Tags innerhalb des <junit>-Tasks benutzt werden. Hier bestehen drei verschiedene Typen [HL04, S. 134]: • brief: Einzelheiten über das Scheitern von Tests werden in Textform zur Verfügung gestellt. • plain: Es werden zusätzlich zu den Einzelheiten über das Scheitern statistische Informationen über jeden ausgeführten Text in Textform erhoben. 15 Kapitel 4: Erweiterte Funktionalitäten und Vergleich mit anderen Build-Werkzeugen • xml: Die Einzelheiten werden im XML-Format zur Verfügung gestellt. Für jeden Testfall werden die Ant-Properties zum Zeitpunkt des Testens, die Systemausgaben und die Systemfehlerausgaben angegeben. Es besteht ferner die Möglichkeit eigene Ergebnis-Fromatierer zu erstellen, dies ist jedoch selten erforderlich, weil sich Testergebnisse im XML-Format ablegen lassen. Testergebnisberichte können einfach erstellt werden, insbesondere wenn die Testergebnisse als XML-Dateien vorliegen, kann mit nur wenigen Schritten ein Bericht im HTML-Format generiert werden. Hierfür steht ein eigener Task zur Verfügung: <junitreport> Ein möglicher <junit>-Task innerhalb einer Build-Datei könnte folgendermaßen aussehen: <junit printsummary="false" haltonfailure="true"> <classpath refid="test.classpath"/> <formatter type="brief" usefile="false"/> <test name=org.example.ShortTest"/> </junit> Für den Fall dass der JUnit-Test nicht korrekt durchläuft, wird auch der Ant-Build mit „BUILD FAILED“ abgebrochen. In diesem Fall werden die Einzelheiten über das Scheitern des Tests in Textform über die Ausgabe dargestellt. Zusammenfassend kann gesagt werden, dass Ant Unit-Tests entscheidend erleichtert indem es diese ausführt, Ergebnisse sammelt und einen Build-Vorgang abbricht, falls ein Test scheitern sollte. Properties und Datentypen ermöglichen gewohnt die Definierung von Klassenpfaden und Verzeichnissen, die zum Testen benötigt werden. Beachtet der Entwickler weitere Best Practices beim Generieren und Durchführen von Testfällen [HL04, S. 146], so unterstützt ihn Ant deutlich bei der Testgetriebenen Entwicklung von Programm-Code/Software-Projekten. 4.2 Vergleich mit dem Build-Tool Make Wie bereits beschrieben, hat Ant in der Praxis das deutlich ältere Build-Tool Make abgelöst. Make wurde bereits in den 70er Jahren von Stuart Feldman entwickelt und unter UNIX-Systemen verwendet. Feldman gilt seither als einer der Vorreiter im Bereich der Build-Tools. In der Praxis findet Make eine weite Verwendung, so werden sich Varianten von Make in fast jedem großen C- oder C++-Projekt verwendet [HL04, 16 Kapitel 4: Erweiterte Funktionalitäten und Vergleich mit anderen Build-Werkzeugen S. 40]. Make arbeitet mit einem dateizentrierten Konzept, Targets enthalten entweder den Namen einer Datei, die aktualisiert werden muss oder ein Phantomziel (PhonyTarget). Targets lösen Aktionen aus wenn sie aufgerufen werden, wie bei Ant sind auch hier Abhängigkeiten zu anderen Targets oder Dateien möglich. Ausnahmen sind die Phantomziele (die clean oder all heißen), die auch ohne Abhängigkeiten existieren können. Ant und Make besitzen zunächst die gleiche Aufgabe und den gleichen Zweck: BuildProzesse werden durch sie automatisiert und ausgeführt in dem eine entsprechende Build-Datei mit festgelegten Operationen ausgewertet wird. Abgesehen von der Syntax und anderen operationalen Einzelheiten besitzen Make und Ant verschiedene Auffassungen darüber, wie Build-Prozesse ablaufen sollten [HL04, S. 40]. • Bei der Verwendung von Ant wird eine Folge von Operationen und Abhängigkeiten zwischen diesen angegeben und den Datei-Abhängigkeiten überlassen, den Code auszuwählen, der alle Operationen innerhalb des BuildProzesses versteht. • Die Targets, die Ant unterstützt, sind den Phantomzielen von Make gleichzusetzen: Targets sind bei der Verwendung von Ant keine einzelnen Dateien sondern existieren in der Build-Datei. • Abhängigkeiten von Targets bestehen aus anderen Targets, sie geben keine Datei-Abhängigkeiten und keine Umwandlungsregeln für Dateien an. Stattdessen werden in der Ant-Build-Datei die Stufen angegeben, die in dem Prozess verwendet werden sollen. (Input-/Output-Dateien können angegeben werden, Platzhalter sind möglich). Beispiel: <javac>- und <jar>-Tasks: Diese Tasks können automatisch alle Java-Dateien in Unterverzeichnissen einbeziehen und entscheiden später, welche kompiliert werden müssen. • Jeder Task muss bei Ant in der von dem Target abgeleiteten Reihenfolge aufgerufen werden, die Tasks können wählen ob sie ausgeführt werden oder nicht. Der Vorteil ergibt sich daraus, dass Tasks mehr domänenspezifisches Wissen enthalten können als das Build-Tool selbst (z.B.: Abhängigkeitsprüfung). • Durch Platzhalter für Quelldateien, JAR-Dateien auf dem Classpath o.ä. können neue Dateien hinzugefügt werden, ohne dass die Build-Datei geändert werden 17 Kapitel 4: Erweiterte Funktionalitäten und Vergleich mit anderen Build-Werkzeugen muss. Dieser Vorteil macht sich bei Ant bemerkbar wenn Projekte größer werden, die Wartung der Build-Dateien aber weiterhin von minimalem Aufwand ist. Obwohl diese Unterscheide zwischen Ant und Make existieren und Ant für bestimmte Szenarien mehrere Vorteile bietet, bedeutet dies keinesfalls, dass Make seine Daseinsberechtigung als Build-Tool verloren hat. Ants Vorteile beruhen vor allem auf den Fall, dass Java-Projekte erstellt werden sollen. Falls es sich jedoch um die Erzeugung von C/C++-Anwendungen handelt, so ist Ant nicht unbedingt das richtige Werkzeug, sondern Make vorzuziehen [HL04, S.42]. Aus diesem Grund schließen sich die beiden Build-Tools auch nicht aus, sondern können zusammenarbeiten: Ant ermöglicht den einfachen Zugriff auf Make, umgekehrt ist Make in der Lage Ant unkompliziert auszuführen. 4.3 Vergleich mit dem Build-Tool Maven Maven wird wie Ant von der Apache Software Foundation entwickelt und (kostenlos) angeboten. Es handelt sich um ein Build-Management-Tool und basiert ebenfalls auf Java. Maven eignet sich zum Kompilieren, Testen und Packen eines Softwareprojekts, Aufgaben die auf dem ersten Blick auch von Ant beherrscht werden. Im Maven Projekt wurden Verbesserungen vorgenommen, die zuvor als Schwächen von Ant galten. Ant kann als eine Teilmenge von Maven angesehen werden, denn Ant Tasks können auch innerhalb Mavens benutzt werden. Die Motivation der Entwickler von Maven liegt darin, Entwicklern den Build-Prozess von jedem Java-Projekt so einfach wie möglich zu gestalten, Best Practices zu beachten und ein einheitliches Referenz-Build-Tool zu generieren [MA08]. Maven ist in der aktuellen Version 2.0.9 von der Projekt-Seite beziehbar (http://maven.apache.org/download.html). Der Gedanke hinter dem Maven-Projekt ist, dass von einem Zyklus ausgegangen wird, der bei der Entwicklung von Software mit Maven oft gleich ist. Eine zentrale XMLDatei von Maven ist die pom.xml [AM08]. Bislang wurden in Ant zu jedem Projekt eine entsprechende Build-Datei geschrieben, bestimmte Targets konnten für andere Projekte genutzt werden, gegebenenfalls mussten diese jedoch angepasst werden. Mavens Hauptgedanke beschäftigt sich mit der Tatsache, dass bestimmte Vorgänge bei der Erstellung von Software stets gleich sind und hat deswegen die Build-Skripte durch Plug-Ins und dem Projekt Object Model (POM) ersetzt [AM08; MS05, S.16]. Anders 18 Kapitel 5: Fazit und Ausblick als bei der Verwendung von Ant, ist die Verzeichnisstruktur innerhalb der Projekte von Maven vorgegeben (project.xml, maven.xml, project.properties müssen vorhanden sein). Src und target sind festgelegte Verzeichnisse. Die aus Ant bekannten Tasks werden durch die Plug-Ins ersetzt, die Konfigurations-Datei pom.xml enthält Informationen darüber, welche Plug-Ins benötigt werden. Neben Dokumentationen und Metriken zur Software-Bewertung bietet Maven die Möglichkeit innerhalt der Konfigurations-Datei maven.xml die XML-Scriptsprache Jelly anzuwenden, diese Funktion bietet Ant nicht an. Die maven.xml ist am nächsten Vergleichbar mit der build.xml die aus Ant bekannt ist, hier können neben definierten Zielen auch Ant-Tasks aufgerufen werden. 5 Fazit und Ausblick Das Build-Tool Ant von der Apache Software Foundation besitzt eine entscheidende Rolle in der Praxis. Aufgrund der immer häufigeren Verwendung von Java als Programmiersprache fiel es Ant in der Vergangenheit nicht schwer, Make als BuildTool abzulösen, denn Ant brachte deutliche Vorteile mit sich: Es kann plattformunabhängig benutzt werden und benutzt durch die XML-Notation eine bekannte und vertraute Form, Build-Dateien zu generieren. Make kann nicht als plattformunabhängig angesehen werden und besitzt eine eigene Beschreibungssprache für die Build-Dateien. Wenngleich von einer „Ablösung“ die Rede ist, hat Make seine Daseinsberechtigung nicht verlorenen, denn insbesondere bei der Generierung einer C / C++ Anwendung können Ant und sein „Nachfolger“ Maven das Tool Make nicht ersetzen, hier findet es weiterhin Anwendung. Innerhalb dieser Ausarbeitung wurden die grundlegenden Elemente von Ant dargestellt und erläutert. Als Erweiterbare Funktion wurde die Möglichkeit beschrieben, mit der Hilfe von Ant das Unit-Testen mit JUnit in den Build-Prozess mit einzubeziehen. Hiermit wurde verdeutlicht, dass Ant für aktuelle Anforderungen bei der modernen Softwareentwicklung gewachsen ist (agile Methoden wie beispielsweile Extreme Programming). Ant kann jedoch noch viel mehr, zum einen durch die endlose Erweiterbarkeit indem eigene Tasks in Java geschrieben werden können (hierdurch können auch andere Compiler als Java benutzt werden), zum anderen weil viele erweiterte Funktionalitäten bereits integriert sind. Als Beispiel sei die Anbindung an 19 Kapitel 5: Fazit und Ausblick SQL-Datenbanken genannt. Ant ist mit seinen Grundlagen schnell zu verstehen, aber in der Tiefe der Einarbeitung scheint es keine Grenze zu geben. Mit dem Projekt Maven hat die Apache Software Foundation ein weiteres Java-basiertes Build-Toll anzubieten. Ein Vergleich mit Ant ist durchaus interessant und sinnvoll, jedoch kann nicht von einem Konkurrenz-Produkt die Rede sein, vielmehr ist Maven als eine Art Erweiterung von Ant zu betrachten. Dies verdeutlicht sich dadurch, dass Maven sämtliche Tasks von Ant enthält. Zusätzlich wurden neue Konzepte eingebracht um ein Build-Tool zu entwickeln, das dem Softwareentwickler die Arbeit noch mehr erleichtert, als Ant dies ohnehin schon vollbringt. Zwar erfordert Ant weniger Einarbeitungszeit als Maven, aber aufgrund der Ähnlichkeit und des Konzeptes (die abstraktere Betrachtung des Build-Prozesses) ist davon auszugehen dass Apache Maven in der Zukunft das am meisten benutzte Build-Tool sein wird. Dies ist nicht zuletzt dadurch begründet, dass Softwareprojekte immer umfangreicher werden aber gleichzeitig ähnlich strukturiert sind. Gerade in diesen Fällen kann Maven mit den Plug-Ins die Lösung anbieten kann, die den entscheidenden Vorteil anbietet. 20 Literaturverzeichnis [AA08] The Apache Ant Project: Documentation, http://ant.apache.org/manual/index.html, Abruf: November 2008. [AM08] The Apache Maven Project: Documentation, http://maven.apache.org/guides/index.html, Abruf: November 2008 [ES06] Stefan Edlich, Jörg Staudemeyer: Ant kurz & gut, 2. Auflage, O'Reilly, 2006. [Fi04] Carten Fiedler: Ausarbeitung Build – Tools, http://www-wi.unimuenster.de/pi/lehre/ws0405/seminar/07BuildTools.pdf, Abruf: November 2008. [HL04] Erik Hatcher, Steve Loughran: Java-Entwicklung mit Ant, 1. Auflage, mitp, 2004. [Ma05] Bernd Matzke: Ant. Eine praktische Einführung in das Java-Build-Tool, 2. Auflage, dpunkt.verlag, 2005. [MS05] Martin Meintel, Jürgen Schmiing: Die Buildwerkzeuge Apache Ant und Maven, https://www.bahorb.de/fileadmin/media/it/studienprojekte/projektarbeiten/se_seminar_it20 03/se_seminar_it2003_09.pdf, 2004