<!-- 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> <head> <link rel="stylesheet" type="text/css" href="../stylesheets/style.css"> <title>JUnitLauncher Task</title> </head> <body> <h2 id="junitlauncher">JUnitLauncher</h2> <h3>Description</h3> <p> This task allows tests to be launched and run using the JUnit 5 framework. </p> <p> 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 <a href="https://junit.org/junit5/">https://junit.org/junit5/</a>. </p> <p> The goal of this <code>junitlauncher</code> 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 <i>not</i> understand what a test case is nor does it execute the tests itself. </p> <p> <strong>Note</strong>: This task depends on external libraries not included in the Apache Ant distribution. See <a href="../install.html#librarydependencies">Library Dependencies</a> for more information. </p> <p> <strong>Note</strong>: 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: </p> <ul id="junit-platform-libraries"> <li> <samp>junit-platform-commons.jar</samp> </li> <li> <samp>junit-platform-engine.jar</samp> </li> <li> <samp>junit-platform-launcher.jar</samp> </li> <li> <samp>opentest4j.jar</samp> </li> </ul> <p> Depending on the test engine(s) that you want to use in your tests, you will further need the following libraries in the classpath </p> <p id="junit-vintage-engine-libraries"> For <q>junit-vintage</q> engine: </p> <ul> <li> <samp>junit-vintage-engine.jar</samp> </li> <li> <samp>junit.jar</samp> (JUnit 4.x version) </li> </ul> <p id="junit-jupiter-engine-libraries"> For <q>junit-jupiter</q> engine: </p> <ul> <li> <samp>junit-jupiter-api.jar</samp> </li> <li> <samp>junit-jupiter-engine.jar</samp> </li> </ul> <p> To have these in the test classpath, you can follow <em>either</em> of the following approaches: </p> <ul> <li>Put all these relevant jars along with the <samp>ant-junitlauncher.jar</samp> in <samp>ANT_HOME/lib</samp> directory</li> <li>OR Leave <samp>ant-junitlauncher.jar</samp> in the <samp>ANT_HOME/lib</samp> directory and include all other relevant jars in the classpath by passing them as a <kbd>-lib</kbd> option, while invoking Ant</li> <li>OR Use the nested <code><classpath></code> element to specify the location of the test engines. For more details about this approach, please read the <a href=#test-engine-in-classpath>using classpath element to include test engines</a> section. </ul> <p> Tests are defined by nested elements like <code>test</code>, <code>testclasses</code> tags (see <a href="#nested">nested elements</a>). </p> <h3>Parameters</h3> <table class="attr"> <tr> <th scope="col">Attribute</th> <th scope="col">Description</th> <th scope="col">Required</th> </tr> <tr> <td>haltOnFailure</td> <td>A value of <q>true</q> implies 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. </td> <td>No; default is <q>false</q></td> </tr> <tr> <td>failureProperty</td> <td>The name of a property to set in the event of a failure (exceptions in tests are considered failures as well). </td> <td>No</td> </tr> <tr> <td>printSummary</td> <td>If the value is set to <code>true</code> then this task, upon completion of the test execution, prints the summary of the execution to <code>System.out</code>. The summary itself is generated by the JUnit 5 platform and not by this task. </td> <td>No; defaults to <code>false</code></td> </tr> </table> <h3 id="nested">Nested Elements</h3> <h4>classpath</h4> <p> The nested <code><classpath></code> element that represents a <a href="../using.html#path">PATH like structure</a> can be used to configure the task to use this classpath for finding and running the tests. This classpath will be used for: </p> <ul> <li>Finding the test classes to execute</li> <li>Finding test engines that run the tests</li> </ul> <p> If the <code>classpath</code> element isn't configured for the task, then the classpath of Ant itself will be used for finding the test classes. </p> <h5 id="test-engine-in-classpath">Using the classpath element to include test engines</h5> <p> The <code><classpath></code> can be used to include the test engines that you want to be considered for execution of the tests. </p> <p> <strong>NOTE:</strong> An important aspect to remember is that whether or not you use this approach, the JUnit 5 platform libraries <a href="#junit-platform-libraries">listed earlier in this document</a> and the <code>ant-junitlauncher.jar</code>, <i>shouldn't</i> be part of this classpath and instead they must be included in Ant runtime's classpath either by placing them in <code>ANT_HOME/lib</code> or by passing the <code>-lib</code> option. </p> <p> 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 <code>ant-junitlauncher.jar</code> have been setup as explained previously. <br/> <pre> <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> </pre> In the example above, the <code>src/lib/jupiter</code> directory is expected to contain the Jupiter test engine related jars (which have been <a href="#junit-jupiter-engine-libraries">listed in an earlier section of this document</a>). In the <code>test</code> target we use the <code>classpath</code> nested element to point to the <code>junit.engine.jupiter.classpath</code> containing those jars. In this <code>test</code> target we also use another <code>classpath</code> element to point to the location containing our test classes. If required, both these classpath can be combined into one. </p> <h4>listener</h4> <p> The <code>junitlauncher</code> task can be configured with <code>listener</code>(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 <code class="code">org.junit.platform.launcher.TestExecutionListener</code>. This <code class="code">TestExecutionListener</code> 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 <code class="code">TestExecutionListener</code> in this task. </p> <h5>Test result formatter</h5> <p> <code>junitlauncher</code> 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 <code>listener</code> element. As noted previously, the <code>listener</code> element expects the listener to implement the <code class="code">org.junit.platform.launcher.TestExecutionListener</code> 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 <code class="code">org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter</code> interface. This interface is specific to Ant <code>junitlauncher</code> task and it extends the <code class="code">org.junit.platform.launcher.TestExecutionListener</code> interface </p> <p> The <code>junitlauncher</code> task comes with the following pre-defined test result formatter types: </p> <ul> <li> <q>legacy-plain</q> : This formatter prints a short statistics line for all test cases. </li> <li> <q>legacy-brief</q> : This formatter prints information for tests that failed or were skipped. </li> <li> <q>legacy-xml</q> : This formatter prints statistics for the tests in XML format. </li> </ul> <p> <strong>Note</strong>: Each of these formatters named <q>legacy</q> try to format the results similar to what the <code>junit</code> task's formatters used to do. Furthermore, the <q>legacy-xml</q> formatter generates the XML to comply with the same schema that the <code>junit</code> task's XML formatter used to follow. As a result, the XML generated by this formatter, can be used as-is by the <code>junitreport</code> task. </p> <p> The <code>listener</code> element supports the following attributes: </p> <table class="attr"> <tr> <th scope="col">Attribute</th> <th scope="col">Description</th> <th scope="col">Required</th> </tr> <tr> <td>type</td> <td>Use a predefined formatter (either <q>legacy-xml</q>, <q>legacy-plain</q> or <q>legacy-brief</q>).</td> <td rowspan="2">Exactly one of these</td> </tr> <tr> <td>classname</td> <td class="left">Name of a listener class which implements <code>org.junit.platform.launcher.TestExecutionListener</code> or the <code>org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter</code> interface </td> </tr> <tr> <td>resultFile</td> <td> The file name to which the formatted result needs to be written to. This attribute is only relevant when the listener class implements the <code>org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter</code> interface. <p> If no value is specified for this attribute and the listener implements the <code>org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter</code> then the file name will be defaulted to and will be of the form <code>TEST-<i>testname</i>.<i>formatter-specific-extension</i></code> (ex: <samp>TEST-org.myapp.SomeTest.xml</samp> for the <q>legacy-xml</q> type formatter) </p> </td> <td>No</td> </tr> <tr> <td>sendSysOut</td> <td>If set to <q>true</q> then the listener will be passed the <code>stdout</code> content generated by the test(s). This attribute is relevant only if the listener class implements the <code>org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter</code> interface.</td> <td>No; defaults to <q>false</q></td> </tr> <tr> <td>sendSysErr</td> <td>If set to <q>true</q> then the listener will be passed the <code>stderr</code> content generated by the test(s). This attribute is relevant only if the listener class implements the <code>org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter</code> interface.</td> <td>No; defaults to <q>false</q></td> </tr> <tr> <td>if</td> <td>Only use this listener <a href="../properties.html#if+unless">if the named property is set</a>.</td> <td>No</td> </tr> <tr> <td>unless</td> <td>Only use this listener <a href="../properties.html#if+unless">if the named property is <strong>not</strong> set</a>.</td> <td>No</td> </tr> </table> <h4>test</h4> <p>Defines a single test class.</p> <table class="attr"> <tr> <th scope="col">Attribute</th> <th scope="col">Description</th> <th scope="col">Required</th> </tr> <tr> <td>name</td> <td>Fully qualified name of the test class.</td> <td>Yes</td> </tr> <tr> <td>methods</td> <td>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.</td> <td>No</td> </tr> <tr> <td>haltOnFailure</td> <td>Stop the build process if a failure occurs during the test run (exceptions are considered as failures too). Overrides value set on <code>junitlauncher</code> element.</td> <td>No</td> </tr> <tr> <td>failureProperty</td> <td>The name of a property to set in the event of a failure (exceptions are considered failures as well). Overrides value set on <code>junitlauncher</code> element.</td> <td>No</td> </tr> <tr> <td>outputDir</td> <td>Directory to write the reports to.</td> <td>No; default is the base directory of the project.</td> </tr> <tr> <td>if</td> <td>Only run this test <a href="../properties.html#if+unless">if the named property is set</a>.</td> <td>No</td> </tr> <tr> <td>unless</td> <td>Only run this test <a href="../properties.html#if+unless">if the named property is <strong>not</strong> set</a>.</td> <td>No</td> </tr> <tr> <td>includeEngines</td> <td>A comma separated set of test engine ids. If specified, only these test engine(s) will be used for running the tests. <br/> For example: <code>includeEngines="junit-jupiter"</code> 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. </td> <td>No</td> </tr> <tr> <td>excludeEngines</td> <td>A comma separated set of test engine ids. If specified, these test engine(s) will be excluded when running the tests. <br/> For example: <code>excludeEngines="junit-vintage"</code> 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. </td> <td>No</td> </tr> </table> <p> Tests can define their own listeners via nested <code>listener</code> elements. </p> <h4>testclasses</h4> <p>Define a number of tests based on pattern matching.</p> <p> <code>testclasses</code> collects the included <a href="../Types/resources.html">resources</a> from any number of nested <a href="../Types/resources.html#collection">Resource Collection</a>s. It then selects each resource whose name ends in <code>.class</code>. These classes are then passed on to the JUnit 5 platform for it to decide and run them as tests. </p> <table class="attr"> <tr> <th scope="col">Attribute</th> <th scope="col">Description</th> <th scope="col">Required</th> </tr> <tr> <td>haltOnFailure</td> <td>Stop the build process if a failure occurs during the test run (exceptions are considered as failures too). Overrides value set on <code>junitlauncher</code> element.</td> <td>No</td> </tr> <tr> <td>failureProperty</td> <td>The name of a property to set in the event of a failure (exceptions are considered failures as well). Overrides value set on <code>junitlauncher</code> element.</td> <td>No</td> </tr> <tr> <td>outputDir</td> <td>Directory to write the reports to.</td> <td>No; default is the base directory of the project.</td> </tr> <tr> <td>if</td> <td>Only run the tests <a href="../properties.html#if+unless">if the named property is set</a>.</td> <td>No</td> </tr> <tr> <td>unless</td> <td>Only run the tests <a href="../properties.html#if+unless">if the named property is <strong>not</strong> set</a>.</td> <td>No</td> </tr> <tr> <td>includeEngines</td> <td>A comma separated set of test engine ids. If specified, only these test engine(s) will be used for running the tests. <br/> For example: <code>includeEngines="junit-jupiter"</code> 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. </td> <td>No</td> </tr> <tr> <td>excludeEngines</td> <td>A comma separated set of test engine ids. If specified, these test engine(s) will be excluded when running the tests. <br/> For example: <code>excludeEngines="junit-vintage"</code> 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. </td> <td>No</td> </tr> </table> <p> <code>testclasses</code> can define their own listeners via nested <code>listener</code> elements. </p> <h3>Examples</h3> <p> Launch the JUnit 5 platform to run the <samp>org.myapp.SimpleTest</samp> test </p> <pre> <path id="test.classpath"> ... </path> <junitlauncher> <classpath refid="test.classpath"/> <test name="org.myapp.SimpleTest"/> </junitlauncher></pre> <p> Launch the JUnit 5 platform to run the <samp>org.myapp.SimpleTest</samp> and the <samp>org.myapp.AnotherTest</samp> tests. The build process will be stopped if any test, in the <samp>org.myapp.SimpleTest</samp>, fails. </p> <pre> <junitlauncher> <classpath refid="test.classpath"/> <test name="org.myapp.SimpleTest" haltOnFailure="true"/> <test name="org.myapp.AnotherTest"/> </junitlauncher> </pre> <p> Launch the JUnit 5 platform to run only the <samp>testFoo</samp> and <samp>testBar</samp> methods of the <samp>org.myapp.SimpleTest</samp> test class. </p> <pre> <junitlauncher> <classpath refid="test.classpath"/> <test name="org.myapp.SimpleTest" methods="testFoo, testBar"/> </junitlauncher></pre> <p> Select any <samp>.class</samp> files that match the <samp>org/example/**/tests/**/</samp> <code>fileset</code> filter, under the <samp>${build.classes.dir}</samp> and passes those classes to the JUnit 5 platform for execution as tests. </p> <pre> <junitlauncher> <classpath refid="test.classpath"/> <testclasses outputdir="${output.dir}"> <fileset dir="${build.classes.dir}"> <include name="org/example/**/tests/**/"/> </fileset> </testclasses> </junitlauncher></pre> <p> Select any <samp>.class</samp> files that match the <samp>org/example/**/tests/**/</samp> <code>fileset</code> filter, under the <samp>${build.classes.dir}</samp> and pass those classes to the JUnit 5 platform for execution as tests. Test results will be written out to the <samp>${output.dir}</samp> by the <q>legacy-xml</q> and <q>legacy-plain</q> formatters, in separate files. Furthermore, both the <q>legacy-xml</q> and the <q>legacy-plain</q> listeners, above, are configured to receive the standard output content generated by the tests. The <q>legacy-xml</q> listener is configured to receive standard error content as well. </p> <pre> <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></pre> </body> </html>