1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
42
43
44
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
58
59
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
69
70
71
72
73 @Parameter(property = "skipITs")
74 private boolean skipITs;
75
76
77
78
79 @Parameter(defaultValue = "${project.build.directory}/failsafe-reports")
80 private File reportsDirectory;
81
82 @SuppressWarnings("checkstyle:linelength")
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 @Parameter(property = "it.test")
106 private String test;
107
108
109
110
111 @Parameter(defaultValue = "${project.build.directory}/failsafe-reports/failsafe-summary.xml", required = true)
112 private File summaryFile;
113
114
115
116
117 @Parameter(property = "failsafe.printSummary", defaultValue = "true")
118 private boolean printSummary;
119
120
121
122
123
124 @Parameter(property = "failsafe.reportFormat", defaultValue = "brief")
125 private String reportFormat;
126
127
128
129
130 @Parameter(property = "failsafe.useFile", defaultValue = "true")
131 private boolean useFile;
132
133
134
135
136
137
138
139
140 @Deprecated
141 @Parameter(property = "it.failIfNoSpecifiedTests", defaultValue = "true")
142 private boolean failIfNoSpecifiedTestsDeprecated;
143
144
145
146
147
148
149
150
151 @Parameter(property = "failsafe.failIfNoSpecifiedTests", defaultValue = "true")
152 private boolean failIfNoSpecifiedTests;
153
154
155
156
157
158
159
160
161
162 @Parameter(property = "maven.failsafe.debug")
163 private String debugForkedProcess;
164
165
166
167
168
169
170
171 @Parameter(property = "failsafe.timeout")
172 private int forkedProcessTimeoutInSeconds;
173
174
175
176
177
178
179
180
181
182
183 @Parameter(property = "failsafe.exitTimeout", defaultValue = "30")
184 private int forkedProcessExitTimeoutInSeconds;
185
186
187
188
189
190
191
192
193
194
195
196 @Parameter(property = "failsafe.parallel.timeout")
197 private double parallelTestsTimeoutInSeconds;
198
199
200
201
202
203
204
205
206
207
208
209
210 @Parameter(property = "failsafe.parallel.forcedTimeout")
211 private double parallelTestsTimeoutForcedInSeconds;
212
213 @SuppressWarnings("checkstyle:linelength")
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241 @Parameter(property = "failsafe.includes")
242
243 private List<String> includes;
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 @Parameter(property = "failsafe.excludes")
270
271 private List<String> excludes;
272
273
274
275
276
277
278
279
280 @Parameter(property = "failsafe.useSystemClassLoader", defaultValue = "true")
281 private boolean useSystemClassLoader;
282
283
284
285
286
287
288
289
290
291
292
293
294 @Parameter(property = "failsafe.useManifestOnlyJar", defaultValue = "true")
295 private boolean useManifestOnlyJar;
296
297
298
299
300
301
302
303
304 @Parameter(property = "encoding", defaultValue = "${project.reporting.outputEncoding}")
305 private String encoding;
306
307
308
309
310
311
312
313 @Parameter(property = "failsafe.rerunFailingTestsCount", defaultValue = "0")
314 private int rerunFailingTestsCount;
315
316
317
318
319
320
321
322
323
324
325 @Parameter(property = "failsafe.suiteXmlFiles")
326 private File[] suiteXmlFiles;
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352 @Parameter(property = "failsafe.runOrder", defaultValue = "filesystem")
353 private String runOrder;
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368 @Parameter(property = "failsafe.runOrder.random.seed")
369 private Long runOrderRandomSeed;
370
371
372
373
374
375
376
377 @Parameter(property = "failsafe.runOrder.statisticsFile.checksum")
378 private String runOrderStatisticsFileChecksum;
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397 @Parameter(property = "failsafe.includesFile")
398 private File includesFile;
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 @Parameter(property = "failsafe.excludesFile")
418 private File excludesFile;
419
420
421
422
423
424
425
426
427
428
429
430
431 @Parameter(property = "failsafe.skipAfterFailureCount", defaultValue = "0")
432 private int skipAfterFailureCount;
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451 @Parameter(property = "failsafe.shutdown", defaultValue = "exit")
452 private String shutdown;
453
454
455
456
457
458
459
460
461
462 @Parameter(property = "failsafe.useModulePath", defaultValue = "true")
463 private boolean useModulePath;
464
465
466
467
468
469
470
471
472
473
474
475
476
477 @Parameter(property = "failsafe.forkNode")
478 private ForkNodeFactory forkNode;
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493 @Parameter(property = "failsafe.excludedEnvironmentVariables")
494 private String[] excludedEnvironmentVariables;
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534 @Parameter(property = "failsafe.enableProcessChecker")
535 private String enableProcessChecker;
536
537
538
539
540
541
542 @Parameter(property = "failsafe.systemPropertiesFile")
543 private File systemPropertiesFile;
544
545
546
547
548
549
550 @Parameter(property = "failsafe.includeJUnit5Engines")
551 private String[] includeJUnit5Engines;
552
553
554
555
556
557
558 @Parameter(property = "failsafe.excludeJUnit5Engines")
559 private String[] excludeJUnit5Engines;
560
561 @Override
562 protected int getRerunFailingTestsCount() {
563 return rerunFailingTestsCount;
564 }
565
566 @Override
567 @SuppressWarnings("unchecked")
568 protected void handleSummary(RunResult summary, Exception firstForkException)
569 throws MojoExecutionException, MojoFailureException {
570 try {
571 if (!summary.isNoTestsRun()) {
572 Object token = getPluginContext().get(FAILSAFE_IN_PROGRESS_CONTEXT_KEY);
573 writeSummary(summary, getSummaryFile(), token != null);
574 }
575 } catch (Exception e) {
576 throw new MojoExecutionException(e.getMessage(), e);
577 }
578
579 getPluginContext().put(FAILSAFE_IN_PROGRESS_CONTEXT_KEY, FAILSAFE_IN_PROGRESS_CONTEXT_KEY);
580 }
581
582 private boolean isJarArtifact(File artifactFile) {
583 return artifactFile != null
584 && artifactFile.isFile()
585 && artifactFile.getName().toLowerCase().endsWith(".jar");
586 }
587
588 private static File toAbsoluteCanonical(File f) {
589 try {
590 return f == null ? null : f.getAbsoluteFile().getCanonicalFile();
591 } catch (IOException e) {
592 throw new IllegalStateException(e.getLocalizedMessage(), e);
593 }
594 }
595
596 @Override
597 @SuppressWarnings("deprecation")
598 protected boolean isSkipExecution() {
599 return isSkip() || isSkipTests() || isSkipITs() || isSkipExec();
600 }
601
602 @Override
603 protected String getPluginName() {
604 return "failsafe";
605 }
606
607 @Override
608 protected String[] getDefaultIncludes() {
609 return new String[] {"**/IT*.java", "**/*IT.java", "**/*ITCase.java"};
610 }
611
612 @Override
613 protected String getReportSchemaLocation() {
614 return "https://maven.apache.org/surefire/maven-failsafe-plugin/xsd/failsafe-test-report.xsd";
615 }
616
617 @Override
618 public boolean isSkipTests() {
619 return skipTests;
620 }
621
622 @Override
623 @Deprecated
624 public void setSkipTests(boolean skipTests) {
625 this.skipTests = skipTests;
626 }
627
628 public boolean isSkipITs() {
629 return skipITs;
630 }
631
632 public void setSkipITs(boolean skipITs) {
633 this.skipITs = skipITs;
634 }
635
636 @Override
637 @Deprecated
638 public boolean isSkipExec() {
639 return skipExec;
640 }
641
642 @Override
643 @Deprecated
644 public void setSkipExec(boolean skipExec) {
645 this.skipExec = skipExec;
646 }
647
648 @Override
649 public boolean isSkip() {
650 return skip;
651 }
652
653 @Override
654 public void setSkip(boolean skip) {
655 this.skip = skip;
656 }
657
658 @Override
659 public File getBasedir() {
660 return basedir;
661 }
662
663 @Override
664 public void setBasedir(File basedir) {
665 this.basedir = basedir;
666 }
667
668 @Override
669 public File getTestClassesDirectory() {
670 return testClassesDirectory;
671 }
672
673 @Override
674 public void setTestClassesDirectory(File testClassesDirectory) {
675 this.testClassesDirectory = testClassesDirectory;
676 }
677
678
679
680
681
682
683 @Override
684 public File getMainBuildPath() {
685 File artifact = getProject().getArtifact().getFile();
686 boolean isDefaultClsDir = classesDirectory == null;
687 return isDefaultClsDir ? (isJarArtifact(artifact) ? artifact : defaultClassesDirectory) : classesDirectory;
688 }
689
690 @Override
691 public void setMainBuildPath(File mainBuildPath) {
692 classesDirectory = toAbsoluteCanonical(mainBuildPath);
693 }
694
695 public void setDefaultClassesDirectory(File defaultClassesDirectory) {
696 this.defaultClassesDirectory = toAbsoluteCanonical(defaultClassesDirectory);
697 }
698
699 @Override
700 public File getReportsDirectory() {
701 return reportsDirectory;
702 }
703
704 @Override
705 public void setReportsDirectory(File reportsDirectory) {
706 this.reportsDirectory = reportsDirectory;
707 }
708
709 @Override
710 public String getTest() {
711 return test;
712 }
713
714 @Override
715 public void setTest(String test) {
716 this.test = test;
717 }
718
719 public File getSummaryFile() {
720 return summaryFile;
721 }
722
723 public void setSummaryFile(File summaryFile) {
724 this.summaryFile = summaryFile;
725 }
726
727 @Override
728 public boolean isPrintSummary() {
729 return printSummary;
730 }
731
732 @Override
733 public void setPrintSummary(boolean printSummary) {
734 this.printSummary = printSummary;
735 }
736
737 @Override
738 public String getReportFormat() {
739 return reportFormat;
740 }
741
742 @Override
743 public void setReportFormat(String reportFormat) {
744 this.reportFormat = reportFormat;
745 }
746
747 @Override
748 public boolean isUseFile() {
749 return useFile;
750 }
751
752 @Override
753 public void setUseFile(boolean useFile) {
754 this.useFile = useFile;
755 }
756
757 @Override
758 public String getDebugForkedProcess() {
759 return debugForkedProcess;
760 }
761
762 @Override
763 public void setDebugForkedProcess(String debugForkedProcess) {
764 this.debugForkedProcess = debugForkedProcess;
765 }
766
767 @Override
768 public int getForkedProcessTimeoutInSeconds() {
769 return forkedProcessTimeoutInSeconds;
770 }
771
772 @Override
773 public void setForkedProcessTimeoutInSeconds(int forkedProcessTimeoutInSeconds) {
774 this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
775 }
776
777 @Override
778 public int getForkedProcessExitTimeoutInSeconds() {
779 return forkedProcessExitTimeoutInSeconds;
780 }
781
782 @Override
783 public void setForkedProcessExitTimeoutInSeconds(int forkedProcessExitTimeoutInSeconds) {
784 this.forkedProcessExitTimeoutInSeconds = forkedProcessExitTimeoutInSeconds;
785 }
786
787 @Override
788 public double getParallelTestsTimeoutInSeconds() {
789 return parallelTestsTimeoutInSeconds;
790 }
791
792 @Override
793 public void setParallelTestsTimeoutInSeconds(double parallelTestsTimeoutInSeconds) {
794 this.parallelTestsTimeoutInSeconds = parallelTestsTimeoutInSeconds;
795 }
796
797 @Override
798 public double getParallelTestsTimeoutForcedInSeconds() {
799 return parallelTestsTimeoutForcedInSeconds;
800 }
801
802 @Override
803 public void setParallelTestsTimeoutForcedInSeconds(double parallelTestsTimeoutForcedInSeconds) {
804 this.parallelTestsTimeoutForcedInSeconds = parallelTestsTimeoutForcedInSeconds;
805 }
806
807 @Override
808 public boolean isUseSystemClassLoader() {
809 return useSystemClassLoader;
810 }
811
812 @Override
813 public void setUseSystemClassLoader(boolean useSystemClassLoader) {
814 this.useSystemClassLoader = useSystemClassLoader;
815 }
816
817 @Override
818 public boolean isUseManifestOnlyJar() {
819 return useManifestOnlyJar;
820 }
821
822 @Override
823 public void setUseManifestOnlyJar(boolean useManifestOnlyJar) {
824 this.useManifestOnlyJar = useManifestOnlyJar;
825 }
826
827 @Override
828 public String getEncoding() {
829 return encoding;
830 }
831
832 @Override
833 public void setEncoding(String encoding) {
834 this.encoding = encoding;
835 }
836
837
838
839 public boolean isTestFailureIgnore() {
840 return true;
841 }
842
843 public void setTestFailureIgnore(boolean testFailureIgnore) {
844
845 }
846
847 @Override
848 protected void addPluginSpecificChecksumItems(ChecksumCalculator checksum) {
849 checksum.add(skipITs);
850 checksum.add(summaryFile);
851 }
852
853 @Override
854 public File getSystemPropertiesFile() {
855 return systemPropertiesFile;
856 }
857
858 @Override
859 public void setSystemPropertiesFile(File systemPropertiesFile) {
860 this.systemPropertiesFile = systemPropertiesFile;
861 }
862
863 @Override
864 @SuppressWarnings("deprecation")
865 public boolean getFailIfNoSpecifiedTests() {
866 if (!failIfNoSpecifiedTestsDeprecated) {
867 getConsoleLogger()
868 .warning("Use " + getPluginName()
869 + ".failIfNoSpecifiedTests property instead of obsolete it.failIfNoSpecifiedTests.");
870 }
871
872 return failIfNoSpecifiedTests && failIfNoSpecifiedTestsDeprecated;
873 }
874
875 @Override
876 public void setFailIfNoSpecifiedTests(boolean failIfNoSpecifiedTests) {
877 this.failIfNoSpecifiedTests = failIfNoSpecifiedTests;
878 }
879
880 @Override
881 public int getSkipAfterFailureCount() {
882 return skipAfterFailureCount;
883 }
884
885 @Override
886 public String getShutdown() {
887 return shutdown;
888 }
889
890 @Override
891 public List<String> getIncludes() {
892 return includes;
893 }
894
895 @Override
896 public void setIncludes(List<String> includes) {
897 this.includes = includes;
898 }
899
900 @Override
901 public List<String> getExcludes() {
902 return excludes;
903 }
904
905 @Override
906 public void setExcludes(List<String> excludes) {
907 this.excludes = excludes;
908 }
909
910 @Override
911 public File[] getSuiteXmlFiles() {
912 return suiteXmlFiles.clone();
913 }
914
915 @Override
916 @SuppressWarnings("UnusedDeclaration")
917 public void setSuiteXmlFiles(File[] suiteXmlFiles) {
918 this.suiteXmlFiles = suiteXmlFiles.clone();
919 }
920
921 @Override
922 public String getRunOrder() {
923 return runOrder;
924 }
925
926 @Override
927 @SuppressWarnings("UnusedDeclaration")
928 public void setRunOrder(String runOrder) {
929 this.runOrder = runOrder;
930 }
931
932 @Override
933 public Long getRunOrderRandomSeed() {
934 return runOrderRandomSeed;
935 }
936
937 @Override
938 public void setRunOrderRandomSeed(Long runOrderRandomSeed) {
939 this.runOrderRandomSeed = runOrderRandomSeed;
940 }
941
942 @Override
943 public String getRunOrderStatisticsFileChecksum() {
944 return runOrderStatisticsFileChecksum;
945 }
946
947 @Override
948 public void setRunOrderStatisticsFileChecksum(String runOrderStatisticsFileChecksum) {
949 this.runOrderStatisticsFileChecksum = runOrderStatisticsFileChecksum;
950 }
951
952 @Override
953 public File getIncludesFile() {
954 return includesFile;
955 }
956
957 @Override
958 public File getExcludesFile() {
959 return excludesFile;
960 }
961
962 @Override
963 protected boolean useModulePath() {
964 return useModulePath;
965 }
966
967 @Override
968 protected void setUseModulePath(boolean useModulePath) {
969 this.useModulePath = useModulePath;
970 }
971
972 @Override
973 protected final List<File> suiteXmlFiles() {
974 return hasSuiteXmlFiles() ? Arrays.asList(suiteXmlFiles) : Collections.<File>emptyList();
975 }
976
977 @Override
978 protected final boolean hasSuiteXmlFiles() {
979 return suiteXmlFiles != null && suiteXmlFiles.length != 0;
980 }
981
982 @Override
983 protected final ForkNodeFactory getForkNode() {
984 return forkNode;
985 }
986
987 @Override
988 protected final String[] getExcludedEnvironmentVariables() {
989 return excludedEnvironmentVariables == null ? new String[0] : excludedEnvironmentVariables;
990 }
991
992 void setExcludedEnvironmentVariables(String[] excludedEnvironmentVariables) {
993 this.excludedEnvironmentVariables = excludedEnvironmentVariables;
994 }
995
996 @Override
997 protected final String getEnableProcessChecker() {
998 return enableProcessChecker;
999 }
1000
1001 public String[] getIncludeJUnit5Engines() {
1002 return includeJUnit5Engines;
1003 }
1004
1005 @SuppressWarnings("UnusedDeclaration")
1006 public void setIncludeJUnit5Engines(String[] includeJUnit5Engines) {
1007 this.includeJUnit5Engines = includeJUnit5Engines;
1008 }
1009
1010 public String[] getExcludeJUnit5Engines() {
1011 return excludeJUnit5Engines;
1012 }
1013
1014 @SuppressWarnings("UnusedDeclaration")
1015 public void setExcludeJUnit5Engines(String[] excludeJUnit5Engines) {
1016 this.excludeJUnit5Engines = excludeJUnit5Engines;
1017 }
1018 }