    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Everyone Hates build.xml</title>
        <link>https://members.accu.org/index.php/articles/2020</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Overload Journal #123 - October 2014</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c342/">o123</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-342/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+342/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Everyone Hates build.xml</h1>
<p><strong>Author:</strong>&nbsp;Martin Moene</p>
<p>
<strong>Date:</strong> 05 October 2014 21:52:51 +01:00 or Sun, 05 October 2014 21:52:51 +01:00</p>
<p><strong>Summary:</strong>&nbsp;Using Ant build tool can be tricky. Andy Balaam shows how to structure and test the build code.

</p>
<p><strong>Body:</strong>&nbsp;<p>If youâ€™re starting a new Java project, Iâ€™d suggest considering the many alternatives to Ant, including Gant [<a href="#[Gant]">Gant</a>], Gradle [<a href="#[Gradle]">Gradle</a>], SCons [<a href="#[SCons]">SCons</a>] and, of course, Make [<a href="#[Make]">Make</a>]. This article covers how to bend Ant to work like a programming language, so you can write good code in it, and how to test that code.</p>

<p>Itâ€™s seriously worth considering a build tool that makes structured programming easier, but if youâ€™ve chosen Ant, or youâ€™re stuck with Ant, read on.</p>

<p>Most projects Iâ€™ve been involved with that use Ant have a hateful <span class="filename">build.xml</span> surrounded by fear. Many projectsâ€™ build files grow to enormous sizes, for example becoming responsible for deployment, system test execution, notifications and many other jobs.</p>

<p>The most important reason for the fear is that the functionality of the build file is not properly tested, so you never know whether youâ€™ve broken it, meaning you never make â€˜non-essentialâ€™ changes: changes that make it easier to use or read.</p>

<p>But, before we can write tests, we must address a pre-requisite:</p>

<p>Can you write good code in Ant, even if you arenâ€™t paralysed by fear?</p>

<h2>Everyone hates build.xml (code reuse in Ant)</h2>

<p>One of the most important aspects of good code is that you only need to express each concept once. Or, to put it another way, you can re-use code.</p>

<p>I want to share with you some of the things I have discovered recently about Ant, and how you should (and should not) re-use code.</p>

<p>But first:</p>

<h2>What is Ant?</h2>

<p>Ant is 2 languages:</p>

<ul>
	<li>A declarative language to describe dependencies</li>
	<li>A procedural language to proscribe actions</li>
</ul>

<p>In fact, itâ€™s just like a Makefile (ignore this if Makefiles arenâ€™t familiar). A Makefile rule consists of a target (the name before the colon) with its dependencies (the names after the colon), which make up a declarative description of the dependencies, and the commands (the things indented by tabs) which are a normal procedural description of what to do to build that target.</p>

<pre class="programlisting">
  # Ignore this if you don't care about Makefiles!
  target: dep1 dep2   # Declarative
      action1         # Procedural
      action2</pre>

<h3>The declarative language</h3>

<p>In Ant, the declarative language is a directed graph of targets and dependencies, shown graphically in Figure 1:</p>

<table class="sidebartable">
	<tr>
		<td><img src="http://accu.org/content/images/journals/ol123/Balaam/Balaam-01.svg" /></td>
	</tr>
	<tr>
		<td class="title">Figure 1</td>
	</tr>
</table>

<pre class="programlisting">
  &lt;target name=&quot;A&quot;/&gt;
  &lt;target name=&quot;B&quot; depends=&quot;A&quot;/&gt;
  &lt;target name=&quot;C&quot; depends=&quot;B&quot;/&gt;
  &lt;target name=&quot;D&quot; depends=&quot;A&quot;/&gt;</pre>

<p>This language describes a directed graph of dependencies. I.e. they say what depends on what, or what must be built before you can build something else. Targets and dependencies are completely separate from what lives inside them, which are tasks.</p>

<h3>The procedural language</h3>

<p>The procedural language is a list of tasks:</p>
<pre class="programlisting">
  &lt;target ...&gt;
      &lt;javac ...&gt;
      &lt;copy ...&gt;
      &lt;zip ...&gt;
      &lt;junit ...&gt;
  &lt;/target&gt;</pre>

<p>When the dependency mechanism has decided a target will be executed, its tasks are executed one by one in order, just like in a programming language. Except that tasks live inside targets, they are completely separate from them. Essentially each target has a little program inside it consisting of tasks, and these tasks are a conventional programming language, nothing special (except for the lack of basic looping and branching constructs).</p>

<p>Iâ€™m sorry if the above is glaringly obvious to you, but it only recently became clear to me, and it helped me a lot when thinking about how to improve my Ant files.</p>

<h2>Avoiding repeated code</h2>

<p>Imagine you have two similar Ant targets (see Listing 1).</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
&lt;target name=&quot;A&quot;&gt;
  &lt;javac
    srcdir=&quot;a/src&quot; destdir=&quot;a/bin&quot;
    classpath=&quot;myutil.jar&quot; debug=&quot;false&quot;
  /&gt;
&lt;/target&gt;

&lt;target name=&quot;B&quot;&gt;
  &lt;javac
    srcdir=&quot;b/code&quot; destdir=&quot;b/int&quot;
    classpath=&quot;myutil.jar&quot; debug=&quot;false&quot;
  /&gt;
&lt;/target&gt;
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<p>The <code>classpath</code> and <code>debug</code> information are the same in both targets, and we would like to write this information in one single place. Imagine with me that the code we want to share is too complex for it to be possible to store it as the values of properties in some properties file.</p>

<p>How do we share this code?</p>

<h3>The wrong way: antcall</h3>

<p>Listing 2 shows the solution we were using in my project until I discovered the right way.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
&lt;target name=&quot;compile&quot;&gt;
  &lt;javac
    srcdir=&quot;${srcdir}&quot; destdir=&quot;${destdir}&quot;
    classpath=&quot;myutil.jar&quot; debug=&quot;false&quot;
  /&gt;
&lt;/target&gt;

&lt;target name=&quot;A&quot;&gt;
  &lt;antcall target=&quot;compile&quot;&gt;
    &lt;param name=&quot;srcdir&quot; value=&quot;a/src&quot;/&gt;
    &lt;param name=&quot;destdir&quot; value=&quot;a/bin&quot;/&gt;
  &lt;/antcall&gt;
&lt;/target&gt;

&lt;target name=&quot;B&quot;&gt;
  &lt;antcall target=&quot;compile&quot;&gt;
  ...
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 2</td>
	</tr>
</table>

<p>Here we put the shared code into a target called <code>compile</code>, which makes use of properties to access the varying information (or the parameters, if we think of this as a function). The targets <code>A</code> and <code>B</code> use the <code>&lt;antcall&gt;</code> task to launch the compile target, setting the values of the relevant properties.</p>

<p>This works, so why is it wrong?</p>

<h3>Why not antcall?</h3>

<p><code>antcall</code> launches a whole new Ant process and runs the supplied target within that. This is wrong because it subverts the way Ant is supposed to work. The new process will re-calculate all the dependencies in the project (even if our target doesnâ€™t depend on anything) which could be slow. Any dependencies of the compile target will be run even if theyâ€™ve already been run, meaning some of your assumptions about order of running could be incorrect, and the assumption that each target will only run once will be violated. Whatâ€™s more, it subverts the Ant concept that properties are immutable, and remain set once youâ€™ve set them: in the example above, <code>srcdir</code> and <code>destdir</code> will have different values at different times (because they exist inside different Ant processes).</p>

<p>Basically what weâ€™re doing here is breaking all of Antâ€™s paradigms to force it to do what we want. Before Ant 1.6 you could have considered it a necessary evil. Now, itâ€™s just evil.</p>

<h3>The horrific way: custom tasks</h3>

<p>Ant allows you to write your own tasks (not targets) in Java. So our example would look something like Listing 3 (Java) and Listing 4 (Ant).</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
// ... imports here ...
public class MyCompile extends Task {
  String srcdir;
  public void setSrcDir(String s) {
    srcdir = s;
  }
  String destdir;
  public void setDestDir(String d) {
    destdir = d;
  }
  public void execute() throws BuildException
  {
    Project p = getProject();
    Javac javac = new Javac();
    javac.setSrcdir( new Path( p, srcdir ) );
    javac.setDestdir( new File( destdir ) );
    javac.setClasspath( new Path( p,
                                  &quot;myutil.jar&quot; ) );
    javac.setDebug( false );
    javac.execute();
  }
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 3</td>
	</tr>
</table>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
&lt;target name=&quot;first&quot;&gt;
  &lt;javac srcdir=&quot;mycompile&quot;/&gt;
  &lt;taskdef name=&quot;mycompile&quot; classname=&quot;MyCompile&quot;
    classpath=&quot;mycompile&quot;/&gt;
&lt;/target&gt;

&lt;target name=&quot;A&quot; depends=&quot;first&quot;&gt;
  &lt;mycompile srcdir=&quot;a/src&quot; destdir=&quot;a/bin&quot;/&gt;
&lt;/target&gt;

&lt;target name=&quot;B&quot; depends=&quot;first&quot;&gt;
  &lt;mycompile srcdir=&quot;b/code&quot; destdir=&quot;b/int&quot;/&gt;
&lt;/target&gt;
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 4</td>
	</tr>
</table>
<p>Here we write the shared code as a Java task, then call that task from inside targets <code>A</code> and <code>B</code>. The only word to describe this approach is â€˜cumbersomeâ€™. Not only do we need to ensure our code gets compiled before we try to use it, and add a <code>taskdef</code> to allow Ant to see our new task (meaning every target gets a new dependency on the â€˜firstâ€™ target), but much worse, our re-used code has to be written in Java, rather than the Ant syntax weâ€™re using for everything else. At this point you might start asking yourself why youâ€™re using Ant at all â€“ my thoughts start drifting towards writing my own build scripts in Java ... anyway, Iâ€™m sure that would be a very bad idea.</p>

<h3>The relatively OK way: macrodef</h3>

<p>So, enough teasing. Listing 5 shows the Right Way.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
&lt;macrodef name=&quot;mycompile&quot;&gt;
  &lt;attribute name=&quot;srcdir&quot;/&gt;
  &lt;attribute name=&quot;destdir&quot;/&gt;
  &lt;sequential&gt;
    &lt;javac
      srcdir=&quot;@{srcdir}&quot; destdir=&quot;@{destdir}&quot;
      classpath=&quot;myutil.jar&quot; debug=&quot;false&quot;
    /&gt;
  &lt;/sequential&gt;
&lt;/macrodef&gt;

&lt;target name=&quot;A&quot;&gt;
  &lt;mycompile srcdir=&quot;a/src&quot; destdir=&quot;a/bin&quot;/&gt;
&lt;/target&gt;

&lt;target name=&quot;B&quot;&gt;
  &lt;mycompile srcdir=&quot;b/code&quot; destdir=&quot;b/int&quot;/&gt;
&lt;/target&gt;
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 5</td>
	</tr>
</table>

<p>Since Ant 1.6, we have the <code>macrodef</code> task, which allows us to write our own tasks in Ant syntax. In any other language these would be called functions, with arguments which Ant calls attributes. You use these attributes by giving their name wrapped in a <code>@{}</code> rather than the normal <code>${}</code> for properties. The body of the function lives inside a sequential tag.</p>

<p>This allows us to write re-usable tasks within Ant. But what about re-using parts from the other language â€“ the declarative targets and dependencies?</p>

<h2>Avoiding repeated dependencies?</h2>

<p>Imagine we have a build file containing targets like this:</p>
<pre class="programlisting">
  &lt;target name=&quot;everyoneneedsme&quot;...
  &lt;target name=&quot;A&quot; depends=&quot;everyoneneedsme&quot;...
  &lt;target name=&quot;B&quot; depends=&quot;everyoneneedsme&quot;...
  &lt;target name=&quot;C&quot; depends=&quot;everyoneneedsme&quot;...
  &lt;target name=&quot;D&quot; depends=&quot;everyoneneedsme&quot;...</pre>

<p>In Ant, I donâ€™t know how to share this. The best I can do is make a single target that is re-used whenever I want the same long list of dependencies, but in a situation like this where everything needs to depend on something, I donâ€™t know what to do. (Except, of course, drop to the Nuclear Option of the <code>&lt;script&gt;</code> tag, which weâ€™ll see later.)</p>

<p>I havenâ€™t used it in anger, but this kind of thing seems pretty straightforward with Gradle. I believe Listing 6 is roughly equivalent to my example above, but I hope someone will correct me if I get it wrong.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
task everyoneneedsme

tasks.whenTaskAdded { task -&gt;
    task.dependsOn everyoneneedsme
}
task A
task B
task C
task D
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 6</td>
	</tr>
</table>

<p>(Disclaimer: I havenâ€™t run this.)</p>

<p>So, if you want nice features in your build tool, like code-reuse and testability, you should consider a build tool that is integrated into a grown-up programming language where all this stuff comes for free. But, if youâ€™re stuck with Ant, you should not despair: basic good practice is possible if you make the effort.</p>

<h2>Everyone loves build.xml (test-driven Ant)</h2>

<p>Of course, if youâ€™re going to have any confidence in your build file youâ€™re going to need to test it. Now weâ€™ve learnt some basic Ant techniques, weâ€™re ready to do the necessary magic that allows us to write tests.</p>

<p>First, let me clear up what weâ€™re testing:</p>

<h3>What do we want to test?</h3>

<p>Weâ€™re not testing our Java code. We know how to do that, and to run tests, if weâ€™ve written them using JUnit [<a href="#[JUnit]">JUnit</a>], just needs a <code>&lt;junit&gt;</code> tag in our <span class="filename">build.xml</span>. (Other testing frameworks are available and some people say theyâ€™re better.)</p>

<p>The things we want to test are:</p>

<ul>
	<li><strong>build artifacts</strong> â€“ the â€˜outputâ€™ of our builds i.e. JAR files, zips and things created when we run the build,</li>

	<li><strong>build logic</strong> â€“ such as whether dependencies are correct, whether the build succeeds or fails under certain conditions, and</li>

	<li><strong>units of code</strong> â€“ checking whether individual macros or code snippets are correct.</li>
</ul>

<p>Note, if youâ€™re familiar with the terminology, that testing build artifacts can never be a â€˜unit testâ€™, since it involves creating real files on the disk and running the real build.</p>

<p>Below weâ€™ll see how I found ways to test build artifacts, and some ideas I had to do the other two, but certainly not a comprehensive solution. Your contributions are welcome.</p>

<p>Before we start, letâ€™s see how Iâ€™m laying out my code:</p>

<h3>Code layout</h3>
<pre class="programlisting">
build.xml      - real build file
asserts.xml    - support code for tests
test-build.xml - actual tests</pre>

<p>I have a normal build file called <span class="filename">build.xml</span>, a file containing support code for the tests (mostly macros allowing us to make assertions) called <span class="filename">asserts.xml</span>, and a file containing the actual tests called <span class="filename">test-build.xml</span>.</p>

<p>To run the tests I invoke Ant like this:</p>
<pre class="programlisting">
  ant -f test-build.xml test-name</pre>

<p><span class="filename">test-build.xml</span> uses an <code>include</code> to get the assertions:</p>
<pre class="programlisting">
  &lt;include file=&quot;asserts.xml&quot;/&gt;</pre>

<p>Tests call a target inside <span class="filename">build.xml</span> using subant, then use the code in <span class="filename">asserts.xml</span> to make assertions about what happened.</p>

<h3>Simple example: code got compiled</h3>

<p>If we want to check that a <code>&lt;javac ...&gt;</code> task worked, we can just check that a <span class="filename">.class</span> file was created. Hereâ€™s the test, in <span class="filename">test-build.xml</span>:</p>
<pre class="programlisting">
  &lt;target name=&quot;test-class-file-created&quot;&gt;
    &lt;assert-target-creates-file
      target=&quot;build&quot;
      file=&quot;bin/my/package/ExampleFile.class&quot;
    /&gt;
  &lt;/target&gt;</pre>

<p>We run it like this:</p>
<pre class="programlisting">
  ant -f test-build.xml test-class-file-created</pre>

<p>The <code>assert-target-creates-file</code> assertion is a <code>macrodef</code> in <span class="filename">asserts.xml</span> like this:</p>
<pre class="programlisting">
  &lt;macrodef name=&quot;assert-target-creates-file&quot;&gt;
    &lt;attribute name=&quot;target&quot;/&gt;
    &lt;attribute name=&quot;file&quot;/&gt;
    &lt;sequential&gt;
      &lt;delete file=&quot;@{file}&quot; quiet=&quot;true&quot;/&gt;
      &lt;subant antfile=&quot;build.xml&quot; buildpath=&quot;.&quot;
              target=&quot;@{target}&quot;/&gt;
      &lt;assert-file-exists file=&quot;@{file}&quot;/&gt;
    &lt;/sequential&gt;
  &lt;/macrodef&gt;</pre>

<p>It just deletes a file (if it exists), runs the target using <code>subant</code>, then asserts that the file exists, which uses the <code>macrodef</code> in Listing 7.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
&lt;macrodef name=&quot;assert-file-exists&quot;&gt;
  &lt;attribute name=&quot;file&quot;/&gt;
  &lt;sequential&gt;
    &lt;echo message=
       &quot;Checking existence of file: @{file}&quot;/&gt;
    &lt;fail message=
       &quot;File '@{file}' does not exist.&quot;&gt;
      &lt;condition&gt;
        &lt;not&gt;&lt;available file=&quot;@{file}&quot;/&gt;&lt;/not&gt;
      &lt;/condition&gt;
    &lt;/fail&gt;
  &lt;/sequential&gt;
&lt;/macrodef&gt;
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 7</td>
	</tr>
</table>

<p>This uses a trick Iâ€™ve used a lot, which is the <code>fail</code> task, with a condition inside it, meaning that we only fail if the condition is satisfied. Here we use <code>not available</code> which means fail if the file doesnâ€™t exist.</p>

<h3>Harder example: JAR file</h3>

<p>Now letâ€™s check that a JAR file was created, and has the right contents. Listing 8 is the test.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
&lt;target name=&quot;test-jar-created-with-manifest&quot;&gt;
  &lt;assert-target-creates-file
    target=&quot;build&quot;
    file=&quot;dist/MyProduct.jar&quot;
  /&gt;
  &lt;assert-file-in-jar-contains
    jarfile=&quot;dist/MyProduct.jar&quot;
    filename=&quot;MANIFEST.MF&quot;
    find=&quot;Main-Class: my.package.MyMain&quot;
  /&gt;
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 8</td>
	</tr>
</table>

<p>This just says after weâ€™ve run the target, the file <span class="filename">MyProduct.jar</span> exists, and it contains a file called <span class="filename">MANIFEST.MF</span> that has the right <code>Main-Class</code> information in it. </p>

<p><code>assert-file-in-jar-contains</code> looks like Listing 9, which basically unzips the JAR into a directory, then searches the directory using fileset for a file with the right name and contents, and fails if itâ€™s not found (i.e. if the resourcecount of the fileset is zero). These are the kinds of backflips you need to do to bend Ant to your will.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
&lt;macrodef name=&quot;assert-file-in-jar-contains&quot;&gt;
  &lt;attribute name=&quot;jarfile&quot;/&gt;
  &lt;attribute name=&quot;filename&quot;/&gt;
  &lt;attribute name=&quot;find&quot;/&gt;
  &lt;sequential&gt;
    &lt;!-- ... insert checks that jar exists, and
     contains file --&gt;
    &lt;delete dir=&quot;${tmpdir}/unzip&quot;/&gt;
    &lt;unzip src=&quot;@{jarfile}&quot;
           dest=&quot;${tmpdir}/unzip&quot;/&gt;
    &lt;fail message=&quot;@{jarfile}:@{filename} should
          contain @{find}&quot;&gt;
      &lt;condition&gt;
        &lt;resourcecount when=&quot;equal&quot; count=&quot;0&quot;&gt;
          &lt;fileset dir=&quot;${tmpdir}/unzip&quot;&gt;
            &lt;and&gt;
              &lt;filename name=&quot;**/@{filename}&quot;/&gt;
              &lt;contains text=&quot;@{find}&quot;/&gt;
            &lt;/and&gt;
          &lt;/fileset&gt;
        &lt;/resourcecount&gt;
      &lt;/condition&gt;
    &lt;/fail&gt;
    &lt;delete dir=&quot;${tmpdir}/unzip&quot;/&gt;
  &lt;/sequential&gt;
&lt;/macrodef&gt;
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 9</td>
	</tr>
</table>

<p>Or, you can choose the Nuclear Option.</p>

<h3>The Nuclear Option</h3>

<p>If ant tasks just wonâ€™t do, since Ant 1.7 and Java 1.6 we can drop into a <code>&lt;script&gt;</code> tag. You ainâ€™t gonna like it:</p>
<pre class="programlisting">
  &lt;script language=&quot;javascript&quot;&gt;&lt;![CDATA[
    system.launchMissiles(); // Muhahahaha
  ]]&gt;&lt;/script&gt;</pre>

<p>The script tag allows us to use a scripting language as provided through the JSR 223 Java feature directly within our Ant file [<a href="#[DrDobbs]">DrDobbs</a>], meaning we can do anything.</p>

<p>In all the JVMs Iâ€™ve tried, the only scripting language actually available is JavaScript, provided by the Rhino virtual machine [<a href="#[MDN]">MDN</a>], which is now part of standard Java.</p>

<p>When using the script tag, expect bad error messages. Rhino produces unhelpful stack traces, and Ant doesnâ€™t really tell you what went wrong.</p>

<p>So now we know how to test the artifacts our build produces, but what about directly testing the logic in <span class="filename">build.xml</span>?</p>

<h2>Testing build logic</h2>

<p>We want to:</p>
<ul>
	<li>Confirm that targets succeed or fail under certain conditions</li>

	<li>Check indirect dependencies are as expected</li>

	<li>Test a unit of Ant logic (e.g. a macrodef)</li>
</ul>

<h3>Success and failure</h3>

<p>Listing 10 is a little macro I cooked up to assert that something is going to fail.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
&lt;macrodef name=&quot;expect-failure&quot;&gt;
  &lt;attribute name=&quot;target&quot;/&gt;
  &lt;sequential&gt;
    &lt;local name=&quot;ex.caught&quot;/&gt;
    &lt;script language=&quot;javascript&quot;&gt;&lt;![CDATA[
      try {
        project.executeTarget( &quot;@{target}&quot; );
      } catch( e ) {
        project.setProperty( &quot;ex.caught&quot;, &quot;yes&quot; )
      }
    ]]&gt;&lt;/script&gt;
    &lt;fail message=&quot;@{target} succeeded!!!&quot;
          unless=&quot;ex.caught&quot;/&gt;
  &lt;/sequential&gt;
&lt;/macrodef&gt;
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 10</td>
	</tr>
</table>

<p>I resorted to the Nuclear Option of a script tag, and used Antâ€™s Java API (through JavaScript) to execute the target, and catch any exceptions that are thrown. If no exception is thrown, we fail.</p>

<h3>Testing dependencies</h3>

<p>To check that the dependencies are as we expect, we really want to run antâ€™s dependency resolution without doing anything. Remarkably, ant has no support for this. But we can hack it in (see Listing 11).</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
&lt;target name=&quot;printCdeps&quot;&gt;
  &lt;script language=&quot;javascript&quot;&gt;&lt;![CDATA[
    var targs = project.getTargets().elements();
    while( targs.hasMoreElements() )
    {
      var targ = targs.nextElement();
      targ.setUnless( &quot;DRY.RUN&quot; );
    }
    project.setProperty( &quot;DRY.RUN&quot;, &quot;1&quot; );
    project.executeTarget( &quot;targetC&quot; );
  ]]&gt;&lt;/script&gt;
&lt;/target&gt;
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 11</td>
	</tr>
</table>

<p>(See â€˜Dry run mode for Antâ€™ [<a href="#[Balaam]">Balaam</a>] for more.)</p>

<p>Now we need to be able to run a build and capture the output. We can do that like Listing 12.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
&lt;target name=&quot;test-C-depends-on-A&quot;&gt;
  &lt;delete file=&quot;${tmpdir}/cdeps.txt&quot;/&gt;
  &lt;ant
    target=&quot;printCdeps&quot;
    output=&quot;${tmpdir}/cdeps.txt&quot;
  /&gt;
  &lt;fail message=&quot;Target A did not execute when
        we ran C!&quot;&gt;
    &lt;condition&gt;
      &lt;resourcecount when=&quot;equal&quot; count=&quot;0&quot;&gt;
        &lt;fileset file=&quot;${tmpdir}/cdeps.txt&quot;&gt;
          &lt;contains text=&quot;targetA:&quot;/&gt;
        &lt;/fileset&gt;
      &lt;/resourcecount&gt;
    &lt;/condition&gt;
  &lt;/fail&gt;
  &lt;delete file=&quot;${tmpdir}/cdeps.txt&quot;/&gt;
&lt;/target&gt;
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 12</td>
	</tr>
</table>

<p>We use ant to run the build, telling it to write to a file <span class="filename">cdeps.txt</span>. Then, to assert that <code>C</code> depends on <code>A</code>, we just fail if <span class="filename">cdeps.txt</span> doesnâ€™t contain a line indicating we ran <code>A</code>. (To assert a file contains a certain line we use a load of <code>fail</code>, <code>condition</code>, <code>resourcecount</code> and <code>fileset</code> machinery as before. This could do with some improvement to cover target names that overlap â€“ for example â€˜compile-aâ€™ will be wrongly found if â€˜test-compile-abcâ€™ was run.)</p>

<p>So, we can check that targets depend on each other, directly or indirectly. Can we write proper unit tests for our <code>macrodef</code>s?</p>

<h3>Testing ant units</h3>

<p>To test a <code>macrodef</code> or target as a piece of logic, without touching the file system or really running it, we will need fake versions of all the tasks, including <code>&lt;jar&gt;</code>, <code>&lt;copy&gt;</code>, <code>&lt;javac&gt;</code> and many more.</p>

<p>If we replace the real versions with fakes and then run our tasks, we can set up our fakes to track what happened, and then make assertions about it.</p>

<p>If we create a file called <span class="filename">real-fake-tasks.xml</span>, we can put things like this inside:</p>
<pre class="programlisting">
  &lt;macrodef name=&quot;jar&quot;&gt;
    &lt;attribute name=&quot;destfile&quot;/&gt;
    &lt;sequential&gt;
      &lt;property name=&quot;jar.was.run&quot; value=&quot;yes&quot;/&gt;
    &lt;/sequential&gt;
  &lt;/macrodef&gt;</pre>

<p>and, in <span class="filename">build.xml</span> we include something called <span class="filename">fake-tasks.xml</span>, with the optional attribute set to <code>true</code>:</p>
<pre class="programlisting">
  &lt;include file=&quot;fake-tasks.xml&quot; optional=&quot;true&quot;/&gt;</pre>

<p>If the target we want to test looks like this (in <span class="filename">build.xml</span>):</p>
<pre class="programlisting">
  &lt;target name=&quot;targetA&quot;&gt;
    &lt;jar destfile=&quot;foo.jar&quot;/&gt;
  &lt;/target&gt;</pre>

<p>Then we can write a test like this in <span class="filename">test-build.xml</span>:</p>
<pre class="programlisting">
  &lt;target name=&quot;test-A-runs-jar&quot;
          depends=&quot;build.targetA&quot;&gt;
    &lt;fail message=&quot;Didn't jar!&quot;
          unless=&quot;jar.was.run&quot;/&gt;
  &lt;/target&gt;</pre>

<p>and run the tests like this:</p>
<pre class="programlisting">
  cp real-fake-tasks.xml fake-tasks.xml
  ant -f test-build.xml test-A-runs-jar
  rm fake-tasks.xml</pre>

<p>If <span class="filename">fake-tasks.xml</span> doesnâ€™t exist, the real tasks will be used, so running your build normally should still work.</p>

<p>This trick relies on the fact that our fake tasks replace the real ones, which appears to be an undocumented behaviour of my version of Ant. Ant complains about us doing this, with an error message that sounds like it didnâ€™t work, but actually it did (on my machine).</p>

<p>If we wanted to avoid relying on this undocumented behaviour, weâ€™d need to write our real targets based on special <code>macrodef</code>s called things like do-jar and provide a version of do-jar that hands off to the real jar, and a version that is a fake. This would be a lot of work, and pollutes our production code with machinery needed for testing, but it could work with Antâ€™s documented behaviour, making it unlikely to fail unexpectedly in the future.</p>

<h2>Summary</h2>

<p>You can write Ant code in a test-driven way, and there are even structures that allow you to write things that might be described as unit tests.</p>

<p>At the moment, I am using mostly the â€˜testing artifactsâ€™ way. The tests run slowly, but they give real confidence that your build file is really working.</p>

<p>Since I introduced this form of testing into our build, I enjoy working with <span class="filename">build.xml</span> a lot more, because I know when Iâ€™ve messed it up.</p>

<p>But I do spend more time waiting around for the tests to run.</p>


<h2>References</h2>

<p class="bibliomixed"><a id="[Balaam]"></a>[Balaam]  â€˜Dry run mode for Antâ€™ on <em>Andy Balaamâ€™s blog</em> <a href="http://www.artificialworlds.net/blog/2013/01/31/dry-run-mode-for-ant-ant-n-ant-dry-run/">http://www.artificialworlds.net/blog/2013/01/31/dry-run-mode-for-ant-ant-n-ant-dry-run/</a></p>

<p class="bibliomixed"><a id="[Gant]"></a>[Gant]  <a href="http://gant.codehaus.org/">http://gant.codehaus.org/</a></p>

<p class="bibliomixed"><a id="[Gradle]"></a>[Gradle]  <a href="http://www.gradle.org/">http://www.gradle.org/</a></p>

<p class="bibliomixed"><a id="[DrDobbs]"></a>[DrDobbs] <a href="http://www.drdobbs.com/jvm/jsr-223-scripting-for-the-java-platform/215801163">http://www.drdobbs.com/jvm/jsr-223-scripting-for-the-java-platform/215801163</a> </p>

<p class="bibliomixed"><a id="[JUnit]"></a>[JUnit]  <a href="http://junit.org/">http://junit.org/</a></p>

<p class="bibliomixed"><a id="[Make]"></a>[Make]  <a href="http://www.gnu.org/software/make/">http://www.gnu.org/software/make/</a></p>

<p class="bibliomixed"><a id="[MDN]"></a>[MDN]  <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino">https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino</a></p>

<p class="bibliomixed"><a id="[SCons]"></a>[SCons]  <a href="http://www.scons.org/">http://www.scons.org/</a></p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
