Ant and JUnit

In this Ant tutorial installment, we’ll take a look at the JUnit task in ant. The JUnit task is moderately complex, so you’ll definitely want to read the Ant manual. I would also recommend taking a look at Java Development with Ant by Erik Hatcher and Steve Loughran (this link will allow you to download Chapter 4: Testing with JUnit). to complete your installation of JUnit. Finally, this example was developed using version 1.5.1 of Ant and version 3.8.1 of JUnit.

We’ll start with the test class shown below. For simplicity, we’ll use a test case that always succeeds and doesn’t really test anything. We’ll take a closer look at writing JUnit test cases later. For now we’ll just say that a JUnit test case extends the junit.framework.TestCase class. Please create this file in a sub-directory named test (or change the value of the build file tst-dir property to suit).

1
2
3
4
5
6
7
import junit.framework.*;
public class TestExample extends TestCase {
public void testOne()
{
assertTrue( "TestExample", true );
}
}

And here is the build.xml file that we’ll be using. Please modify this build file to reflect the location of junit.jar on your system. In addition, you must add junit.jar to your CLASSPATH or copy junit.jar to your Ant library from your JUnit library to enable the integration of JUnit and Ant.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<project default="all">
<property name="tst-dir" location="test" />
<property name="TALK" value="true" />
<path id="classpath.base">
</path>
<path id="classpath.test">
<pathelement location="/Projects/Java/Lib/junit.jar" />
<pathelement location="${tst-dir}" />
<path refid="classpath.base" />
</path>
<target name="compile-test">
<javac srcdir="${tst-dir}"
verbose="${TALK}"
>
<classpath refid="classpath.test"/>
</javac>
</target>
<target name="clean-compile-test">
<delete verbose="${TALK}">
<fileset dir="${tst-dir}" includes="**/*.class" />
</delete>
</target>
<target name="test" depends="compile-test">
<junit>
<classpath refid="classpath.test" />
<formatter type="brief" usefile="false" />
<test name="TestExample" />
</junit>
</target>
<target name="all" depends="test" />
<target name="clean" depends="clean-compile-test" />
</project>

There are three primary differences between this build.xml file and the ones used previously:

  1. Addition of the TALK property. We’ll use this as a flag to the verbose attribute of various tasks. Our example below will demonstrate the effect of the verbose attribute for the delete and the javac tasks. Note that we assign the property with the value attribute since this is not a file system location. This is different from the ant -verbose option. Setting verbose=true on a task causes that task to be more informative about it’s behavior. Passing the -verbose option to ant causes ant to be more informative about ant’s behavior.

  2. Explicit declaration of the Java Classpath. In this case we define a base classpath and then we define the test classpath relative to it. If we were actually testing a real class, then the base classpath would be used to compile that class. The test classpath adds the location of the JUnit tests and the JUnit jar file to the base classpath.

  3. The JUnit task. There are three nested elements to our JUnit task:

    1. The java classpath.
    2. The formatter, which controls the output from the task.
    3. The name, which defines a single test class to be run.

We can now execute our test as shown below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
$ ant -DTALK=false clean
Buildfile: build.xml
clean-compile-test:
[delete] Deleting 1 files from /Tutorial/Ant/Junit/test
clean:
BUILD SUCCESSFUL
Total time: 2 seconds
$ ant -DTALK=false
Buildfile: build.xml
compile-test:
[javac] Compiling 1 source file
test:
[junit] Testsuite: TestExample
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.007 sec
all:
BUILD SUCCESSFUL
Total time: 4 seconds
$ ant clean
Buildfile: build.xml
clean-compile-test:
[delete] Deleting 1 files from /Tutorial/Ant/Junit/test
[delete] Deleting /Tutorial/Ant/Junit/test/TestExample.class
clean:
BUILD SUCCESSFUL
Total time: 2 seconds
$ ant
Buildfile: build.xml
compile-test:
[javac] Compiling 1 source file
[javac] [parsing started /Tutorial/Ant/Junit/test/TestExample.java]
[javac] [parsing completed 81ms]
[javac] [loading /Projects/Java/Lib/junit.jar(junit/framework/TestCase.class)]
[javac] [checking TestExample]
[javac] [loading /Projects/Java/Lib/junit.jar(junit/framework/Assert.class)]
[javac] [loading /System/Library/.../1.3.1/Classes/classes.jar(java/lang/Object.class)]
[javac] [loading /Projects/Java/Lib/junit.jar(junit/framework/Test.class)]
[javac] [loading /System/Library/.../1.3.1/Classes/classes.jar(java/lang/String.class)]
[javac] [wrote /Tutorial/Ant/Junit/test/TestExample.class]
[javac] [total 866ms]
test:
[junit] Testsuite: TestExample
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.005 sec
all:
BUILD SUCCESSFUL
Total time: 4 seconds

Disclaimer: I don’t claim to be an expert on ant. Please send comments and corrections.