This task allows tests to be launched and run using the JUnit 5 framework.
JUnit 5 introduced a newer set of APIs to write and launch tests. It also introduced the concept of test engines. Test engines decide which classes are considered as testcases and how they are executed. JUnit 5 supports running tests that have been written using JUnit 4 constructs as well as tests that have been written using JUnit 5 constructs. For more details about JUnit 5 itself, please refer to the JUnit 5 project's documentation at https://junit.org/junit5/.
The goal of this junitlauncher
task is to allow launching the JUnit 5 test launcher
and building the test requests so that the selected tests can then be parsed and executed by the
test engine(s) supported by JUnit 5. This task in itself does not understand what a test
case is nor does it execute the tests itself.
Note: This task depends on external libraries not included in the Apache Ant distribution. See Library Dependencies for more information.
Note: You must have the necessary JUnit 5 libraries in the classpath of the tests. At the time of writing this documentation, the list of JUnit 5 platform libraries that are necessary to run the tests are:
Depending on the test engine(s) that you want to use in your tests, you will further need the following libraries in the classpath
For junit-vintage
engine:
For junit-jupiter
engine:
To have these in the test classpath, you can follow either of the following approaches:
<classpath>
element to specify the location of the
test engines. For more details about this approach, please read the
using classpath element to include test engines section.
Tests are defined by nested elements like test
, testclasses
tags
(see nested elements).
Attribute | Description | Required |
---|---|---|
haltOnFailure | A value of trueimplies that build has to stop if any failure occurs in any of the tests. JUnit 4+ classifies failures as both assertion failures as well as exceptions that get thrown during test execution. As such, this task too considers both these cases as failures and doesn't distinguish one from another. |
No; default is false |
failureProperty | The name of a property to set in the event of a failure (exceptions in tests are considered failures as well). | No |
printSummary | If the value is set to true then this task, upon completion of the test execution,
prints the summary of the execution to System.out . The summary itself is generated
by the JUnit 5 platform and not by this task.
|
No; defaults to false |
The nested <classpath>
element that represents
a PATH like structure can be used to configure the task to use
this classpath for finding and running the tests. This classpath will be used for:
If the classpath
element isn't configured for the task, then the classpath of Ant
itself will be used for finding the test classes.
The <classpath>
can be used to include the test engines that you want to be
considered for execution of the tests.
NOTE: An important aspect to remember is that
whether or not you use this approach, the JUnit 5 platform libraries
listed earlier in this
document and the ant-junitlauncher.jar
, shouldn't be part of this classpath
and instead they must be included in Ant runtime's classpath either by placing them
in ANT_HOME/lib
or by passing the -lib
option.
Below is an example of setting up the classpath to include the Jupiter test engine during the
execution of the tests. We assume that the JUnit 5 platform libraries and the
ant-junitlauncher.jar
have been setup as explained previously.
<project> <property name="output.dir" value="${basedir}/build"/> <property name="src.test.dir" value="${basedir}/src/test"/> <property name="build.classes.dir" value="${output.dir}/classes"/> <target name="init"> <mkdir dir="${output.dir}"/> </target> <path id="junit.engine.jupiter.classpath"> <fileset dir="${basedir}/src/lib/jupiter/"/> </path> <target name="compile-test" depends="init"> <mkdir dir="${build.classes.dir}"/> <javac srcdir="${src.test.dir}" destdir="${build.classes.dir}"> <classpath refid="junit.engine.jupiter.classpath"/> </javac> </target> <target name="test" depends="compile-test"> <junitlauncher> <classpath refid="junit.engine.jupiter.classpath"/> <classpath> <pathelement location="${build.classes.dir}"/> </classpath> <testclasses outputdir="${output.dir}"> <fileset dir="${build.classes.dir}"/> <listener type="legacy-brief" sendSysOut="true"/> <listener type="legacy-xml" sendSysErr="true" sendSysOut="true"/> </testclasses> </junitlauncher> </target> </project>In the example above, the
src/lib/jupiter
directory is expected to contain
the Jupiter test engine related jars (which have been
listed in an earlier section of this
document). In the test
target we use the classpath
nested element
to point to the junit.engine.jupiter.classpath
containing those jars. In this
test
target we also use another classpath
element to point to
the location containing our test classes. If required, both these classpath can be combined
into one.
The junitlauncher
task can be configured with listener
(s) to listen to
test execution events (such as a test execution starting, completing etc...). The listener is
expected to be a class which implements
the org.junit.platform.launcher.TestExecutionListener
.
This TestExecutionListener
interface is an API exposed by the JUnit 5
platform APIs and isn't specific to Ant. As such, you can use any existing implementation
of TestExecutionListener
in this task.
junitlauncher
provides a way where the test execution results can be formatted and
presented in a way that's customizable. The task allows for configuring test result formatters,
through the use of listener
element. As noted previously, the listener
element expects the listener to implement
the org.junit.platform.launcher.TestExecutionListener
interface. Typically, result formatters need a bit more configuration details to be fed to them,
during the test execution—details like where to write out the formatted result. Any such
listener can optionally implement
the org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter
interface. This interface is specific to Ant junitlauncher
task and it extends
the org.junit.platform.launcher.TestExecutionListener
interface
The junitlauncher
task comes with the following pre-defined test result formatter
types:
legacy-plain: This formatter prints a short statistics line for all test cases.
legacy-brief: This formatter prints information for tests that failed or were skipped.
legacy-xml: This formatter prints statistics for the tests in XML format.
Note: Each of these formatters named legacy
try to format the results
similar to what the junit
task's formatters used to do. Furthermore,
the legacy-xml
formatter generates the XML to comply with the same schema that
the junit
task's XML formatter used to follow. As a result, the XML generated by
this formatter, can be used as-is by the junitreport
task.
The listener
element supports the following attributes:
Attribute | Description | Required |
---|---|---|
type | Use a predefined formatter (either legacy-xml, legacy-plainor legacy-brief). |
Exactly one of these |
classname | Name of a listener class which
implements org.junit.platform.launcher.TestExecutionListener or
the org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter
interface
|
|
resultFile |
The file name to which the formatted result needs to be written to. This attribute is
only relevant when the listener class implements
the org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter
interface.
If no value is specified for this attribute and the listener implements
the |
No |
sendSysOut | If set to truethen the listener will be passed the stdout content
generated by the test(s). This attribute is relevant only if the listener class
implements
the org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter
interface. |
No; defaults to false |
sendSysErr | If set to truethen the listener will be passed the stderr content
generated by the test(s). This attribute is relevant only if the listener class
implements
the org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter
interface. |
No; defaults to false |
if | Only use this listener if the named property is set. | No |
unless | Only use this listener if the named property is not set. | No |
Defines a single test class.
Attribute | Description | Required |
---|---|---|
name | Fully qualified name of the test class. | Yes |
methods | Comma-separated list of names of test case methods to execute. If this is specified, then only these test methods from the test class will be executed. | No |
haltOnFailure | Stop the build process if a failure occurs during the test run (exceptions are
considered as failures too). Overrides value set on junitlauncher
element. |
No |
failureProperty | The name of a property to set in the event of a failure (exceptions are considered
failures as well). Overrides value set on junitlauncher element. |
No |
outputDir | Directory to write the reports to. | No; default is the base directory of the project. |
if | Only run this test if the named property is set. | No |
unless | Only run this test if the named property is not set. | No |
includeEngines | A comma separated set of test engine ids. If specified, only these test engine(s)
will be used for running the tests.
For example: includeEngines="junit-jupiter" will only use the Jupiter
test engine for execution of the tests and will ignore any other engines that might
have been found in the classpath.
|
No |
excludeEngines | A comma separated set of test engine ids. If specified, these test engine(s)
will be excluded when running the tests.
For example: excludeEngines="junit-vintage" will exclude the vintage
test engine during execution of the tests and will use any other engines that might
have been found in the classpath.
|
No |
Tests can define their own listeners via nested listener
elements.
Define a number of tests based on pattern matching.
testclasses
collects the included resources
from any number of nested Resource
Collections. It then selects each resource whose name ends in .class
. These
classes are then passed on to the JUnit 5 platform for it to decide and run them as tests.
Attribute | Description | Required |
---|---|---|
haltOnFailure | Stop the build process if a failure occurs during the test run (exceptions are
considered as failures too). Overrides value set on junitlauncher
element. |
No |
failureProperty | The name of a property to set in the event of a failure (exceptions are considered
failures as well). Overrides value set on junitlauncher element. |
No |
outputDir | Directory to write the reports to. | No; default is the base directory of the project. |
if | Only run the tests if the named property is set. | No |
unless | Only run the tests if the named property is not set. | No |
includeEngines | A comma separated set of test engine ids. If specified, only these test engine(s)
will be used for running the tests.
For example: includeEngines="junit-jupiter" will only use the Jupiter
test engine for execution of the tests and will ignore any other engines that might
have been found in the classpath.
|
No |
excludeEngines | A comma separated set of test engine ids. If specified, these test engine(s)
will be excluded when running the tests.
For example: excludeEngines="junit-vintage" will exclude the vintage
test engine during execution of the tests and will use any other engines that might
have been found in the classpath.
|
No |
testclasses
can define their own listeners via nested listener
elements.
Launch the JUnit 5 platform to run the org.myapp.SimpleTest test
<path id="test.classpath"> ... </path> <junitlauncher> <classpath refid="test.classpath"/> <test name="org.myapp.SimpleTest"/> </junitlauncher>
Launch the JUnit 5 platform to run the org.myapp.SimpleTest and the org.myapp.AnotherTest tests. The build process will be stopped if any test, in the org.myapp.SimpleTest, fails.
<junitlauncher> <classpath refid="test.classpath"/> <test name="org.myapp.SimpleTest" haltOnFailure="true"/> <test name="org.myapp.AnotherTest"/> </junitlauncher>
Launch the JUnit 5 platform to run only the testFoo and testBar methods of the org.myapp.SimpleTest test class.
<junitlauncher> <classpath refid="test.classpath"/> <test name="org.myapp.SimpleTest" methods="testFoo, testBar"/> </junitlauncher>
Select any .class files that match
the org/example/**/tests/**/ fileset
filter, under
the ${build.classes.dir} and passes those classes to the JUnit 5 platform for
execution as tests.
<junitlauncher> <classpath refid="test.classpath"/> <testclasses outputdir="${output.dir}"> <fileset dir="${build.classes.dir}"> <include name="org/example/**/tests/**/"/> </fileset> </testclasses> </junitlauncher>
Select any .class files that match
the org/example/**/tests/**/ fileset
filter, under
the ${build.classes.dir} and pass those classes to the JUnit 5 platform for
execution as tests. Test results will be written out to the ${output.dir} by
the legacy-xml
and legacy-plain
formatters, in separate files. Furthermore, both
the legacy-xml
and the legacy-plain
listeners, above, are configured to receive
the standard output content generated by the tests. The legacy-xml
listener is configured
to receive standard error content as well.
<junitlauncher> <classpath refid="test.classpath"/> <testclasses outputdir="${output.dir}"> <fileset dir="${build.classes.dir}"> <include name="org/example/**/tests/**/"/> </fileset> <listener type="legacy-xml" sendSysOut="true" sendSysErr="true"/> <listener type="legacy-plain" sendSysOut="true" /> </testclasses> </junitlauncher>