|
-
-
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <!--
- 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.
- -->
- <html lang="en">
- <!-- GENERATED FILE, DO NOT EDIT, EDIT THE XML FILE IN xdocs INSTEAD! -->
- <head>
- <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>Apache Ant - Apache AntUnit</title>
- <link type="text/css" href="../../page.css" rel="stylesheet">
- </head>
-
- <body>
- <p class="navpath">
- <script src="../../breadcrumbs.js" language="JavaScript" type="text/javascript"></script>
- </p>
-
- <div class="logobar">
- <table width="100%" border="0" cellspacing="0" cellpadding="0">
- <tr>
- <td align="left"><img border="0" alt="Apache Ant site" src="../../images/group-logo.gif"></td>
- <td align="center" width="100%"><img alt="Apache Ant logo" border="0" src="../../images/project-logo.gif"></td>
- <td align="right">
- <form target="_blank" onsubmit="q.value = query.value + ' site:ant.apache.org'" action="http://www.google.com/search" method="get">
- <table summary="search" border="0" cellspacing="0" cellpadding="0" bgcolor="#4C6C8F">
- <tr>
- <td colspan="3"><img height="10" width="1" alt="" src="../../images/spacer.gif"></td>
- </tr>
- <tr>
- <td><img height="1" width="1" alt="" src="../../images/spacer.gif"></td>
- <td nowrap="nowrap" class="searchcaption">
- <input name="q" type="hidden">
- <input size="15" id="query" type="text">
- <img height="1" width="5" alt="" src="../../images/spacer.gif">
- <input name="Search" value="Search" type="submit">
- <br>
- the Apache Ant site
- </td>
- <td><img height="1" width="1" alt="" src="../../images/spacer.gif"></td>
- </tr>
- <tr>
- <td><img alt="" border="0" height="10" width="9" src="../../images/search-left.gif"></td>
- <td><img height="1" width="1" alt="" src="../../images/spacer.gif"></td>
- <td><img alt="" border="0" height="10" width="9" src="../../images/search-right.gif"></td>
- </tr>
- </table>
- </form>
- </td>
- </tr>
- </table>
- </div>
-
- <div class="tab">
- <table summary="tab bar" border="0" cellpadding="0" cellspacing="0">
- <tr>
- <td width="5"><img alt="" height="8" width="8" src="../../images/spacer.gif"></td><td valign="bottom">
- <table summary="non selected tab" style="height: 1.4em" border="0" cellpadding="0" cellspacing="0">
- <tr>
- <td valign="top" width="5" bgcolor="#B2C4E0"><img height="5" width="5" alt="" src="../../images/tab-left.gif"></td><td valign="middle" bgcolor="#B2C4E0"><a href="../../index.html"><font size="2" face="Arial, Helvetica, Sans-serif">Home</font></a></td><td valign="top" width="5" bgcolor="#B2C4E0"><img height="5" width="5" alt="" src="../../images/tab-right.gif"></td>
- </tr>
- </table>
- </td>
- <td width="8"><img alt="" height="5" width="8" src="../../images/spacer.gif"></td><td valign="bottom">
- <table summary="selected tab" style="height: 1.5em" border="0" cellpadding="0" cellspacing="0">
- <tr>
- <td valign="top" width="5" bgcolor="#4C6C8F"><img height="5" width="5" alt="" src="../../images/tabSel-left.gif"></td><td valign="middle" bgcolor="#4C6C8F"><font color="#ffffff" size="2" face="Arial, Helvetica, Sans-serif"><b>Projects</b></font></td><td valign="top" width="5" bgcolor="#4C6C8F"><img height="5" width="5" alt="" src="../../images/tabSel-right.gif"></td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </div>
-
- <div class="bluebar"></div>
-
- <div class="menucontainer">
- <div class="menu">
- <ul>
- <li class="menuheader">Projects
- <ul>
- <li>
- <a href="../../projects/index.html">Welcome</a>
- </li>
- </ul>
- </li>
- <li class="menuheader">Apache Ant Libraries
- <ul>
- <li>
- <a href="../../antlibs/index.html">Introduction</a>
- </li>
- <li>
- <a href="../../antlibs/charter.html">Charter</a>
- </li>
- <li>
- <a href="../../antlibs/proper.html">Ant Libraries</a>
- </li>
- <li>
- <a href="../../antlibs/sandbox.html">Sandbox Ant Libraries</a>
- </li>
- <li>
- <a href="http://ant.apache.org/antlibs/bindownload.cgi">Binary Distributions</a>
- </li>
- <li>
- <a href="http://ant.apache.org/antlibs/srcdownload.cgi">Source Distributions</a>
- </li>
- </ul>
- </li>
- <li class="menuheader">Apache Ivy
- <ul>
- <li>
- <a href="../../projects/ivy.html">Introduction</a>
- </li>
- <li>
- <a href="http://ant.apache.org/ivy/">Homepage</a>
- </li>
- <li>
- <a href="http://ant.apache.org/ivy/download.cgi">Distributions</a>
- </li>
- <li>
- <a href="http://cwiki.apache.org/IVY/">Wiki</a>
- </li>
- </ul>
- </li>
- <li class="menuheader">Apache IvyDE
- <ul>
- <li>
- <a href="../../projects/ivyde.html">Introduction</a>
- </li>
- <li>
- <a href="http://ant.apache.org/ivy/ivyde">Homepage</a>
- </li>
- <li>
- <a href="http://ant.apache.org/ivy/ivyde/screenshots.html">Screenshots</a>
- </li>
- <li>
- <a href="http://ant.apache.org/ivy/ivyde/download.cgi">Distributions</a>
- </li>
- </ul>
- </li>
- </ul>
- </div>
- <center>
- <a href="http://www.apache.org/events/current-event.html"><img border="0" title="ApacheCon" alt="ApacheCon - logo" src="http://www.apache.org/events/current-event-125x125.png" style="width: 125px;height: 125px;"></a>
- </center>
- <img style="float: left" height="10" width="10" border="0" alt="" src="../../images/menu-left.gif">
- <img style="float: right" height="10" width="10" border="0" alt="" src="../../images/menu-right.gif">
- </div>
- <div class="lightbluebar"> </div>
- <div class="main">
- <div class="content">
- <h1 class="title">Apache AntUnit</h1>
- <h3 class="section">
- <a name="Apache AntUnit 1.1"></a>
- Apache AntUnit 1.1
- </h3>
- <h3>September 26, 2008 - Apache AntUnit 1.1 Released</h3>
- <p>Apache AntUnit 1.1 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>
- <p>In addition to a few bugfixes and some new assertions AntUnit
- 1.1 allows test listeners to receive the log output of the
- project under test. Both plainlistener and xmllistener have
- an option that makes them echo the project's output into their
- respective logs.</p>
- <h3 class="section">
- <a name="AntUnit 1.1 Beta 1"></a>
- AntUnit 1.1 Beta 1
- </h3>
- <h3>September 3, 2008 - Apache AntUnit 1.1 Beta 1 Available</h3>
- <h3 class="section">
- <a name="AntUnit 1.0"></a>
- AntUnit 1.0
- </h3>
- <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>
- <h3 class="section">
- <a name="Idea"></a>
- Idea
- </h3>
- <p>Initially all tests for Apache 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/viewvc/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>
- <pre class="code">
- <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>
- </pre>
- <p>where the corresponding JUnit testcase has been reduced
- to</p>
- <pre class="code">
- ...
- 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");
- }
- ...
- }
- </pre>
- <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>
- <h3 class="section">
- <a name="Concepts"></a>
- Concepts
- </h3>
- <h4 class="subsection">
- <a name="antunit Task"></a>
- antunit Task
- </h4>
- <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>
- <h4 class="subsection">
- <a name="Assertions"></a>
- Assertions
- </h4>
- <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>
- <h4 class="subsection">
- <a name="Other Tasks"></a>
- Other Tasks
- </h4>
- <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>
- <h4 class="subsection">
- <a name="AntUnitListener"></a>
- AntUnitListener
- </h4>
- <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>
- <h3 class="section">
- <a name="Examples"></a>
- Examples
- </h3>
- <p>This is a way to test that <code><touch></code>
- actually creates a file if it doesn't exist:</p>
- <pre class="code">
- <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>
- </pre>
- <p>When running a task like</p>
- <pre class="code">
- <au:antunit>
- <fileset dir="." includes="touch.xml"/>
- <au:plainlistener/>
- </au:antunit>
- </pre>
- <p>from a buildfile of its own you'll get a result that looks like</p>
- <pre class="code">
- [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
- </pre>
-
- </div>
- </div>
-
- <p class="copyright">
- <script type="text/javascript" language="JavaScript"><!--
- document.write(" - "+"Last Published: " + document.lastModified);
- // -->
- </script>
- </p>
- </body>
- </html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|