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