此任务运行来自 JUnit 测试框架的测试。该框架的最新版本可以在 https://junit.cn 找到。此任务已在 JUnit 3.0 到 JUnit 3.8.2 上测试过;它不适用于 JUnit 3.0 之前的版本。它也适用于 JUnit 4.x,包括仅使用注解且不使用 JUnit4TestAdapter 的“纯”JUnit 4 测试。
注意:此任务依赖于 Apache Ant 分发版中未包含的外部库。有关更多信息,请参见 库依赖项。
注意:如果此任务启动的测试或测试使用的任何库调用了诸如 java.lang.System.exit() 或 java.lang.Runtime.exit() 之类的 API,则必须设置 fork=true
。
注意:您必须拥有 junit.jar。您可以执行以下操作之一:
ANT_HOME/lib 中。ANT_HOME/lib 中,而是将它们的位置包含在您的 CLASSPATH 环境变量中。<taskdef> 中的 <classpath> 元素指定这两个 JAR 的位置。ANT_HOME/lib 中的默认位置,但将 junit.jar 包含在传递给 <junit> 的 <classpath> 中。从 Ant 1.7 开始有关详细信息,请参见 常见问题解答。
测试由嵌套的 test 或 batchtest 标签定义(请参见 嵌套元素)。
| 属性 | 描述 | 必需 |
|---|---|---|
| printsummary | 为每个测试用例打印单行统计信息。可以取值 on、 off和 withOutAndErr。 withOutAndErr与 on相同,但还包括测试写入 System.out 和 System.err 的输出。 |
否;默认值为 off |
| fork | 在单独的 JVM 中运行测试。 | 否;默认值为 off |
| forkmode | 控制如果您想分叉一些测试,将创建多少个 JVM。可能的值是 perTest(默认值)、 perBatch和 once。 once仅为所有测试创建一个 JVM,而 perTest为每个 TestCase 类创建一个新的 JVM。 perBatch为每个嵌套的 <batchtest> 创建一个 JVM,并创建一个收集所有嵌套的 <test> 的 JVM。请注意,只有具有相同 filtertrace、haltonerror、haltonfailure、errorproperty 和 failureproperty 设置的测试才能共享一个 JVM,因此即使您将 forkmode 设置为 once,Ant 也可能必须创建多个 JVM。此属性将被忽略,因为测试不会分叉到新的 JVM 中。从 Ant 1.6.2 开始 |
否;默认值为 perTest |
| haltonerror | 如果在测试运行期间发生错误,则停止构建过程。 | 否;默认值为 off |
| errorproperty | 在发生错误时要设置的属性的名称。 | 否 |
| haltonfailure | 如果测试失败(错误也被视为失败),则停止构建过程。 | 否;默认值为 off |
| failureproperty | 在发生失败(错误也被视为失败)时要设置的属性的名称。 | 否 |
| filtertrace | 从错误和失败堆栈跟踪中过滤掉 JUnit 和 Ant 堆栈帧。 | 否;默认值为 on |
| timeout | 如果单个测试在给定时间内(以毫秒为单位)未完成,则取消该测试。如果 fork 为 off,则忽略此项。在同一 JVM 中运行多个测试(请参见 forkMode)时,timeout 适用于所有测试一起使用的时间,而不是单个测试。 |
否 |
| maxmemory | 分配给分叉 JVM 的最大内存量。如果 fork 为 off,则忽略此项。注意:如果您在某些测试中遇到 java.lang.OutOfMemoryError: Java heap space,则需要提高大小,例如 maxmemory=128m |
否 |
| jvm | 用于调用 JVM 的命令。该命令由 java.lang.Runtime.exec() 解析。 |
否;默认值为 java,如果 fork 为 false,则忽略此项 |
| dir | 在其中调用 JVM 的目录。 | 否,如果 fork 为 false,则忽略此项 |
| newenvironment | 在指定新的环境变量时,不要传播旧环境。 | 否;默认值为 false,如果 fork 为 false,则忽略此项 |
| includeantruntime | 在分叉模式下,将隐式地将运行测试所需的 Ant 类和 JUnit 添加到类路径中。 | 否;默认值为 true |
| showoutput | 将测试生成的任何输出发送到 Ant 的日志系统以及格式化程序。 | 否;默认情况下,只有格式化程序会收到输出 |
| outputtoformatters | 将测试生成的任何输出发送到测试格式化程序。从 Ant 1.7.0 开始。 | 否;默认值为 true |
| tempdir | Ant 应放置临时文件的位置。从 Ant 1.6 开始。 | 否;默认值为项目的 basedir |
| reloading | 是否应为每个测试用例实例化一个新的类加载器。 如果 fork 设置为 true,则忽略此项。从 Ant 1.6 开始。 |
否;默认值为 true |
| clonevm | 如果设置为 true,则分叉 JVM 的所有系统属性和 bootclasspath 将与运行 Ant 的 JVM 的系统属性和 bootclasspath 相同。从 Ant 1.7 开始 |
否;默认值为 false,如果 fork 为 false,则忽略此项 |
| logfailedtests | 当 Ant 执行多个测试并且不会在错误或失败时停止时,它会将其日志系统中的每个失败测试的“FAILED”消息记录下来。如果您将此选项设置为 false,则不会记录该消息,您必须依靠格式化程序输出来查找失败的测试。从 Ant 1.8.0 开始 |
否 |
| enableTestListenerEvents | Ant 是否应将有关正在运行的测试的细粒度信息发送到 Ant 的日志系统,处于详细级别。自定义测试侦听器可以使用此类事件来显示测试的进度。 从 Ant 1.8.2 开始—Ant 1.7.0 到 1.8.1 的行为就好像此属性默认情况下为 true一样。 |
否;默认值为 false,可以由 神奇属性 覆盖 |
| threads | 运行测试的线程数。 当指定此属性时,测试将被任意地拆分到线程中。 要求测试使用 perTest选项分叉才能生效。 从 Ant 1.9.4 开始 |
否 |
通过使用 errorproperty 和 failureproperty 属性,可以执行设置工作(例如启动外部服务器)、执行测试、清理,并且在发生失败时仍然使构建失败。
filtertrace 属性在报告错误和失败堆栈跟踪之前会压缩它们。它适用于普通格式化程序和 XML 格式化程序。它会过滤掉以以下字符串模式开头的任何行:
"junit.framework.TestCase"
"junit.framework.TestResult"
"junit.framework.TestSuite"
"junit.framework.Assert."
"junit.swingui.TestRunner"
"junit.awtui.TestRunner"
"junit.textui.TestRunner"
"java.lang.reflect.Method.invoke("
"sun.reflect."
"org.apache.tools.ant."
"org.junit."
"junit.framework.JUnit4TestAdapter"
" more"
<junit> 任务支持一个嵌套的 <classpath> 元素,它表示一个 类似路径的结构。
从 Ant 1.7 开始,此类路径可用于引用 junit.jar 以及您的测试和被测试的代码。
如果 fork 为 true
,则可以通过嵌套的 <jvmarg> 元素将其他参数传递给新的 JVM。例如
<junit fork="yes"> <jvmarg value="-Dfoo=bar"/> ... </junit>
将在没有 JIT 的 JVM 中运行测试。
<jvmarg> 允许 命令行参数 中描述的所有属性。
使用嵌套的 <sysproperty> 元素来指定类所需的系统属性。这些属性将在测试执行期间(在 Ant 的 JVM 或分叉的 JVM 中,如果 fork=true
)提供给 JVM。此元素的属性与 环境变量 的属性相同。
<junit fork="no">
<sysproperty key="basedir" value="${basedir}"/>
...
</junit>
将在 Ant 的 JVM 中运行测试,并将 basedir 属性提供给测试。
从 Ant 1.6 开始
您可以使用 syspropertyset 指定一组用作系统属性的属性。
可以通过嵌套的 <env> 元素指定要传递给分叉 JVM 的环境变量。有关 <env> 元素属性的描述,请参见 exec 任务中的描述。
如果 fork=false
,则设置将被忽略。
从 Ant 1.6 开始.
可以使用此 类似路径的结构 指定引导类文件的位置—如果 fork 为 false
或目标 JVM 不支持它(即 Java 1.1),则将被忽略。
从 Ant 1.6 开始.
注意:
在 Java 18 及更高版本上运行时,此元素不再受支持。有关详细信息,请参见 permissions。
可以通过嵌套的 permissions 元素在类执行期间撤销和授予安全权限。有关更多信息,请参见 permissions
如果 fork=true
,则设置将被忽略。
从 Ant 1.6 开始.
您可以使用 <assertions> 子元素来控制 Java 1.4 断言的启用。
断言语句目前在非分叉模式下被忽略。
从 Ant 1.9.8 开始
可以使用此 类似路径的结构 指定模块的位置。modulepath 要求 fork 设置为 true
。
从 Ant 1.9.8 开始
可以使用此 类似路径的结构 指定替换运行时映像中可升级模块的模块的位置。upgrademodulepath 要求 fork 设置为 true
。
测试结果可以用不同的格式打印。输出始终会发送到文件,除非您将 usefile 属性设置为 false
。文件名称由测试名称确定,可以通过 <test> 的 outfile 属性设置。
有四个预定义的格式化程序—一个以 XML 格式打印测试结果,另一个发出纯文本。名为 brief
的格式化程序只打印失败测试用例的详细信息,而 plain
为所有测试用例提供一个简短的统计信息行。可以指定需要实现 org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter 的自定义格式化程序。
如果您使用 XML 格式化程序,它可能不包含测试写入的相同输出,因为某些字符在 XML 文档中是非法的,将被删除。
第四个名为 failure
的格式化程序(从 Ant 1.8.0 开始)收集所有失败的 testXXX() 方法,并创建一个新的 TestCase,它只委托这些失败的方法。名称和位置可以通过 Java 系统属性或 Ant 属性 ant.junit.failureCollector 指定。该值必须指向结果类的目录和名称(不带后缀)。它默认为 java-tmp-dir/FailedTests。
| 属性 | 描述 | 必需 |
|---|---|---|
| type | 使用预定义的格式化程序(xml、 plain、 brief或 failure)。 |
这些中只有一个 |
| classname | 自定义格式化程序类的名称。 | |
| extension | 要附加到输出文件名中的扩展名。 | 是,如果已使用 classname |
| usefile | 确定是否应将输出发送到文件的布尔值。 | 否;默认值为 true |
| if | 仅在 命名属性已设置 时使用格式化程序。 | 否;默认值为 true |
| unless | 仅在 命名属性未设置 时使用格式化程序。 | 否;默认值为 true |
定义单个测试类。
| 属性 | 描述 | 必需 |
|---|---|---|
| name | 测试类的名称。 | 是 |
| methods | 要执行的测试用例方法的逗号分隔名称列表。自 1.8.2 起 methods 属性在以下场景中很有用
如果使用了 methods 属性但未指定测试方法,则不会执行套件中的任何测试方法。 |
否;默认情况下运行套件中的所有测试方法 |
| fork | 在单独的 JVM 中运行测试。覆盖在 <junit> 中设置的值。 |
否 |
| haltonerror | 如果在测试运行期间发生错误,则停止构建过程。覆盖在 <junit> 中设置的值。 |
否 |
| errorproperty | 发生错误时要设置的属性的名称。覆盖在 <junit> 中设置的值。 |
否 |
| haltonfailure | 如果测试失败(错误也被视为失败),则停止构建过程。覆盖在 <junit> 中设置的值。 |
否 |
| failureproperty | 发生故障(错误也被视为故障)时要设置的属性的名称。覆盖在 <junit> 中设置的值。 |
否 |
| filtertrace | 从错误和故障堆栈跟踪中过滤掉 JUnit 和 Ant 堆栈帧。覆盖在 <junit> 中设置的值。 |
否;默认值为 on |
| todir | 要将报告写入的目录。 | 否;默认值为当前目录 |
| outfile | 测试结果的基名称。完整文件名是 outfile.formatter。 | 否;默认值为 TEST-name |
| if | 仅在 设置了命名属性 时运行测试。 | 否 |
| unless | 仅在 未设置命名属性 时运行测试。 | 否 |
| skipNonTests | 不要将任何不包含 JUnit 测试的类传递给测试运行器。这可以防止非测试在测试结果中显示为测试错误。 通过在不扩展 junit.framework.TestCase 的具体类中的任何方法上查找 @Test 注释,或通过在扩展 junit.framework.TestCase 的具体类中查找以 test开头的公共/受保护方法来识别测试。标记有 JUnit 4 org.junit.runner.RunWith 或 org.junit.runner.Suite.SuiteClasses 注释的类也会传递给 JUnit 以执行,与任何具有公共/受保护的无参数 suite() 方法的类一样。 |
否;默认值为 false |
测试可以通过嵌套的 <formatter> 元素定义自己的格式化程序。
根据模式匹配定义一定数量的测试。
batchtest 收集来自任何数量的嵌套 资源集合 的包含的 资源。然后,它为每个以 .java 或 .class 结尾的资源生成一个测试类名。
任何类型的资源集合都支持作为嵌套元素,在 Ant 1.7 之前,仅支持 <fileset>。
| 属性 | 描述 | 必需 |
|---|---|---|
| fork | 在单独的 JVM 中运行测试。覆盖在 <junit> 中设置的值。 |
否 |
| haltonerror | 如果在测试运行期间发生错误,则停止构建过程。覆盖在 <junit> 中设置的值。 |
否 |
| errorproperty | 发生错误时要设置的属性的名称。覆盖在 <junit> 中设置的值。 |
否 |
| haltonfailure | 如果测试失败(错误也被视为失败),则停止构建过程。覆盖在 <junit> 中设置的值。 |
否 |
| failureproperty | 发生故障(错误也被视为故障)时要设置的属性的名称。覆盖在 <junit> 中设置的值 |
否 |
| filtertrace | 从错误和故障堆栈跟踪中过滤掉 JUnit 和 Ant 堆栈帧。覆盖在 <junit> 中设置的值。 |
否;默认值为 on |
| todir | 要将报告写入的目录。 | 否;默认值为当前目录 |
| if | 仅在 设置了命名属性 时运行测试。 | 否 |
| unless | 仅在 未设置命名属性 时运行测试。 | 否 |
| skipNonTests | 不要将任何不包含 JUnit 测试的类传递给测试运行器。这可以防止非测试在测试结果中显示为测试错误。 通过在不扩展 junit.framework.TestCase 的具体类中的任何方法上查找 @Test 注释,或通过在扩展 junit.framework.TestCase 的具体类中查找以 test开头的公共/受保护方法来识别测试。标记有 JUnit 4 org.junit.runner.RunWith 或 org.junit.runner.Suite.SuiteClasses 注释的类也会传递给 JUnit 以执行,与任何具有公共/受保护的无参数 suite() 方法的类一样。 |
否;默认值为 false |
批处理测试可以通过嵌套的 <formatter> 元素定义自己的格式化程序。
tearDown()如果分叉测试遇到超时,Ant 将终止它创建的 JVM 进程,这可能意味着测试的 tearDown() 方法永远不会被调用。如果分叉 JVM 因其他原因崩溃,情况也是如此。
自 Ant 1.8.0 起,Ant 附带了一个特殊的格式化程序,它尝试加载分叉 JVM 中的测试用例并调用该类的 tearDown() 方法。此格式化程序具有以下限制
perTest之外的任何 forkMode 一起使用,并且如果测试类包含
suite() 方法,它将不会执行任何操作。如果格式化程序识别出不兼容的 forkMode 或 suite() 方法或无法加载测试类,它将静默地不执行任何操作。
格式化程序对未分叉或未导致超时或 JVM 崩溃的测试没有任何影响。
要启用格式化程序,请添加一个 formatter,例如
<formatter classname="org.apache.tools.ant.taskdefs.optional.junit.TearDownOnVmCrash"
usefile="false"/>
到您的 junit 任务中。
ant.junit.enabletestlistenerevents 魔法属性自 Ant 1.8.2 起,任务的 enableTestListenerEvents 属性控制是否将细粒度日志消息发送到任务的详细日志。除了此属性之外,Ant 还将查询属性 ant.junit.enabletestlistenerevents,并且属性的值将覆盖属性的设置。
此属性的存在是为了让运行 Ant 的容器(依赖于附加日志事件)能够确保即使构建文件禁用了这些事件,它们也会生成。
在同一个 VM 中运行在 my.test.TestCase 中定义的测试。除非测试失败,否则不会生成任何输出。
<junit>
<test name="my.test.TestCase"/>
</junit>
在单独的 JVM 中运行在 my.test.TestCase 中定义的测试。在测试结束时,将打印一行摘要。测试的详细报告可以在 TEST-my.test.TestCase.txt 中找到。如果测试失败,构建过程将停止。
<junit printsummary="yes" fork="yes" haltonfailure="yes">
<formatter type="plain"/>
<test name="my.test.TestCase"/>
</junit>
在同一个 JVM 中运行 my.test.TestCase,忽略给定的 CLASSPATH;如果此测试失败,只会打印警告。除了纯文本测试结果之外,对于此测试,将输出一个 XML 结果到 result.xml。然后,对于 ${src.tests} 定义的目录中的每个匹配文件,将在单独的 JVM 中运行一个测试。如果测试失败,构建过程将中止。结果将收集在名为 TEST-name.txt 的文件中,并写入 ${reports.tests}。
<junit printsummary="yes" haltonfailure="yes">
<classpath>
<pathelement location="${build.tests}"/>
<pathelement path="${java.class.path}"/>
</classpath>
<formatter type="plain"/>
<test name="my.test.TestCase" haltonfailure="no" outfile="result">
<formatter type="xml"/>
</test>
<batchtest fork="yes" todir="${reports.tests}">
<fileset dir="${src.tests}">
<include name="**/*Test*.java"/>
<exclude name="**/AllTests.java"/>
</fileset>
</batchtest>
</junit>
在第一次运行时,所有测试都通过 <batchtest/> 元素收集。它的 plain 格式化程序在控制台上显示输出。 failure 格式化程序在 ${build.dir}/failingTests/FailedTests.java 中创建一个 Java 源文件,它扩展了 junit.framework.TestCase 并从 suite() 方法返回失败测试的测试套件。
在第二次运行时,收集器类存在,并且代替 <batchtest/>,将运行单个 <test/>。因此,只重新运行失败的测试用例。两个嵌套的格式化程序用于显示(供用户使用)和更新收集器类。
<target name="test">
<property name="collector.dir" value="${build.dir}/failingTests"/>
<property name="collector.class" value="FailedTests"/>
<!-- Delete 'old' collector classes -->
<delete>
<fileset dir="${collector.dir}" includes="${collector.class}*.class"/>
</delete>
<!-- compile the FailedTests class if present -->
<javac srcdir="${collector.dir}" destdir="${collector.dir}"/>
<available file="${collector.dir}/${collector.class}.class" property="hasFailingTests"/>
<junit haltonerror="false" haltonfailure="false">
<sysproperty key="ant.junit.failureCollector" value="${collector.dir}/${collector.class}"/>
<classpath>
<pathelement location="${collector.dir}"/>
</classpath>
<batchtest todir="${collector.dir}" unless="hasFailingTests">
<fileset dir="${collector.dir}" includes="**/*.java" excludes="**/${collector.class}.*"/>
<!-- for initial creation of the FailingTests.java -->
<formatter type="failure"/>
<!-- I want to see something ... -->
<formatter type="plain" usefile="false"/>
</batchtest>
<test name="FailedTests" if="hasFailingTests">
<!-- update the FailingTests.java -->
<formatter type="failure"/>
<!-- again, I want to see something -->
<formatter type="plain" usefile="false"/>
</test>
</junit>
</target>
在由 platform.java 属性给出的分叉 JVM 中,将 my.test.TestCase 作为白盒测试运行。JUnit 库是未命名模块的一部分,而被测项目和必需模块位于模块路径上。测试没有模块信息文件,并在由 module.name 属性给出的项目模块中执行。
--patch-module Java 选项在由 module.name 属性给出的模块中执行构建到 ${build.test.classes} 中的测试。
--add-modules Java 选项启用被测模块。
--add-reads Java 选项使包含 JUnit 的未命名模块可被被测模块读取。
--add-exports Java 选项使未导出的测试包 my.test 可从包含 JUnit 的未命名模块访问。
<junit fork="true"
jvm="${platform.java}">
<jvmarg line="--patch-module ${module.name}=${build.test.classes}"/>
<jvmarg line="--add-modules ${module.name}"/>
<jvmarg line="--add-reads ${module.name}=ALL-UNNAMED"/>
<jvmarg line="--add-exports ${module.name}/my.test=ALL-UNNAMED"/>
<classpath>
<pathelement path="${libs.junit}"/>
</classpath>
<modulepath>
<pathelement path="${modules}:${build.classes}"/>
</modulepath>
<formatter type="plain"/>
<test name="my.test.TestCase"/>
</junit>
在由 platform.java 属性给出的分叉 JVM 中,将 my.test.TestCase 作为黑盒测试运行。JUnit 库用作自动模块。测试的模块信息需要被测模块和 JUnit。
--add-modules Java 选项启用测试模块。
--add-exports Java 选项使未导出的测试包 my.test 可从 JUnit 模块和 Ant 的测试运行器访问。另一种可能性是在测试的模块信息中通过 exports my.test 指令导出测试包。
<junit fork="true"
jvm="${platform.java}">
<jvmarg line="--add-modules ${test.module.name}"/>
<jvmarg line="--add-exports ${test.module.name}/my.test=junit,ALL-UNNAMED"/>
<modulepath>
<pathelement path="${modules}:${build.classes}:${libs.junit}"/>
</modulepath>
<formatter type="plain"/>
<test name="my.test.TestCase"/>
</junit>