Use a testing framework (JUnit)
Ant has these characteristics:
Every Java programmer should at least be familiar with Ant.
Using Ant, a build file is made up of tasks, which perform operations commonly needed for builds. The list of tasks is extensive:
<project name="test-ant-builds" default='all' basedir="." >
<description>
Demonstrate the use of the Ant build tool with a simple Java project.
</description>
<!--
First define properties, datatypes, and default tasks; then define targets.
Any Ant tasks placed outside of any target are always executed first.
-->
<!-- Override default property values with an external properties file, if present. -->
<property file='build.properties'/>
<!-- Default property values, if not overridden elsewhere: -->
<property name='build' location='build' />
<property name='app.version' value='1.0'/>
<property name='app.name' value='Example App'/>
<property name='distro-name' value='example-app-${app.version}'/>
<tstamp><format property='build.time' pattern='yyyy-MM-dd HH:mm:ss'/></tstamp>
<path id='compile.classpath'>
<fileset dir='lib'>
<include name='*.jar'/>
</fileset>
</path>
<!-- Simply extends the compile.classpath with your own compiled classes. -->
<path id='run.classpath'>
<path refid='compile.classpath'/>
<path location='src'/>
</path>
<fileset id='class.files' dir='src'>
<include name='**/*.class'/>
</fileset>
<fileset id='files.for.jar' dir='src'>
<exclude name='**/*.java'/>
<exclude name='**/doc-files/'/>
</fileset>
<fileset id='test.classes' dir='src'>
<include name='**/TEST*.java'/>
</fileset>
<!-- Text files using Ant's '@' syntax are here called template files. -->
<fileset id='template.files' dir='.'>
<include name='**/*_template.*'/>
</fileset>
<!-- Inspect the environment, to see if a deployment host is currently running. -->
<condition property='deployment.server.running' value='true' else='false'>
<socket port='8081' server='127.0.0.1' />
</condition>
<!-- A connection to this URL is used when building javadoc. -->
<condition property='jdk.javadoc.visible' value='true' else='false'>
<http url='http://java.sun.com/javase/6/docs/api/' />
</condition>
<echo>
Application: ${app.name} ${app.version}
Build File : ${ant.file}
Run Date : ${build.time}
Run by : ${user.name}
Build Dir : ${build}
Base Dir : ${basedir}
Java Home : ${java.home}
Deployment host running: ${deployment.server.running}
Connected to the web : ${jdk.javadoc.visible}
</echo>
<echo message='Create build directory, and its subdirectories.'/>
<mkdir dir="${build}/javadoc"/>
<mkdir dir="${build}/dist"/>
<mkdir dir="${build}/templates"/>
<!-- Now define the targets, which use the properties and datatypes defined above. -->
<target name='clean' description="Delete all build artifacts." >
<delete dir='${build}'/>
<delete>
<fileset refid='class.files'/>
</delete>
<mkdir dir="${build}/javadoc"/>
<mkdir dir="${build}/dist"/>
<mkdir dir="${build}/templates"/>
</target>
<target name='compile' description='Compile source files and place beside source.'>
<javac srcdir="src">
<classpath refid='compile.classpath'/>
</javac>
<!-- Here's a simple way of debugging a path, fileset, or patternset, using its refid: -->
<echo>Classpath: ${toString:compile.classpath}</echo>
</target>
<target name='test' description='Run all JUnit tests.' depends='compile'>
<junit haltonfailure='false'>
<classpath>
<pathelement location="src"/>
</classpath>
<batchtest>
<fileset refid='test.classes'/>
</batchtest>
<formatter type='brief' usefile='no'/>
</junit>
</target>
<target name='launch' description='Build and run the program.' depends='compile, test'>
<java classname='hirondelle.ante.Launcher' classpathref='run.classpath' failonerror='true'>
<arg value="Solar System"/>
</java>
</target>
<target name='jar' description='Create a jar file for distribution.' depends='compile'>
<jar destfile='${build}/dist/${distro-name}.jar' manifest='MANIFEST.MF' duplicate='preserve'>
<fileset refid='files.for.jar'/>
<!-- The static manifest.mf file is merged with additional dynamic items, specified here : -->
<manifest>
<attribute name='Specification-Version' value='${app.version}'/>
<attribute name='Specification-Title' value='${app.name}' />
<attribute name='Implementation-Version' value='${app.version}'/>
<attribute name='Implementation-Title' value='${app.name}' />
</manifest>
</jar>
</target>
<target name='javadoc' description='Generate javadoc.' >
<javadoc
use='true' author='true' version='true'
overview='overview.html'
access='package'
sourcepath='src'
packagenames='*.*'
destdir='${build}/javadoc'
windowtitle='${app.name} ${app.version}'
noqualifier='java.*:javax.*:com.sun.*'
linksource='true'
>
<classpath refid='compile.classpath'/>
<link href='http://java.sun.com/javase/6/docs/api/'/>
<header><![CDATA[<h1>${app.name} ${app.version}</h1>]]></header>
</javadoc>
</target>
<target name='text-templates' description='Process template files, and assign values to @ variables.'>
<copy overwrite='true' todir='${build}/templates'>
<fileset refid='template.files'/>
<!-- New files have 'template' removed from their name : -->
<globmapper from='*_template.txt' to='*.txt'/>
<filterset>
<filter token='app.name' value='${app.name}'/>
<filter token='app.version' value='${app.version}'/>
<filter token='build.time' value='${build.time}'/>
</filterset>
</copy>
</target>
<target name='distro-binary' description='Create zip file with executable jar, docs.' depends='jar, javadoc, text-templates'>
<zip destfile='${build}/dist/${distro-name}-binary.zip' duplicate='preserve'>
<zipfileset dir='${build}/dist/' includes='${distro-name}.jar'/>
<zipfileset dir='${build}/javadoc' prefix='javadoc' />
<zipfileset dir='${build}/templates' includes='README.txt'/>
</zip>
</target>
<target name='distro-source' description='Create zip file with project source code.'>
<zip destfile='${build}/dist/${distro-name}-src.zip' duplicate='preserve' >
<!-- exclude items specific to the author's IDE setup: -->
<zipfileset dir='.' excludes='.classpath, .project'/>
</zip>
</target>
<!-- Add mail.jar and activation.jar to your ANT_HOME/lib! -->
<!-- Please edit, using values appropriate to your environment. -->
<target name='email' >
<mail mailhost='smtp.blah.com' mailport='25' user='blah@blah.com'
password='blah' messageMimeType='text/html'
tolist='blah@whatever.com' from='blah@blah.com' subject='Build completed.'
>
<message>
<![CDATA[ Test email. <P><a href='http://www.google.com'>link</a> ]]>
</message>
</mail>
</target>
<target name='all' description='Create all build artifacts.'
depends='clean, compile, test, jar, javadoc, distro-binary, distro-source'>
<echo>Finished creating all build artifacts.</echo>
</target>
</project>
Example of running the above build script:
C:\\johanley\\Projects\\ant-test>ant -file build.xml all
Buildfile: build.xml
[echo]
[echo] Application: Example Appl 1.1
[echo] Build File : C:\\johanley\\Projects\\ant-test\\build.xml
[echo] Run Date : 2010-07-21 19:14:11
[echo] Run by : John
[echo] Build Dir : C:\\@build
[echo] Base Dir : C:\\johanley\\Projects\\ant-test
[echo] Java Home : C:\\jdk1.5.0\\jre
[echo] Deployment host running: true
[echo] Connected to the web : true
[echo]
[echo] Create build directory, and its subdirectories.
[mkdir] Created dir: C:\\@build\\javadoc
[mkdir] Created dir: C:\\@build\\dist
[mkdir] Created dir: C:\\@build\\templates
clean:
[delete] Deleting directory C:\\@build
[delete] Deleting 3 files from C:\\johanley\\Projects\\ant-test\\src
[mkdir] Created dir: C:\\@build\\javadoc
[mkdir] Created dir: C:\\@build\\dist
[mkdir] Created dir: C:\\@build\\templates
compile:
[javac] Compiling 5 source files
[echo] Classpath: C:\\johanley\\Projects\\ant-test\\lib\\junit.jar
test:
[junit] Testsuite: hirondelle.ante.TESTLauncher
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0 sec
jar:
[jar] Building jar: C:\\@build\\dist\\example-app-1.1.jar
javadoc:
[javadoc] Generating Javadoc
[javadoc] Javadoc execution
[javadoc] Loading source files for package hirondelle.ante...
[javadoc] Loading source files for package hirondelle.ante.deluvian...
[javadoc] Constructing Javadoc information...
[javadoc] Standard Doclet version 1.5.0_07
[javadoc] Building tree for all the packages and classes...
[javadoc] Generating C:\\@build\\javadoc\\hirondelle/ante/\\package-summary.html...
[javadoc] Copying file C:\\johanley\\Projects\\ant-test\\src\\hirondelle\\ante\\doc-files\\VersionHistory.html
to directory C:\\@build\\javadoc\\hirondelle\\ante\\doc-files...
[javadoc] Building index for all the packages and classes...
[javadoc] Building index for all classes...
text-templates:
[copy] Copying 1 file to C:\\@build\\templates
distro-binary:
[zip] Building zip: C:\\@build\\dist\\example-app-1.1-binary.zip
distro-source:
[zip] Building zip: C:\\@build\\dist\\example-app-1.1-src.zip
all:
[echo] Finished creating all build artifacts.
BUILD SUCCESSFUL
Total time: 6 seconds
(<javac>, for example), and inspect file timestamp information.
on/true/yes means true, and all other values are false.
PATH and CLASSPATH
excludes override includes
<defaultexcludes> task controls the list of default excludes
<property> tasks
<property> task
ANT_OPTS environment variable
ant -Dx=y, or ant -propertfile blah.properties. This style can never be overidden by other settings.
user.name, user.home, etc.)
ant.project.name
ant.file
ant.home
ant.java.version
ant.version
basedir
${xyz} syntax when used with <property>, but NOT when used with -propertyfile on the Ant command line.
<property name='x' value='y'> since the location attribute isn't used, this isn't
recommended for files and directories, since this will not resolve relative references.
If you do specify a location in a properties file, then it should be absolute, not relative. In addition, you'll
need to escape backslashes.
# example properties file
app.version = 1.0
# This style also works, and it's not sensitive to order
# of appearance in this file
# Thus, the contents of this file is manipulated somewhat
# after being loaded.
# This does NOT work when using 'ant -propertyfile'
app.name = My Wonderful App ${app.version}
# you need to escape backslashes
build.dir = C:\\\\@build
ant -Dx=y, or ant -propertfile blah.properties.
ant -propertyfile blah.properties doesn't resolve ${xyz} style references within properties files.
ant -projecthelp lists all targets having a description. It also tests the general syntax of your build file.
@ placeholder, ensure overwrite='yes'.
fork='true' can often fix problems.
like-this
location attribute, not value
antcall; to specify order, use the order of dependencies instead
<property file='build.properties'> in your build file, to let users easily override values.
The build file must work without the build.properties file being present.
<defaultexcludes> task; you
should usually only extend the default file types.
<property environment='env'/> to force ant properties and system properties into different namespaces.
$CVSIGNORE environment variable, or place a .cvsignore file in their home directory.
duplicate='preserve' is usually desirable.