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