View Javadoc
1   package org.apache.maven.plugin.failsafe;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.plugin.MojoExecutionException;
23  import org.apache.maven.plugin.MojoFailureException;
24  import org.apache.maven.plugin.surefire.AbstractSurefireMojo;
25  import org.apache.maven.plugin.surefire.booterclient.ChecksumCalculator;
26  import org.apache.maven.plugins.annotations.LifecyclePhase;
27  import org.apache.maven.plugins.annotations.Mojo;
28  import org.apache.maven.plugins.annotations.Parameter;
29  import org.apache.maven.plugins.annotations.ResolutionScope;
30  import org.apache.maven.surefire.extensions.ForkNodeFactory;
31  import org.apache.maven.surefire.api.suite.RunResult;
32  
33  import java.io.File;
34  import java.io.IOException;
35  import java.util.Arrays;
36  import java.util.Collections;
37  import java.util.List;
38  
39  import static org.apache.maven.plugin.failsafe.util.FailsafeSummaryXmlUtils.writeSummary;
40  
41  /**
42   * Run integration tests using Surefire.
43   *
44   * @author Jason van Zyl
45   * @author Stephen Connolly
46   */
47  @Mojo( name = "integration-test", requiresProject = true, requiresDependencyResolution = ResolutionScope.TEST,
48               defaultPhase = LifecyclePhase.INTEGRATION_TEST, threadSafe = true )
49  public class IntegrationTestMojo
50          extends AbstractSurefireMojo
51  {
52  
53      private static final String FAILSAFE_IN_PROGRESS_CONTEXT_KEY = "failsafe-in-progress";
54  
55      /**
56       * The path representing project <em>JAR</em> file, if exists; Otherwise the directory containing generated
57       * classes of the project being tested. This will be included after the test classes in the test classpath.
58       * Defaults to built artifact <em>JAR</em> file or <code>${project.build.outputDirectory}</code>.
59       */
60      @Parameter
61      private File classesDirectory;
62  
63      @Parameter( defaultValue = "${project.build.outputDirectory}", readonly = true, required = true )
64      private File defaultClassesDirectory;
65  
66      /**
67       * Set this to "true" to skip running integration tests, but still compile them. Its use is NOT RECOMMENDED, but
68       * quite convenient on occasion.
69       *
70       * @since 2.4.3-alpha-2
71       */
72      @Parameter( property = "skipITs" )
73      private boolean skipITs;
74  
75      /**
76       * Base directory where all reports are written to.
77       */
78      @Parameter( defaultValue = "${project.build.directory}/failsafe-reports" )
79      private File reportsDirectory;
80  
81      @SuppressWarnings( "checkstyle:linelength" )
82      /**
83       * Specify this parameter to run individual tests by file name, overriding parameter {@code includes} and
84       * {@code excludes}. Each pattern you specify here will be used to create an include pattern formatted like
85       * <code>**{@literal /}${it.test}.java</code>, so you can just type {@code -Dit.test=MyIT} to run
86       * a single test file called "foo/MyIT.java". The test patterns prefixed with a <em>!</em> will be excluded.
87       * <br>
88       * This parameter overrides the parameter {@code includes} and {@code excludes}, and the TestNG parameter
89       * {@code suiteXmlFiles}.
90       * <br>
91       * Since 2.7.3 You can execute a limited number of methods in the test with adding <i>#myMethod</i> or
92       * <i>#my*ethod</i>. E.g. type {@code -Dit.test=MyIT#myMethod} <b>supported for junit 4.x and TestNg.</b>
93       * <br>
94       * Since 2.19 a complex syntax is supported in one parameter (JUnit 4, JUnit 4.7+, TestNG):
95       * <pre><code>"-Dit.test=???IT, !Unstable*, pkg{@literal /}**{@literal /}Ci*leIT.java, *IT#test*One+testTwo?????, #fast*+slowTest"</code></pre>
96       * or e.g.
97       * <br>
98       * <pre><code>"-Dit.test=Basic*, !%regex[.*.Unstable.*], !%regex[.*.MyIT.class#one.*|two.*], %regex[#fast.*|slow.*]"</code></pre>
99       * <br>
100      * The Parameterized JUnit runner {@code describes} test methods using an index in brackets, so the non-regex
101      * method pattern would become: {@code #testMethod[*]}. If using <code>@Parameters(name="{index}: fib({0})={1}")</code>
102      * and selecting the index e.g. 5 in pattern, the non-regex method pattern would become {@code #testMethod[5:*]}.
103      */
104     @Parameter( property = "it.test" )
105     private String test;
106 
107     /**
108      * The summary file to write integration test results to.
109      */
110     @Parameter( defaultValue = "${project.build.directory}/failsafe-reports/failsafe-summary.xml", required = true )
111     private File summaryFile;
112 
113     /**
114      * Option to print summary of test suites or just print the test cases that have errors.
115      */
116     @Parameter( property = "failsafe.printSummary", defaultValue = "true" )
117     private boolean printSummary;
118 
119     /**
120      * Selects the formatting for the test report to be generated. Can be set as "brief" or "plain".
121      * Only applies to the output format of the output files  (target/surefire-reports/testName.txt)
122      */
123     @Parameter( property = "failsafe.reportFormat", defaultValue = "brief" )
124     private String reportFormat;
125 
126     /**
127      * Option to generate a file test report or just output the test report to the console.
128      */
129     @Parameter( property = "failsafe.useFile", defaultValue = "true" )
130     private boolean useFile;
131 
132     /**
133      * Set this to "true" to cause a failure if none of the tests specified in -Dtest=... are run. Defaults to
134      * "true".
135      *
136      * @since 2.12
137      */
138     @Parameter( property = "it.failIfNoSpecifiedTests", defaultValue = "true" )
139     private boolean failIfNoSpecifiedTests;
140 
141     /**
142      * Attach a debugger to the forked JVM. If set to "true", the process will suspend and wait for a debugger to attach
143      * on port 5005. If set to some other string, that string will be appended to the argLine, allowing you to configure
144      * arbitrary debugging ability options (without overwriting the other options specified through the {@code argLine}
145      * parameter).
146      *
147      * @since 2.4
148      */
149     @Parameter( property = "maven.failsafe.debug" )
150     private String debugForkedProcess;
151 
152     /**
153      * Kill the forked test process after a certain number of seconds. If set to 0, wait forever for the process, never
154      * timing out.
155      *
156      * @since 2.4
157      */
158     @Parameter( property = "failsafe.timeout" )
159     private int forkedProcessTimeoutInSeconds;
160 
161     /**
162      * Forked process is normally terminated without any significant delay after given tests have completed.
163      * If the particular tests started non-daemon Thread(s), the process hangs instead of been properly terminated
164      * by {@code System.exit()}. Use this parameter in order to determine the timeout of terminating the process.
165      * <a href="http://maven.apache.org/surefire/maven-failsafe-plugin/examples/shutdown.html">see the documentation:
166      * http://maven.apache.org/surefire/maven-failsafe-plugin/examples/shutdown.html</a>
167      *
168      * @since 2.20
169      */
170     @Parameter( property = "failsafe.exitTimeout", defaultValue = "30" )
171     private int forkedProcessExitTimeoutInSeconds;
172 
173     /**
174      * Stop executing queued parallel JUnit tests after a certain number of seconds.
175      * <br>
176      * Example values: "3.5", "4"<br>
177      * <br>
178      * If set to 0, wait forever, never timing out.
179      * Makes sense with specified {@code parallel} different from "none".
180      *
181      * @since 2.16
182      */
183     @Parameter( property = "failsafe.parallel.timeout" )
184     private double parallelTestsTimeoutInSeconds;
185 
186     /**
187      * Stop executing queued parallel JUnit tests
188      * and <i>interrupt</i> currently running tests after a certain number of seconds.
189      * <br>
190      * Example values: "3.5", "4"<br>
191      * <br>
192      * If set to 0, wait forever, never timing out.
193      * Makes sense with specified {@code parallel} different from "none".
194      *
195      * @since 2.16
196      */
197     @Parameter( property = "failsafe.parallel.forcedTimeout" )
198     private double parallelTestsTimeoutForcedInSeconds;
199 
200     @SuppressWarnings( "checkstyle:linelength" )
201     /**
202      * A list of {@literal <include>} elements specifying the test filter (by pattern) of tests which should be
203      * included in testing. If it is not specified and the {@code test} parameter is unspecified as well, the default
204      * includes is
205      * <pre><code>
206      * {@literal <includes>}
207      *     {@literal <include>}**{@literal /}IT*.java{@literal </include>}
208      *     {@literal <include>}**{@literal /}*IT.java{@literal </include>}
209      *     {@literal <include>}**{@literal /}*ITCase.java{@literal </include>}
210      * {@literal </includes>}
211      * </code></pre>
212      * <br>
213      * Each include item may also contain a comma-separated sublist of items, which will be treated as multiple
214      * {@literal <include>} entries.<br>
215      * Since 2.19 a complex syntax is supported in one parameter (JUnit 4, JUnit 4.7+, TestNG):
216      * <pre><code>
217      * {@literal <include>}%regex[.*[Cat|Dog].*], Basic????, !Unstable*{@literal </include>}
218      * {@literal <include>}%regex[.*[Cat|Dog].*], !%regex[pkg.*Slow.*.class], pkg{@literal /}**{@literal /}*Fast*.java{@literal </include>}
219      * </code></pre>
220      * <br>
221      * This parameter is ignored if the TestNG {@code suiteXmlFiles} parameter is specified.<br>
222      * <br>
223      * <b>Notice that</b> these values are relative to the directory containing generated test classes of the project
224      * being tested. This directory is declared by the parameter {@code testClassesDirectory} which defaults
225      * to the POM property <code>${project.build.testOutputDirectory}</code>, typically
226      * <code>{@literal src/test/java}</code> unless overridden.
227      */
228     @Parameter( property = "failsafe.includes" )
229     // TODO use regex for fully qualified class names in 3.0 and change the filtering abilities
230     private List<String> includes;
231 
232     /**
233      * A list of {@literal <exclude>} elements specifying the tests (by pattern) that should be excluded in testing.
234      * When not specified and when the {@code test} parameter is not specified, the default excludes will be <br>
235      * <pre><code>
236      * {@literal <excludes>}
237      *     {@literal <exclude>}**{@literal /}*$*{@literal </exclude>}
238      * {@literal </excludes>}
239      * </code></pre>
240      * (which excludes all inner classes).
241      * <br>
242      * This parameter is ignored if the TestNG {@code suiteXmlFiles} parameter is specified.
243      * <br>
244      * Each exclude item may also contain a comma-separated sub-list of items, which will be treated as multiple
245      * {@literal <exclude>} entries.<br>
246      * Since 2.19 a complex syntax is supported in one parameter (JUnit 4, JUnit 4.7+, TestNG):
247      * <pre><code>
248      * {@literal <exclude>}%regex[pkg.*Slow.*.class], Unstable*{@literal </exclude>}
249      * </code></pre>
250      * <br>
251      * <b>Notice that</b> these values are relative to the directory containing generated test classes of the project
252      * being tested. This directory is declared by the parameter {@code testClassesDirectory} which defaults
253      * to the POM property <code>${project.build.testOutputDirectory}</code>, typically
254      * <code>{@literal src/test/java}</code> unless overridden.
255      */
256     @Parameter( property = "failsafe.excludes" )
257     // TODO use regex for fully qualified class names in 3.0 and change the filtering abilities
258     private List<String> excludes;
259 
260     /**
261      * Option to pass dependencies to the system's classloader instead of using an isolated class loader when forking.
262      * Prevents problems with JDKs which implement the service provider lookup mechanism by using the system's
263      * classloader.
264      *
265      * @since 2.3
266      */
267     @Parameter( property = "failsafe.useSystemClassLoader", defaultValue = "true" )
268     private boolean useSystemClassLoader;
269 
270     /**
271      * By default, Surefire forks your tests using a manifest-only JAR; set this parameter to "false" to force it to
272      * launch your tests with a plain old Java classpath. (See the
273      * <a href="http://maven.apache.org/plugins/maven-failsafe-plugin/examples/class-loading.html">
274      * http://maven.apache.org/plugins/maven-failsafe-plugin/examples/class-loading.html</a>
275      * for a more detailed explanation of manifest-only JARs and their benefits.)
276      * <br>
277      * Beware, setting this to "false" may cause your tests to fail on Windows if your classpath is too long.
278      *
279      * @since 2.4.3
280      */
281     @Parameter( property = "failsafe.useManifestOnlyJar", defaultValue = "true" )
282     private boolean useManifestOnlyJar;
283 
284     /**
285      * The character encoding scheme to be applied while generating test report
286      * files (see target/surefire-reports/yourTestName.txt).
287      * The report output files (*-out.txt) are still encoded with JVM's encoding used in standard out/err pipes.
288      *
289      * @since 3.0.0-M1
290      */
291     @Parameter( property = "encoding", defaultValue = "${project.reporting.outputEncoding}" )
292     private String encoding;
293 
294     /**
295      * (JUnit 4+ providers and JUnit 5+ providers since 3.0.0-M4)
296      * The number of times each failing test will be rerun. If set larger than 0, rerun failing tests immediately after
297      * they fail. If a failing test passes in any of those reruns, it will be marked as pass and reported as a "flake".
298      * However, all the failing attempts will be recorded.
299      */
300     @Parameter( property = "failsafe.rerunFailingTestsCount", defaultValue = "0" )
301     private int rerunFailingTestsCount;
302 
303     /**
304      * (TestNG) List of &lt;suiteXmlFile&gt; elements specifying TestNG suite xml file locations. Note that
305      * {@code suiteXmlFiles} is incompatible with several other parameters of this plugin, like
306      * {@code includes} and {@code excludes}.<br>
307      * This parameter is ignored if the {@code test} parameter is specified (allowing you to run a single test
308      * instead of an entire suite).
309      *
310      * @since 2.2
311      */
312     @Parameter( property = "failsafe.suiteXmlFiles" )
313     private File[] suiteXmlFiles;
314 
315     /**
316      * Defines the order the tests will be run in. Supported values are {@code alphabetical},
317      * {@code reversealphabetical}, {@code random}, {@code hourly} (alphabetical on even hours, reverse alphabetical
318      * on odd hours), {@code failedfirst}, {@code balanced} and {@code filesystem}.
319      * <br>
320      * <br>
321      * Odd/Even for hourly is determined at the time the of scanning the classpath, meaning it could change during a
322      * multi-module build.
323      * <br>
324      * <br>
325      * Failed first will run tests that failed on previous run first, as well as new tests for this run.
326      * <br>
327      * <br>
328      * Balanced is only relevant with parallel=classes, and will try to optimize the run-order of the tests reducing the
329      * overall execution time. Initially a statistics file is created and every next test run will reorder classes.
330      * <br>
331      * <br>
332      * Note that the statistics are stored in a file named <b>.surefire-XXXXXXXXX</b> beside <i>pom.xml</i> and
333      * should not be checked into version control. The "XXXXX" is the SHA1 checksum of the entire surefire
334      * configuration, so different configurations will have different statistics files, meaning if you change any
335      * configuration settings you will re-run once before new statistics data can be established.
336      *
337      * @since 2.7
338      */
339     @Parameter( property = "failsafe.runOrder", defaultValue = "filesystem" )
340     private String runOrder;
341 
342     /**
343      * Sets the random seed that will be used to order the tests if {@code failsafe.runOrder} is set to {@code random}.
344      * <br>
345      * <br>
346      * If no seeds are set and {@code failsafe.runOrder} is set to {@code random}, then the seed used will be
347      * outputted (search for "To reproduce ordering use flag -Dfailsafe.runOrder.random.seed").
348      * <br>
349      * <br>
350      * To deterministically reproduce any random test order that was run before, simply set the seed to
351      * be the same value.
352      *
353      * @since 3.0.0-M6
354      */
355     @Parameter( property = "failsafe.runOrder.random.seed" )
356     private Long runOrderRandomSeed;
357 
358     /**
359      * A file containing include patterns, each in a next line. Blank lines, or lines starting with # are ignored.
360      * If {@code includes} are also specified, these patterns are appended. Example with path, simple and regex
361      * includes:
362      * <pre><code>
363      * *{@literal /}it{@literal /}*
364      * **{@literal /}NotIncludedByDefault.java
365      * %regex[.*IT.*|.*Not.*]
366      * </code></pre>
367      * <br>
368      * Since 3.0.0-M6, method filtering support is provided in the inclusions file as well, example:
369      * <pre><code>
370      * pkg.SomeIT#testMethod
371      * </code></pre>
372      *
373      * @since 2.13
374      */
375     @Parameter( property = "failsafe.includesFile" )
376     private File includesFile;
377 
378     /**
379      * A file containing exclude patterns, each in a next line. Blank lines, or lines starting with # are ignored.
380      * If {@code excludes} are also specified, these patterns are appended.
381      * Example with path, simple and regex excludes:
382      * <pre><code>
383      * *{@literal /}it{@literal /}*
384      * **{@literal /}DontRunIT.*
385      * %regex[.*IT.*|.*Not.*]
386      * </code></pre>
387      * <br>
388      * Since 3.0.0-M6, method filtering support is provided in the exclusions file as well, example:
389      * <pre><code>
390      * pkg.SomeIT#testMethod
391      * </code></pre>
392      *
393      * @since 2.13
394      */
395     @Parameter( property = "failsafe.excludesFile" )
396     private File excludesFile;
397 
398     /**
399      * Set to error/failure count in order to skip remaining tests.
400      * Due to race conditions in parallel/forked execution this may not be fully guaranteed.<br>
401      * Enable with system property {@code -Dfailsafe.skipAfterFailureCount=1} or any number greater than zero.
402      * Defaults to "0".<br>
403      * See the prerequisites and limitations in documentation:<br>
404      * <a href="http://maven.apache.org/plugins/maven-failsafe-plugin/examples/skip-after-failure.html">
405      * http://maven.apache.org/plugins/maven-failsafe-plugin/examples/skip-after-failure.html</a>
406      *
407      * @since 2.19
408      */
409     @Parameter( property = "failsafe.skipAfterFailureCount", defaultValue = "0" )
410     private int skipAfterFailureCount;
411 
412     /**
413      * After the plugin process is shutdown by sending <i>SIGTERM signal (CTRL+C)</i>, <i>SHUTDOWN command</i> is
414      * received by every forked JVM.
415      * <br>
416      * The value is set to ({@code shutdown=exit}) by default (changed in version 3.0.0-M4).
417      * <br>
418      * The parameter can be configured with other two values {@code testset} and {@code kill}.
419      * <br>
420      * With({@code shutdown=testset}) the test set may still continue to run in forked JVM.
421      * <br>
422      * Using {@code exit} forked JVM executes {@code System.exit(1)} after the plugin process has received
423      * <i>SIGTERM signal</i>.
424      * <br>
425      * Using {@code kill} the JVM executes {@code Runtime.halt(1)} and kills itself.
426      *
427      * @since 2.19
428      */
429     @Parameter( property = "failsafe.shutdown", defaultValue = "exit" )
430     private String shutdown;
431 
432     /**
433      * When {@code true}, uses the modulepath when executing with JDK 9+ and <i>module-info.java</i> is
434      * present. When {@code false}, always uses the classpath.
435      * <br>
436      * Defaults to {@code true}.
437      *
438      * @since 3.0.0-M2
439      */
440     @Parameter( property = "failsafe.useModulePath", defaultValue = "true" )
441     private boolean useModulePath;
442 
443     /**
444      * This parameter configures the forked node. Currently, you can select the communication protocol, i.e. process
445      * pipes or TCP/IP sockets.
446      * The plugin uses process pipes by default which will be turned to TCP/IP in the version 3.0.0.
447      * Alternatively, you can implement your own factory and SPI.
448      * <br>
449      * See the documentation for more details:<br>
450      * <a href="https://maven.apache.org/plugins/maven-surefire-plugin/examples/process-communication.html">
451      *     https://maven.apache.org/plugins/maven-surefire-plugin/examples/process-communication.html</a>
452      *
453      * @since 3.0.0-M5
454      */
455     @Parameter( property = "failsafe.forkNode" )
456     private ForkNodeFactory forkNode;
457 
458     /**
459      * You can selectively exclude individual environment variables by enumerating their keys.
460      * <br>
461      * The environment is a system-dependent mapping from keys to values which is inherited from the Maven process
462      * to the forked Surefire processes. The keys must literally (case sensitive) match in order to exclude
463      * their environment variable.
464      * <br>
465      * Example to exclude three environment variables:
466      * <br>
467      * <i>mvn test -Dfailsafe.excludedEnvironmentVariables=ACME1,ACME2,ACME3</i>
468      *
469      * @since 3.0.0-M4
470      */
471     @Parameter( property = "failsafe.excludedEnvironmentVariables" )
472     private String[] excludedEnvironmentVariables;
473 
474     /**
475      * Since 3.0.0-M4 the process checkers are disabled.
476      * You can enable them namely by setting {@code ping} and {@code native} or {@code all} in this parameter.
477      * <br>
478      * The checker is useful in situations when you kill the build on a CI system and you want the Surefire forked JVM
479      * to kill the tests asap and free all handlers on the file system been previously used by the JVM and by the tests.
480      *
481      * <br>
482      *
483      * The {@code ping} should be safely used together with ZGC or Shenandoah Garbage Collector.
484      * Due to the {@code ping} relies on timing of the PING (triggered every 30 seconds), slow GCs may pause
485      * the timers and pretend that the parent process of the forked JVM does not exist.
486      *
487      * <br>
488      *
489      * The {@code native} is very fast checker.
490      * It is useful mechanism on Unix based systems, Linux distributions and Alpine/BusyBox Linux.
491      * See the JIRA <a href="https://issues.apache.org/jira/browse/SUREFIRE-1631">SUREFIRE-1631</a> for Windows issues.
492      *
493      * <br>
494      *
495      * Another useful configuration parameter is {@code forkedProcessTimeoutInSeconds}.
496      * <br>
497      * See the Frequently Asked Questions page with more details:<br>
498      * <a href="http://maven.apache.org/surefire/maven-surefire-plugin/faq.html#kill-jvm">
499      *     http://maven.apache.org/surefire/maven-surefire-plugin/faq.html#kill-jvm</a>
500      * <br>
501      * <a href="http://maven.apache.org/surefire/maven-failsafe-plugin/faq.html#kill-jvm">
502      *     http://maven.apache.org/surefire/maven-failsafe-plugin/faq.html#kill-jvm</a>
503      *
504      * <br>
505      *
506      * Example of use:
507      * <br>
508      * <i>mvn test -Dfailsafe.enableProcessChecker=all</i>
509      *
510      * @since 3.0.0-M4
511      */
512     @Parameter( property = "failsafe.enableProcessChecker" )
513     private String enableProcessChecker;
514 
515     @Parameter( property = "failsafe.systemPropertiesFile" )
516     private File systemPropertiesFile;
517 
518     /**
519      * Provide the ID/s of an JUnit engine to be included in the test run.
520      *
521      * @since 3.0.0-M6
522      */
523     @Parameter( property = "includeJUnit5Engines" )
524     private String[] includeJUnit5Engines;
525 
526     /**
527      * Provide the ID/s of an JUnit engine to be excluded in the test run.
528      *
529      * @since 3.0.0-M6
530      */
531     @Parameter( property = "excludeJUnit5Engines" )
532     private String[] excludeJUnit5Engines;
533 
534     @Override
535     protected int getRerunFailingTestsCount()
536     {
537         return rerunFailingTestsCount;
538     }
539 
540     @Override
541     @SuppressWarnings( "unchecked" )
542     protected void handleSummary( RunResult summary, Exception firstForkException )
543             throws MojoExecutionException, MojoFailureException
544     {
545         File summaryFile = getSummaryFile();
546         if ( !summaryFile.getParentFile().isDirectory() )
547         {
548             //noinspection ResultOfMethodCallIgnored
549             summaryFile.getParentFile().mkdirs();
550         }
551 
552         try
553         {
554             Object token = getPluginContext().get( FAILSAFE_IN_PROGRESS_CONTEXT_KEY );
555             writeSummary( summary, summaryFile, token != null );
556         }
557         catch ( Exception e )
558         {
559             throw new MojoExecutionException( e.getMessage(), e );
560         }
561 
562         getPluginContext().put( FAILSAFE_IN_PROGRESS_CONTEXT_KEY, FAILSAFE_IN_PROGRESS_CONTEXT_KEY );
563     }
564 
565     private boolean isJarArtifact( File artifactFile )
566     {
567         return artifactFile != null && artifactFile.isFile() && artifactFile.getName().toLowerCase().endsWith( ".jar" );
568     }
569 
570     private static File toAbsoluteCanonical( File f )
571     {
572         try
573         {
574             return f == null ? null : f.getAbsoluteFile().getCanonicalFile();
575         }
576         catch ( IOException e )
577         {
578             throw new IllegalStateException( e.getLocalizedMessage(), e );
579         }
580     }
581 
582     @Override
583     @SuppressWarnings( "deprecation" )
584     protected boolean isSkipExecution()
585     {
586         return isSkip() || isSkipTests() || isSkipITs() || isSkipExec();
587     }
588 
589     @Override
590     protected String getPluginName()
591     {
592         return "failsafe";
593     }
594 
595     @Override
596     protected String[] getDefaultIncludes()
597     {
598         return new String[]{ "**/IT*.java", "**/*IT.java", "**/*ITCase.java" };
599     }
600 
601     @Override
602     protected String getReportSchemaLocation()
603     {
604         return "https://maven.apache.org/surefire/maven-failsafe-plugin/xsd/failsafe-test-report-3.0.xsd";
605     }
606 
607     @Override
608     public boolean isSkipTests()
609     {
610         return skipTests;
611     }
612 
613     @Override
614     @Deprecated
615     public void setSkipTests( boolean skipTests )
616     {
617         this.skipTests = skipTests;
618     }
619 
620     public boolean isSkipITs()
621     {
622         return skipITs;
623     }
624 
625     public void setSkipITs( boolean skipITs )
626     {
627         this.skipITs = skipITs;
628     }
629 
630     @Override
631     @SuppressWarnings( "deprecation" )
632     @Deprecated
633     public boolean isSkipExec()
634     {
635         return skipExec;
636     }
637 
638     @Override
639     @SuppressWarnings( "deprecation" )
640     @Deprecated
641     public void setSkipExec( boolean skipExec )
642     {
643         this.skipExec = skipExec;
644     }
645 
646     @Override
647     public boolean isSkip()
648     {
649         return skip;
650     }
651 
652     @Override
653     public void setSkip( boolean skip )
654     {
655         this.skip = skip;
656     }
657 
658     @Override
659     public File getBasedir()
660     {
661         return basedir;
662     }
663 
664     @Override
665     public void setBasedir( File basedir )
666     {
667         this.basedir = basedir;
668     }
669 
670     @Override
671     public File getTestClassesDirectory()
672     {
673         return testClassesDirectory;
674     }
675 
676     @Override
677     public void setTestClassesDirectory( File testClassesDirectory )
678     {
679         this.testClassesDirectory = testClassesDirectory;
680     }
681 
682     /**
683      * @return Output directory, or artifact file if artifact type is "jar". If not forking the JVM, parameter
684      * {@link #useSystemClassLoader} is ignored and the {@link org.apache.maven.surefire.booter.IsolatedClassLoader} is
685      * used instead. See the resolution of {@link #getClassLoaderConfiguration() ClassLoaderConfiguration}.
686      */
687     @Override
688     public File getMainBuildPath()
689     {
690         File artifact = getProject().getArtifact().getFile();
691         boolean isDefaultClsDir = classesDirectory == null;
692         return isDefaultClsDir ? ( isJarArtifact( artifact ) ? artifact : defaultClassesDirectory ) : classesDirectory;
693     }
694 
695     @Override
696     public void setMainBuildPath( File mainBuildPath )
697     {
698         classesDirectory = toAbsoluteCanonical( mainBuildPath );
699     }
700 
701     public void setDefaultClassesDirectory( File defaultClassesDirectory )
702     {
703         this.defaultClassesDirectory = toAbsoluteCanonical( defaultClassesDirectory );
704     }
705 
706     @Override
707     public File getReportsDirectory()
708     {
709         return reportsDirectory;
710     }
711 
712     @Override
713     public void setReportsDirectory( File reportsDirectory )
714     {
715         this.reportsDirectory = reportsDirectory;
716     }
717 
718     @Override
719     public String getTest()
720     {
721         return test;
722     }
723 
724     @Override
725     public void setTest( String test )
726     {
727         this.test = test;
728     }
729 
730     public File getSummaryFile()
731     {
732         return summaryFile;
733     }
734 
735     public void setSummaryFile( File summaryFile )
736     {
737         this.summaryFile = summaryFile;
738     }
739 
740     @Override
741     public boolean isPrintSummary()
742     {
743         return printSummary;
744     }
745 
746     @Override
747     public void setPrintSummary( boolean printSummary )
748     {
749         this.printSummary = printSummary;
750     }
751 
752     @Override
753     public String getReportFormat()
754     {
755         return reportFormat;
756     }
757 
758     @Override
759     public void setReportFormat( String reportFormat )
760     {
761         this.reportFormat = reportFormat;
762     }
763 
764     @Override
765     public boolean isUseFile()
766     {
767         return useFile;
768     }
769 
770     @Override
771     public void setUseFile( boolean useFile )
772     {
773         this.useFile = useFile;
774     }
775 
776     @Override
777     public String getDebugForkedProcess()
778     {
779         return debugForkedProcess;
780     }
781 
782     @Override
783     public void setDebugForkedProcess( String debugForkedProcess )
784     {
785         this.debugForkedProcess = debugForkedProcess;
786     }
787 
788     @Override
789     public int getForkedProcessTimeoutInSeconds()
790     {
791         return forkedProcessTimeoutInSeconds;
792     }
793 
794     @Override
795     public void setForkedProcessTimeoutInSeconds( int forkedProcessTimeoutInSeconds )
796     {
797         this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
798     }
799 
800     @Override
801     public int getForkedProcessExitTimeoutInSeconds()
802     {
803         return forkedProcessExitTimeoutInSeconds;
804     }
805 
806     @Override
807     public void setForkedProcessExitTimeoutInSeconds( int forkedProcessExitTimeoutInSeconds )
808     {
809         this.forkedProcessExitTimeoutInSeconds = forkedProcessExitTimeoutInSeconds;
810     }
811 
812     @Override
813     public double getParallelTestsTimeoutInSeconds()
814     {
815         return parallelTestsTimeoutInSeconds;
816     }
817 
818     @Override
819     public void setParallelTestsTimeoutInSeconds( double parallelTestsTimeoutInSeconds )
820     {
821         this.parallelTestsTimeoutInSeconds = parallelTestsTimeoutInSeconds;
822     }
823 
824     @Override
825     public double getParallelTestsTimeoutForcedInSeconds()
826     {
827         return parallelTestsTimeoutForcedInSeconds;
828     }
829 
830     @Override
831     public void setParallelTestsTimeoutForcedInSeconds( double parallelTestsTimeoutForcedInSeconds )
832     {
833         this.parallelTestsTimeoutForcedInSeconds = parallelTestsTimeoutForcedInSeconds;
834     }
835 
836     @Override
837     public boolean isUseSystemClassLoader()
838     {
839         return useSystemClassLoader;
840     }
841 
842     @Override
843     public void setUseSystemClassLoader( boolean useSystemClassLoader )
844     {
845         this.useSystemClassLoader = useSystemClassLoader;
846     }
847 
848     @Override
849     public boolean isUseManifestOnlyJar()
850     {
851         return useManifestOnlyJar;
852     }
853 
854     @Override
855     public void setUseManifestOnlyJar( boolean useManifestOnlyJar )
856     {
857         this.useManifestOnlyJar = useManifestOnlyJar;
858     }
859 
860     @Override
861     public String getEncoding()
862     {
863         return encoding;
864     }
865 
866     @Override
867     public void setEncoding( String encoding )
868     {
869         this.encoding = encoding;
870     }
871 
872     // the following will be refactored out once the common code is all in one place
873 
874     public boolean isTestFailureIgnore()
875     {
876         return true; // ignore
877     }
878 
879     public void setTestFailureIgnore( boolean testFailureIgnore )
880     {
881         // ignore
882     }
883 
884     @Override
885     protected void addPluginSpecificChecksumItems( ChecksumCalculator checksum )
886     {
887         checksum.add( skipITs );
888         checksum.add( summaryFile );
889     }
890 
891     @Override
892     public File getSystemPropertiesFile()
893     {
894         return systemPropertiesFile;
895     }
896 
897     @Override
898     public void setSystemPropertiesFile( File systemPropertiesFile )
899     {
900         this.systemPropertiesFile = systemPropertiesFile;
901     }
902 
903     @Override
904     public boolean getFailIfNoSpecifiedTests()
905     {
906         return failIfNoSpecifiedTests;
907     }
908 
909     @Override
910     public void setFailIfNoSpecifiedTests( boolean failIfNoSpecifiedTests )
911     {
912         this.failIfNoSpecifiedTests = failIfNoSpecifiedTests;
913     }
914 
915     @Override
916     public int getSkipAfterFailureCount()
917     {
918         return skipAfterFailureCount;
919     }
920 
921     @Override
922     public String getShutdown()
923     {
924         return shutdown;
925     }
926 
927     @Override
928     public List<String> getIncludes()
929     {
930         return includes;
931     }
932 
933     @Override
934     public void setIncludes( List<String> includes )
935     {
936         this.includes = includes;
937     }
938 
939     @Override
940     public List<String> getExcludes()
941     {
942         return excludes;
943     }
944 
945     @Override
946     public void setExcludes( List<String> excludes )
947     {
948         this.excludes = excludes;
949     }
950 
951     @Override
952     public File[] getSuiteXmlFiles()
953     {
954         return suiteXmlFiles.clone();
955     }
956 
957     @Override
958     @SuppressWarnings( "UnusedDeclaration" )
959     public void setSuiteXmlFiles( File[] suiteXmlFiles )
960     {
961         this.suiteXmlFiles = suiteXmlFiles.clone();
962     }
963 
964     @Override
965     public String getRunOrder()
966     {
967         return runOrder;
968     }
969 
970     @Override
971     @SuppressWarnings( "UnusedDeclaration" )
972     public void setRunOrder( String runOrder )
973     {
974         this.runOrder = runOrder;
975     }
976 
977     @Override
978     public Long getRunOrderRandomSeed()
979     {
980         return runOrderRandomSeed;
981     }
982 
983     @Override
984     public void setRunOrderRandomSeed( Long runOrderRandomSeed )
985     {
986         this.runOrderRandomSeed = runOrderRandomSeed;
987     }
988 
989     @Override
990     public File getIncludesFile()
991     {
992         return includesFile;
993     }
994 
995     @Override
996     public File getExcludesFile()
997     {
998         return excludesFile;
999     }
1000 
1001     @Override
1002     protected boolean useModulePath()
1003     {
1004         return useModulePath;
1005     }
1006 
1007     @Override
1008     protected void setUseModulePath( boolean useModulePath )
1009     {
1010         this.useModulePath = useModulePath;
1011     }
1012 
1013     @Override
1014     protected final List<File> suiteXmlFiles()
1015     {
1016         return hasSuiteXmlFiles() ? Arrays.asList( suiteXmlFiles ) : Collections.<File>emptyList();
1017     }
1018 
1019     @Override
1020     protected final boolean hasSuiteXmlFiles()
1021     {
1022         return suiteXmlFiles != null && suiteXmlFiles.length != 0;
1023     }
1024 
1025     @Override
1026     protected final ForkNodeFactory getForkNode()
1027     {
1028         return forkNode;
1029     }
1030 
1031     @Override
1032     protected final String[] getExcludedEnvironmentVariables()
1033     {
1034         return excludedEnvironmentVariables == null ? new String[0] : excludedEnvironmentVariables;
1035     }
1036 
1037     void setExcludedEnvironmentVariables( String[] excludedEnvironmentVariables )
1038     {
1039         this.excludedEnvironmentVariables = excludedEnvironmentVariables;
1040     }
1041 
1042     @Override
1043     protected final String getEnableProcessChecker()
1044     {
1045         return enableProcessChecker;
1046     }
1047 
1048     public String[] getIncludeJUnit5Engines()
1049     {
1050         return includeJUnit5Engines;
1051     }
1052 
1053     @SuppressWarnings( "UnusedDeclaration" )
1054     public void setIncludeJUnit5Engines( String[] includeJUnit5Engines )
1055     {
1056         this.includeJUnit5Engines = includeJUnit5Engines;
1057     }
1058 
1059     public String[] getExcludeJUnit5Engines()
1060     {
1061         return excludeJUnit5Engines;
1062     }
1063 
1064     @SuppressWarnings( "UnusedDeclaration" )
1065     public void setExcludeJUnit5Engines( String[] excludeJUnit5Engines )
1066     {
1067         this.excludeJUnit5Engines = excludeJUnit5Engines;
1068     }
1069 }