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     @Parameter(property = "failsafe.systemPropertiesFile")
529     private File systemPropertiesFile;
530 
531     /**
532      * Provide the ID/s of an JUnit engine to be included in the test run.
533      *
534      * @since 3.0.0-M6
535      */
536     @Parameter(property = "failsafe.includeJUnit5Engines")
537     private String[] includeJUnit5Engines;
538 
539     /**
540      * Provide the ID/s of an JUnit engine to be excluded in the test run.
541      *
542      * @since 3.0.0-M6
543      */
544     @Parameter(property = "failsafe.excludeJUnit5Engines")
545     private String[] excludeJUnit5Engines;
546 
547     @Override
548     protected int getRerunFailingTestsCount() {
549         return rerunFailingTestsCount;
550     }
551 
552     @Override
553     @SuppressWarnings("unchecked")
554     protected void handleSummary(RunResult summary, Exception firstForkException)
555             throws MojoExecutionException, MojoFailureException {
556         try {
557             if (!summary.isNoTestsRun()) {
558                 Object token = getPluginContext().get(FAILSAFE_IN_PROGRESS_CONTEXT_KEY);
559                 writeSummary(summary, getSummaryFile(), token != null);
560             }
561         } catch (Exception e) {
562             throw new MojoExecutionException(e.getMessage(), e);
563         }
564 
565         getPluginContext().put(FAILSAFE_IN_PROGRESS_CONTEXT_KEY, FAILSAFE_IN_PROGRESS_CONTEXT_KEY);
566     }
567 
568     private boolean isJarArtifact(File artifactFile) {
569         return artifactFile != null
570                 && artifactFile.isFile()
571                 && artifactFile.getName().toLowerCase().endsWith(".jar");
572     }
573 
574     private static File toAbsoluteCanonical(File f) {
575         try {
576             return f == null ? null : f.getAbsoluteFile().getCanonicalFile();
577         } catch (IOException e) {
578             throw new IllegalStateException(e.getLocalizedMessage(), e);
579         }
580     }
581 
582     @Override
583     @SuppressWarnings("deprecation")
584     protected boolean isSkipExecution() {
585         return isSkip() || isSkipTests() || isSkipITs() || isSkipExec();
586     }
587 
588     @Override
589     protected String getPluginName() {
590         return "failsafe";
591     }
592 
593     @Override
594     protected String[] getDefaultIncludes() {
595         return new String[] {"**/IT*.java", "**/*IT.java", "**/*ITCase.java"};
596     }
597 
598     @Override
599     protected String getReportSchemaLocation() {
600         return "https://maven.apache.org/surefire/maven-failsafe-plugin/xsd/failsafe-test-report.xsd";
601     }
602 
603     @Override
604     public boolean isSkipTests() {
605         return skipTests;
606     }
607 
608     @Override
609     @Deprecated
610     public void setSkipTests(boolean skipTests) {
611         this.skipTests = skipTests;
612     }
613 
614     public boolean isSkipITs() {
615         return skipITs;
616     }
617 
618     public void setSkipITs(boolean skipITs) {
619         this.skipITs = skipITs;
620     }
621 
622     @Override
623     @Deprecated
624     public boolean isSkipExec() {
625         return skipExec;
626     }
627 
628     @Override
629     @Deprecated
630     public void setSkipExec(boolean skipExec) {
631         this.skipExec = skipExec;
632     }
633 
634     @Override
635     public boolean isSkip() {
636         return skip;
637     }
638 
639     @Override
640     public void setSkip(boolean skip) {
641         this.skip = skip;
642     }
643 
644     @Override
645     public File getBasedir() {
646         return basedir;
647     }
648 
649     @Override
650     public void setBasedir(File basedir) {
651         this.basedir = basedir;
652     }
653 
654     @Override
655     public File getTestClassesDirectory() {
656         return testClassesDirectory;
657     }
658 
659     @Override
660     public void setTestClassesDirectory(File testClassesDirectory) {
661         this.testClassesDirectory = testClassesDirectory;
662     }
663 
664     /**
665      * @return Output directory, or artifact file if artifact type is "jar". If not forking the JVM, parameter
666      * {@link #useSystemClassLoader} is ignored and the {@link org.apache.maven.surefire.booter.IsolatedClassLoader} is
667      * used instead. See the resolution of {@link #getClassLoaderConfiguration() ClassLoaderConfiguration}.
668      */
669     @Override
670     public File getMainBuildPath() {
671         File artifact = getProject().getArtifact().getFile();
672         boolean isDefaultClsDir = classesDirectory == null;
673         return isDefaultClsDir ? (isJarArtifact(artifact) ? artifact : defaultClassesDirectory) : classesDirectory;
674     }
675 
676     @Override
677     public void setMainBuildPath(File mainBuildPath) {
678         classesDirectory = toAbsoluteCanonical(mainBuildPath);
679     }
680 
681     public void setDefaultClassesDirectory(File defaultClassesDirectory) {
682         this.defaultClassesDirectory = toAbsoluteCanonical(defaultClassesDirectory);
683     }
684 
685     @Override
686     public File getReportsDirectory() {
687         return reportsDirectory;
688     }
689 
690     @Override
691     public void setReportsDirectory(File reportsDirectory) {
692         this.reportsDirectory = reportsDirectory;
693     }
694 
695     @Override
696     public String getTest() {
697         return test;
698     }
699 
700     @Override
701     public void setTest(String test) {
702         this.test = test;
703     }
704 
705     public File getSummaryFile() {
706         return summaryFile;
707     }
708 
709     public void setSummaryFile(File summaryFile) {
710         this.summaryFile = summaryFile;
711     }
712 
713     @Override
714     public boolean isPrintSummary() {
715         return printSummary;
716     }
717 
718     @Override
719     public void setPrintSummary(boolean printSummary) {
720         this.printSummary = printSummary;
721     }
722 
723     @Override
724     public String getReportFormat() {
725         return reportFormat;
726     }
727 
728     @Override
729     public void setReportFormat(String reportFormat) {
730         this.reportFormat = reportFormat;
731     }
732 
733     @Override
734     public boolean isUseFile() {
735         return useFile;
736     }
737 
738     @Override
739     public void setUseFile(boolean useFile) {
740         this.useFile = useFile;
741     }
742 
743     @Override
744     public String getDebugForkedProcess() {
745         return debugForkedProcess;
746     }
747 
748     @Override
749     public void setDebugForkedProcess(String debugForkedProcess) {
750         this.debugForkedProcess = debugForkedProcess;
751     }
752 
753     @Override
754     public int getForkedProcessTimeoutInSeconds() {
755         return forkedProcessTimeoutInSeconds;
756     }
757 
758     @Override
759     public void setForkedProcessTimeoutInSeconds(int forkedProcessTimeoutInSeconds) {
760         this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
761     }
762 
763     @Override
764     public int getForkedProcessExitTimeoutInSeconds() {
765         return forkedProcessExitTimeoutInSeconds;
766     }
767 
768     @Override
769     public void setForkedProcessExitTimeoutInSeconds(int forkedProcessExitTimeoutInSeconds) {
770         this.forkedProcessExitTimeoutInSeconds = forkedProcessExitTimeoutInSeconds;
771     }
772 
773     @Override
774     public double getParallelTestsTimeoutInSeconds() {
775         return parallelTestsTimeoutInSeconds;
776     }
777 
778     @Override
779     public void setParallelTestsTimeoutInSeconds(double parallelTestsTimeoutInSeconds) {
780         this.parallelTestsTimeoutInSeconds = parallelTestsTimeoutInSeconds;
781     }
782 
783     @Override
784     public double getParallelTestsTimeoutForcedInSeconds() {
785         return parallelTestsTimeoutForcedInSeconds;
786     }
787 
788     @Override
789     public void setParallelTestsTimeoutForcedInSeconds(double parallelTestsTimeoutForcedInSeconds) {
790         this.parallelTestsTimeoutForcedInSeconds = parallelTestsTimeoutForcedInSeconds;
791     }
792 
793     @Override
794     public boolean isUseSystemClassLoader() {
795         return useSystemClassLoader;
796     }
797 
798     @Override
799     public void setUseSystemClassLoader(boolean useSystemClassLoader) {
800         this.useSystemClassLoader = useSystemClassLoader;
801     }
802 
803     @Override
804     public boolean isUseManifestOnlyJar() {
805         return useManifestOnlyJar;
806     }
807 
808     @Override
809     public void setUseManifestOnlyJar(boolean useManifestOnlyJar) {
810         this.useManifestOnlyJar = useManifestOnlyJar;
811     }
812 
813     @Override
814     public String getEncoding() {
815         return encoding;
816     }
817 
818     @Override
819     public void setEncoding(String encoding) {
820         this.encoding = encoding;
821     }
822 
823     // the following will be refactored out once the common code is all in one place
824 
825     public boolean isTestFailureIgnore() {
826         return true; // ignore
827     }
828 
829     public void setTestFailureIgnore(boolean testFailureIgnore) {
830         // ignore
831     }
832 
833     @Override
834     protected void addPluginSpecificChecksumItems(ChecksumCalculator checksum) {
835         checksum.add(skipITs);
836         checksum.add(summaryFile);
837     }
838 
839     @Override
840     public File getSystemPropertiesFile() {
841         return systemPropertiesFile;
842     }
843 
844     @Override
845     public void setSystemPropertiesFile(File systemPropertiesFile) {
846         this.systemPropertiesFile = systemPropertiesFile;
847     }
848 
849     @Override
850     @SuppressWarnings("deprecation")
851     public boolean getFailIfNoSpecifiedTests() {
852         if (!failIfNoSpecifiedTestsDeprecated) {
853             getConsoleLogger()
854                     .warning("Use " + getPluginName()
855                             + ".failIfNoSpecifiedTests property instead of obsolete it.failIfNoSpecifiedTests.");
856         }
857         // since both have default "true", assuming that any "false" is set by user on purpose
858         return failIfNoSpecifiedTests && failIfNoSpecifiedTestsDeprecated;
859     }
860 
861     @Override
862     public void setFailIfNoSpecifiedTests(boolean failIfNoSpecifiedTests) {
863         this.failIfNoSpecifiedTests = failIfNoSpecifiedTests;
864     }
865 
866     @Override
867     public int getSkipAfterFailureCount() {
868         return skipAfterFailureCount;
869     }
870 
871     @Override
872     public String getShutdown() {
873         return shutdown;
874     }
875 
876     @Override
877     public List<String> getIncludes() {
878         return includes;
879     }
880 
881     @Override
882     public void setIncludes(List<String> includes) {
883         this.includes = includes;
884     }
885 
886     @Override
887     public List<String> getExcludes() {
888         return excludes;
889     }
890 
891     @Override
892     public void setExcludes(List<String> excludes) {
893         this.excludes = excludes;
894     }
895 
896     @Override
897     public File[] getSuiteXmlFiles() {
898         return suiteXmlFiles.clone();
899     }
900 
901     @Override
902     @SuppressWarnings("UnusedDeclaration")
903     public void setSuiteXmlFiles(File[] suiteXmlFiles) {
904         this.suiteXmlFiles = suiteXmlFiles.clone();
905     }
906 
907     @Override
908     public String getRunOrder() {
909         return runOrder;
910     }
911 
912     @Override
913     @SuppressWarnings("UnusedDeclaration")
914     public void setRunOrder(String runOrder) {
915         this.runOrder = runOrder;
916     }
917 
918     @Override
919     public Long getRunOrderRandomSeed() {
920         return runOrderRandomSeed;
921     }
922 
923     @Override
924     public void setRunOrderRandomSeed(Long runOrderRandomSeed) {
925         this.runOrderRandomSeed = runOrderRandomSeed;
926     }
927 
928     @Override
929     public File getIncludesFile() {
930         return includesFile;
931     }
932 
933     @Override
934     public File getExcludesFile() {
935         return excludesFile;
936     }
937 
938     @Override
939     protected boolean useModulePath() {
940         return useModulePath;
941     }
942 
943     @Override
944     protected void setUseModulePath(boolean useModulePath) {
945         this.useModulePath = useModulePath;
946     }
947 
948     @Override
949     protected final List<File> suiteXmlFiles() {
950         return hasSuiteXmlFiles() ? Arrays.asList(suiteXmlFiles) : Collections.<File>emptyList();
951     }
952 
953     @Override
954     protected final boolean hasSuiteXmlFiles() {
955         return suiteXmlFiles != null && suiteXmlFiles.length != 0;
956     }
957 
958     @Override
959     protected final ForkNodeFactory getForkNode() {
960         return forkNode;
961     }
962 
963     @Override
964     protected final String[] getExcludedEnvironmentVariables() {
965         return excludedEnvironmentVariables == null ? new String[0] : excludedEnvironmentVariables;
966     }
967 
968     void setExcludedEnvironmentVariables(String[] excludedEnvironmentVariables) {
969         this.excludedEnvironmentVariables = excludedEnvironmentVariables;
970     }
971 
972     @Override
973     protected final String getEnableProcessChecker() {
974         return enableProcessChecker;
975     }
976 
977     public String[] getIncludeJUnit5Engines() {
978         return includeJUnit5Engines;
979     }
980 
981     @SuppressWarnings("UnusedDeclaration")
982     public void setIncludeJUnit5Engines(String[] includeJUnit5Engines) {
983         this.includeJUnit5Engines = includeJUnit5Engines;
984     }
985 
986     public String[] getExcludeJUnit5Engines() {
987         return excludeJUnit5Engines;
988     }
989 
990     @SuppressWarnings("UnusedDeclaration")
991     public void setExcludeJUnit5Engines(String[] excludeJUnit5Engines) {
992         this.excludeJUnit5Engines = excludeJUnit5Engines;
993     }
994 }