I am trying to get a simple(?) test project working with Ant, Ivy and JUnit. The basic idea is that Ivy will download junit.jar and then Ant will use it.
Note that the junit jar is on the classpath because otherwise (without the classpath
element in the junit task) I see "The <classpath> for <junit> must include junit.jar if not in Ant's own classpath". Also, the class given below (junit.framework.TestListener) is in junit-4.8.2.jar.
However, when I try ant test
on the following I see:
test:
BUILD FAILED
/home/andrew/project/guice/hg/build.xml:33: java.lang.NoClassDefFoundError: junit/framework/TestListener
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
...
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)
Caused by: java.lang.ClassNotFoundException: junit.framework.TestListener
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
...
So I guess something is wrong with my build.xml? What?
Here is the build.xml:
<project xmlns:ivy="antlib:org.apache.ivy.ant"
name="java-example" default="dist" basedir=".">
<description>
simple example build file
</description>
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="lib" location="lib"/>
<path id="lib.path">
<fileset dir="${lib}"/>
</path>
<target name="init">
<tstamp/>
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init,resolve"
description="compile the source">
<javac srcdir="${src}" destdir="${build}" classpathref="lib.path"
includeantruntime="false">
<compilerarg value="-Xlint"/>
</javac>
</target>
<target name="test" depends="compile"
description="run the tests">
<junit>
<classpath refid="lib.path"/>
<batchtest>
<fileset dir="${build}">
<include name="**/*Test.class"/>
</fileset>
</batchtest>
</junit>
</target>
<target name="dist" depends="compile"
description="generate the distribution">
<mkdir dir="${dist}/lib"/>
<jar jarfile="${dist}/lib/example-${DSTAMP}.jar" basedir="${build}"/>
</target>
<target name="clean"
description="clean up">
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
<target name="resolve"
description="download required dependencies">
<ivy:retrieve/>
</target>
</project>
and the existing directory structure after compilation:
.
├── build
│ └── com
│ └── isti
│ └── example
│ ├── AppendToList.class
│ ├── DumpToStdout.class
│ ├── LimitedCounter.class
│ ├── MessageSink.class
│ ├── MessageSource.class
│ └── SinkToSourceTest.class
├── build.xml
├── dist
│ └── lib
│ └── example-20130412.jar
├── ivy.xml
├── lib
│ ├── junit-4.8.2.jar
│ ├── junit-4.8.2-javadoc.jar
│ └── junit-4.8.2-sources.jar
├── README.md
└── src
├── main
│ └── java
│ └── com
│ └── isti
│ └── example
│ ├── AppendToList.java
│ ├── DumpToStdout.java
│ ├── LimitedCounter.java
│ ├── MessageSink.java
│ └── MessageSource.java
└── test
└── java
└── com
└── isti
└── example
└── SinkToSourceTest.java
Update Incidentally, ant -lib lib test
(explicitly giving the lib directory) works. And there are lots of confused descriptions of the handling of this in random web search results – but my impression is that the approach above is consistent with the latest docs (I am using ant 1.9) – see point 5. So I am thinking this may be a bug; bug.
Best Answer
Example
Project contains the following files:
Build runs as follows:
ivy.xml
A very powerful feature of ivy is configurations. These allow you to group dependencies together.
Notes:
build.xml
Ivy configurations can be leveraged by tasks like cachepath (to create an ANT path) and retrieve (copy files into your build). I also recommend using the report target so that you can see which jars appear in each configuration (Useful to managing transitive dependencies)
Note:
App.java
Hello world logging example.
AppTest.java
This is an old example from my archives. Not using the Junit assertions.
log4j.properties