Apache Ant site Apache Ant logo

Apache Ant 网站
首页
项目
 

Apache AntUnit

Apache AntUnit™

Apache AntUnit 是一个 Antlib,它为 Apache Ant 任务和类型提供了一个测试框架。

Apache AntUnit 1.4.1

2021 年 7 月 7 日 - Apache AntUnit 1.4.1 发布

Apache AntUnit 1.4.1 现在可以作为 二进制源代码 发行版下载。

此版本修复了 antlib.xml 描述符,以便 AntUnit 现在可以使用用户定义的 URI,而不是将 AntUnit 的首选 URI 硬编码。

想法

最初,Apache Ant 任务的所有测试都作为单独的 JUnit 测试用例编写。很快,很明显,大多数测试都需要执行一些常见的任务,例如读取构建文件,用它初始化项目实例并执行目标。此时,BuildFileTest 被发明出来,它是几乎所有任务测试用例的基类。

BuildFileTest 工作正常,事实上,它也被 Ant-Contrib 项目 和其他人采用。

随着时间的推移,一种新的模式出现了,越来越多的测试只执行一个目标,而不检查任何效果。相反,该目标包含断言作为 <fail> 任务。这是一个来自 ANTLR 任务构建文件的示例(使用 Ant 1.7 功能)

  <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>

其中相应的 JUnit 测试用例已简化为

...
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");
    }
...
}

这种方法有几个优点,其中之一是将错误报告中的示例构建文件转换为测试用例非常容易。如果你要求用户提供针对 Ant 中给定错误的测试用例,他现在不再需要理解 JUnit 或者如何将测试融入 Ant 的现有测试了。

AntUnit 将这种测试方法更进一步,它完全删除了 JUnit,并提供了一组预定义的 <assert> 任务,以便重用常见的检查类型。

事实证明,AntUnit 也能解决其他问题。断言是一种简单的方法,可以在甚至开始构建过程之前验证设置,例如。AntUnit 也可以用于 Ant 任务范围之外的功能和集成测试(在运行应用程序后断言数据库的内容,断言 HTTP 响应的内容...)。这是一个需要更多研究的领域。

概念

antunit 任务

<antunit> 任务驱动测试,就像 <junit> 对 JUnit 测试一样。

当在构建文件上调用时,该任务将为该构建文件启动一个新的 Ant 项目,并扫描名称以“test”开头的目标。对于每个这样的目标,它将

  1. 执行名为 setUp 的目标,如果有的话。
  2. 执行目标本身 - 如果此目标依赖于其他目标,则正常的 Ant 规则适用,并且依赖目标将首先执行。
  3. 执行名为 tearDown 的目标,如果有的话。

断言

基本任务是 <assertTrue>。它接受一个嵌套条件,如果该条件计算结果为 false,则抛出一个名为 AssertionFailedException 的 BuildException 子类。

此任务可以使用 <macrodef><fail> 实现,但实际上它是一个“真实”任务,因此可以抛出 BuildException 的子类。<antunit> 任务捕获此异常并将目标标记为失败,任何其他类型的异常(包括其他 BuildException)都是测试错误。

除了 <assertTrue> 之外,还有许多预定义的断言用于常见条件,其中大多数只是宏。

其他任务

<logcapturer> 捕获所有通过 Ant 日志系统传递的消息,并通过项目中的引用提供它们。如果你想断言某些日志消息,你需要启动此任务(在你的测试目标之前)并使用 <assertLogContains> 断言。

<expectFailure> 是一个任务容器,它捕获嵌套到其中的任务抛出的任何 BuildException。如果没有抛出异常,它将导致测试失败(通过抛出 AssertionFailedException)。

AntUnitListener

库的一部分是 AntUnitListener 接口,它可以用于记录测试结果。<antunit> 任务接受任意多个监听器,并将测试结果转发给它们。

目前,库中捆绑了两个实现 - <plainlistener>xmllistener,它们模仿“plain”和“xml”JUnit 监听器。

示例

这是一种测试 <touch> 是否真的创建了一个不存在的文件的方法

<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>

当从它自己的构建文件运行像

    <au:antunit>
      <fileset dir="." includes="touch.xml"/>
      <au:plainlistener/>
    </au:antunit>

这样的任务时,你会得到一个看起来像这样的结果

[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