此任务运行来自 JUnit 测试框架的测试。该框架的最新版本可以在 https://junit.java.net.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>