Ant ist ein Build-Werkzeug aus der Java-Welt, das auch für Python Projekte verwendbar ist. Diese Präsentation zeigt Beispiele für häufige Aufgaben und beschreibt, wie eine Einbindung in Jenkins zur continuous integration erfolgeb kann.
2. Agenda
● Was ist ant?
● Grundkonzepte und allgemeine Verwendung.
● Konkrete Beispiele für Python.
● Ausgewählte Features von ant.
3. Was ist ant?
● Ant ist ein Build-Tool.
● Ursprung in der Java-Welt.
● Bewährt seit 2000.
● Einfache Einbindung in Jenkins.
● Auch für Python-Projekte verwendbar als
Ergänzung zu distutils / setup.py.
● Sehr gutes Handbuch mit vielen Beispielen.
4. Vergleich mit anderen Build-Tools
● Oft kompakter als distutils / setup.py. → Standard-
Aufgaben und leistungsfähige Dateimuster statt
komplexe shutils-Aufrufe.
● Weiter verbreitet als Scons.
http://www.scons.org/
● Robuster als Shell-Scripts → Abbruch bei Fehlern.
● Deterministischeres Verhalten als Make.
http://en.wikipedia.org/wiki/Make_(software)
● Einfacher zu verwenden als Maven.
http://maven.apache.org/
5. Grundlagen zu ant
● Build.xml beschreibt Projekt.
● Projekt besteht aus Zielen („targets“).
● Ziele führen Aufgaben („tasks“) aus und erstellen Dateien.
● Ziele können von anderen Zielen abhängig sein.
● Aufgaben sind i.d.R. auf mehrere Dateien anwendbar –
ausgewählt mit leistungsfähigen Dateimustern.
● Eigenschaften („properties“) sind verwendbar als Variablen
oder Konstante. Allerdings kaum Funktionen für String-
Manipulation oder mathematische Berechnungen.
● Einfache Makros zum parameterisierten Aufruf von
mehreren Aufgaben.
6. Beispiel für build.xml
<project name="hello" default="build" basedir=".">
Setzt Eigenschaft
<description>Say hello.</description> „greeting“ auf „Hello“
<property name="greeting" value="Hello" /> Setzt Präfix für Zugriff auf
<property environment="env" /> Umgebungsvariablen.
<target name="build" depends="hello"> Definiert Ziel „build“ mit
<!-- Do nothing. --> Abhängigkeit zu Ziel „hello“
</target>
Definiert Ziel „hello“ zur
<target name="hello"> Ausgabe einer Begrüßung.
<echo message="${greeting} ${env.USER}! How are you?" />
</target>
</project>
7. Aufruf und Ausgabe
$ ant
Buildfile: /Users/someone/hello/build.xml
Bearbeitung von
Ziel „hello“
hello:
[echo] Hello someone! How are you?
Bearbeitung von
Ziel „build“
build:
BUILD SUCCESSFUL
Total time: 0 seconds
8. Beispiel-Ziele
● PEP8 Style-Prüfung.
● Anzahl der Quellcode-Zeilen.
● Tests inklusive Testabdeckung.
● Aufrufe von setup.py.
Quelle für vollständiges build.xml:
http://sourceforge.net/apps/trac/cutplace/browser/t
runk/build.xml
10. Anzahl der Quellcode-Zeilen
<target name="sloccount" description="build sloccount report">
<echo message="build sloccount report" />
<exec executable="sloccount" failonerror="true">
<arg value="--details" />
<arg value="--wide" />
Download über Package Manager oder
http://www.dwheeler.com/sloccount/
<arg value="cutplace" />
<redirector output="sloccount.sc">
<outputfilterchain> Entfernt Zeilen mit „.svn“,
<linecontains negate="true"> um interne Kopie von
<contains value=".svn" />
Subversion nicht mit
zu zählen.
</linecontains>
</outputfilterchain>
</redirector>
</exec>
</target>
11. Tests inklusive Testabdeckung (1/2)
● Unter Verwendung von nose und coverage.
http://pypi.python.org/pypi/nose/
http://pypi.python.org/pypi/coverage/
● Ausgabe von nose im Format von JUnit.
● Ausgabe von coverage im Format von
Cobertura.
12. Tests inklusive Testabdeckung (2/2)
<target name="test" depends="testdata" description="run test suite">
<exec executable="nosetests" failonerror="false">
<arg value="--with-coverage" />
<arg value="--with-doctest" />
<arg value="--with-xunit" /> Nach fehlgeschlagenen Tests
<arg value="--cover-erase" /> den Build fortsetzen und
Jenkins-Berichte erzeugen.
<arg value="--exclude" />
<arg value="(.*setup.*)|(.*test_performance.*)" />
</exec>
<exec executable="coverage" failonerror="true">
<arg value="xml" />
</exec>
Keine Testabdeckung für
</target>
setup.py („Test“ im Rahmen
des builds) und des
Performance-Test (erfolgt
mit eigenem Ziel).
17. Plugins, Muster, Filter
<taskdef classname="org.acm.seguin.ant.Pretty"
classpath="lib/pretty.jar;lib/JavaStyle.jar" Import einer
externen Aufgabe
name="pretty"/>
<target depends="init" description="reformat java source code"
name="reformat-java"> Aufruf der
importierten
<pretty settingsDir="${settings.dir}">
Aufgabe Dateien, auf die
<fileset dir="${source.dir}"> Aufgabe an zu
wenden ist.
<include name="**/*.java"/>
<not><contains text="/*@"/></not>
</fileset> „**“ = alle Ordner und
enthaltene Unterordner
</pretty>
</target>
18. Zusammenfassung
● Bewährtes Werkzeug aus der Java-Welt.
● Vergleichsweise einfach und deterministisch.
● Viele fertige Aufgaben (Tasks).
● Einfache Einbindung von Python-Projekten in
Jenkins.