| <?xml version="1.0"?> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <document> |
| |
| <properties> |
| <index value="1"/> |
| <title>AntUnit</title> |
| </properties> |
| |
| <body> |
| |
| <section name="AntUnit 1.0"> |
| <h3>January 8, 2007 - Apache AntUnit 1.0 Available</h3> |
| |
| <p>Apache AntUnit 1.0 is now available for download as <a |
| href="http://ant.apache.org/antlibs/bindownload.cgi">binary</a> |
| or <a |
| href="http://ant.apache.org/antlibs/srcdownload.cgi">source</a> |
| release.</p> |
| </section> |
| |
| <section name="Idea"> |
| <p>Initially all tests for Ant tasks were written as individual |
| <a href="http://www.junit.org/">JUnit</a> test cases. Pretty |
| soon it was clear that most tests needed to perform common tasks |
| like reading a build file, initializing a project instance with |
| it and executing a target. At this point <a |
| href="http://svn.apache.org/viewcvs.cgi/ant/core/trunk/src/testcases/org/apache/tools/ant/BuildFileTest.java">BuildFileTest</a> |
| was invented, a base class for almost all task test cases.</p> |
| |
| <p>BuildFileTest works fine and in fact has been picked up by <a |
| href="http://ant-contrib.sf.net/">the Ant-Contrib Project</a> |
| and others as well.</p> |
| |
| <p>Over time a new pattern evolved, more and more tests only |
| executed a target and didn't check any effects. Instead that |
| target contained the assertions as a <code><fail></code> |
| task. This is an example taken from the build file for the |
| ANTLR task (using Ant 1.7 features):</p> |
| |
| <source><![CDATA[ |
| <target name="test3" depends="setup"> |
| <antlr target="antlr.g" outputdirectory="${tmp.dir}"/> |
| <fail> |
| <condition> |
| <!-- to prove each of these files exists; |
| ANTLR >= 2.7.6 leaves behind new (.smap) files as well. --> |
| <resourcecount when="ne" count="5"> |
| <fileset dir="${tmp.dir}"> |
| <include name="CalcParserTokenTypes.txt" /> |
| <include name="CalcParserTokenTypes.java" /> |
| <include name="CalcLexer.java" /> |
| <include name="CalcParser.java" /> |
| <include name="CalcTreeWalker.java" /> |
| </fileset> |
| </resourcecount> |
| </condition> |
| </fail> |
| </target> |
| ]]></source> |
| |
| <p>where the corresponding JUnit testcase has been reduced |
| to</p> |
| |
| <source><![CDATA[ |
| ... |
| public class ANTLRTest extends BuildFileTest { |
| |
| private final static String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/antlr/"; |
| |
| public ANTLRTest(String name) { |
| super(name); |
| } |
| |
| public void setUp() { |
| configureProject(TASKDEFS_DIR + "antlr.xml"); |
| } |
| |
| public void tearDown() { |
| executeTarget("cleanup"); |
| } |
| |
| public void test3() { |
| executeTarget("test3"); |
| } |
| ... |
| } |
| ]]></source> |
| |
| <p>This approach has a couple of advantages, one of them is that |
| it is very easy to translate an example build file from a bug |
| report into a test case. If you ask a user for a testcase for a |
| given bug in Ant, he now doesn't need to understand JUnit or how |
| to fit a test into Ant's existing tests any more.</p> |
| |
| <p>AntUnit takes this approach to testing even further, it |
| removes JUnit completely and it comes with a set of predefined |
| <code><assert></code> tasks in order to reuse common kind |
| of checks.</p> |
| |
| <p>It turns out that AntUnit lends itself as a solution to other |
| problems as well. The assertions are an easy way to validate a |
| setup before even starting the build process, for example. |
| AntUnit could also be used for functional and integration tests |
| outside of the scope of Ant tasks (assert contents of databases |
| after running an application, assert contents of HTTP responses |
| ...). This is an area that will need more research.</p> |
| </section> |
| |
| <section name="Concepts"> |
| <subsection name="antunit Task"> |
| <p>The <antunit> task drives the tests much like |
| <junit> does for JUnit tests.</p> |
| |
| <p>When called on a build file, the task will start a new Ant |
| project for that build file and scan for targets with names |
| that start with "test". For each such target it then will</p> |
| <ol> |
| <li>Execute the target named setUp, if there is one.</li> |
| <li>Execute the target itself - if this target depends on |
| other targets the normal Ant rules apply and the dependent |
| targets are executed first.</li> |
| <li>Execute the target names tearDown, if there is one.</li> |
| </ol> |
| |
| </subsection> |
| <subsection name="Assertions"> |
| |
| <p>The base task is <code><assertTrue></code>. It |
| accepts a single nested condition and throws a subclass of |
| BuildException named AssertionFailedException if that |
| condition evaluates to false.</p> |
| |
| <p>This task could have been implemented using |
| <code><macrodef></code> and <code><fail></code>, |
| but in fact it is a "real" task so that it is possible to |
| throw a subclass of BuildException. The |
| <code><antunit></code> task catches this exception and |
| marks the target as failed, any other type of Exception |
| (including other BuildException) are test errors.</p> |
| |
| <p>Together with <code><assertTrue></code> there are |
| many predefined assertions for common conditions, most of |
| these are only macros.</p> |
| |
| </subsection> |
| |
| <subsection name="Other Tasks"> |
| |
| <p>The <code><logcapturer></code> captures all messages |
| that pass Ant's logging system and provides them via a |
| reference inside of the project. If you want to assert |
| certain log messages, you need to start this task (prior to |
| your target under test) and use the |
| <code><assertLogContains></code> assertion.</p> |
| |
| <p><code><expectFailure></code> is a task container that |
| catches any BuildException thrown by tasks nested into it. If |
| no exception has been thrown it will cause a test failure (by |
| throwing an AssertionFailedException).</p> |
| </subsection> |
| |
| <subsection name="AntUnitListener"> |
| <p>Part of the library is the <code>AntUnitListener</code> |
| interface that can be used to record test results. The |
| <antunit> task accepts arbitrary many listeners and |
| relays test results to them.</p> |
| |
| <p>Currently two implementations - |
| <code><plainlistener></code> and <code>xmllistener</code> |
| modelled after the "plain" and "xml" |
| JUnit listeners - are bundled with the library.</p> |
| </subsection> |
| </section> |
| |
| <section name="Examples"> |
| |
| <p>This is a way to test that <code><touch></code> |
| actually creates a file if it doesn't exist:</p> |
| |
| <source><![CDATA[ |
| <project xmlns:au="antlib:org.apache.ant.antunit"> |
| <!-- is called prior to the test --> |
| <target name="setUp"> |
| <property name="foo" value="foo"/> |
| </target> |
| |
| <!-- is called after the test, even if that caused an error --> |
| <target name="tearDown"> |
| <delete file="${foo}" quiet="true"/> |
| </target> |
| |
| <!-- the actual test case --> |
| <target name="testTouchCreatesFile"> |
| <au:assertFileDoesntExist file="${foo}"/> |
| <touch file="${foo}"/> |
| <au:assertFileExists file="${foo}"/> |
| </target> |
| </project> |
| ]]></source> |
| |
| <p>When running a task like</p> |
| |
| <source><![CDATA[ |
| <au:antunit> |
| <fileset dir="." includes="touch.xml"/> |
| <au:plainlistener/> |
| </au:antunit> |
| ]]></source> |
| |
| <p>from a buildfile of its own you'll get a result that looks like</p> |
| |
| <source><![CDATA[ |
| [au:antunit] Build File: /tmp/touch.xml |
| [au:antunit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.249 sec |
| [au:antunit] Target: testTouchCreatesFile took 0.183 sec |
| |
| BUILD SUCCESSFUL |
| Total time: 1 second |
| ]]></source> |
| |
| </section> |
| </body> |
| </document> |