Conditional Execution in Ant

In this Ant tutorial installment, we’ll take a look at the conditional execution of targets. Let’s start with the simple Hello World build file from before. Modify the hello and goodbye targets to include the if and unless attributes as shown in bold.

1
2
3
4
5
6
7
8
9
10
11
<project default="all">
<target name="hello" if="hello.set">
<echo message="Hello, World"/>
</target>
<target name="goodbye" unless="hello.set">
<echo message="Goodbye, Cruel World"/>
</target>
<target name="all" depends="hello,goodbye" />
</project>

The if=”named.property” attribute causes a target to be executed if the named property is set. And the unless=”named.property” attribute causes a target to be executed unless the named property is set. If we execute the build file without specifying a value for the property “hello.set”, then the hello target will be skipped and the goodbye target will be executed. And specifying a value for the property “hello.set” yields the opposite result.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ ant
Buildfile: build.xml
hello:
goodbye:
[echo] Goodbye, Cruel World
all:
BUILD SUCCESSFUL
Total time: 2 seconds
$ ant -Dhello.set=true
Buildfile: build.xml
hello:
[echo] Hello, World
goodbye:
all:
BUILD SUCCESSFUL
Total time: 4 seconds

Of course, we could just specify the desired target on the command line and avoid all that. But let’s take a look at how we can use this to cleanup after a failed target. Start with the build file we used to run multiple JUnit test cases and split the original target “test” into three pieces: test-execute, test-failed, and test. Target “test-execute” will contain the JUnit task, target “test-failed” will contain the cleanup code and be conditional on if=”test.failure”, and target “test” will tie it all together. This will execute our clean up code if a test fails and skip the clean up code if all tests pass. Note that we could consolidate targets “test-failed” and “test” together at the cost of some clarity about the intent of each target.

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
<project default="all">
<property name="tst-dir" value="test" />
<property name="TALK" value="false" />
<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}"
debug="true"
>
<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-execute" depends="compile-test">
<junit failureProperty="test.failure">
<classpath refid="classpath.test" />
<formatter type="brief" usefile="false" />
<batchtest>
<fileset dir="${tst-dir}" includes="**/Test*.class" />
</batchtest>
</junit>
<fail message="test failed" if="test.failure" />
</target>
<target name="test-failed" depends="test-execute" if="test.failure">
<echo message="perform test cleanup" />
<fail message="test failed" />
</target>
<target name="test" depends="test-failed" />
<target name="all" depends="test" />
<target name="clean" depends="clean-compile-test" />
</project>

Execution with Test Failure

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
$ ant -f build.xml
Buildfile: build.xml
compile-test:
test-execute:
[junit] Testsuite: Test
[junit] Tests run: 1, Failures: 1, Errors: 0, Time elapsed: 0.035 sec
[junit] Testcase: test(Test): FAILED
[junit] Equality Test expected:<0> but was:<1>
[junit] junit.framework.AssertionFailedError: Equality Test expected:<0> but was:<1>
[junit] at Test.test(Test.java:7)
[junit] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[junit] at sun.reflect.NativeMethodAccessorImpl.invoke( ... .java:39)
[junit] at sun.reflect.DelegatingMethodAccessorImpl.invoke( ... .java:25)
[junit] TEST Test FAILED
[junit] Testsuite: TestExample
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.001 sec
test-failed:
[echo] perform test cleanup
BUILD FAILED
file:/Tutorial/Ant/Conditional/junit.xml:38: test failed
Total time: 3 seconds

Execution with Test Success

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ ant -f build.xml
Buildfile: build.xml
compile-test:
test-execute:
[junit] Testsuite: Test
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.026 sec
[junit] Testsuite: TestExample
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.001 sec
test-failed:
test:
all:
BUILD SUCCESSFUL
Total time: 4 seconds

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