1 package org.apache.maven.plugin.failsafe;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.plugin.MojoExecutionException;
23 import org.apache.maven.plugin.MojoFailureException;
24 import org.apache.maven.plugin.surefire.AbstractSurefireMojo;
25 import org.apache.maven.plugin.surefire.booterclient.ChecksumCalculator;
26 import org.apache.maven.plugins.annotations.LifecyclePhase;
27 import org.apache.maven.plugins.annotations.Mojo;
28 import org.apache.maven.plugins.annotations.Parameter;
29 import org.apache.maven.plugins.annotations.ResolutionScope;
30 import org.apache.maven.surefire.suite.RunResult;
31
32 import java.io.File;
33 import java.io.IOException;
34 import java.nio.charset.Charset;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.List;
38 import java.util.Locale;
39
40 import static org.apache.maven.plugin.failsafe.util.FailsafeSummaryXmlUtils.writeSummary;
41
42
43
44
45
46
47
48 @Mojo( name = "integration-test", requiresProject = true, requiresDependencyResolution = ResolutionScope.TEST,
49 defaultPhase = LifecyclePhase.INTEGRATION_TEST, threadSafe = true )
50 public class IntegrationTestMojo
51 extends AbstractSurefireMojo
52 {
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( readonly = true, defaultValue = "${project.build.outputDirectory}" )
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 @Parameter( property = "it.failIfNoSpecifiedTests" )
140 private Boolean failIfNoSpecifiedTests;
141
142
143
144
145
146
147
148
149
150 @Parameter( property = "maven.failsafe.debug" )
151 private String debugForkedProcess;
152
153
154
155
156
157
158
159 @Parameter( property = "failsafe.timeout" )
160 private int forkedProcessTimeoutInSeconds;
161
162
163
164
165
166
167
168
169
170
171 @Parameter( property = "failsafe.exitTimeout", defaultValue = "30" )
172 private int forkedProcessExitTimeoutInSeconds;
173
174
175
176
177
178
179
180
181
182
183
184 @Parameter( property = "failsafe.parallel.timeout" )
185 private double parallelTestsTimeoutInSeconds;
186
187
188
189
190
191
192
193
194
195
196
197
198 @Parameter( property = "failsafe.parallel.forcedTimeout" )
199 private double parallelTestsTimeoutForcedInSeconds;
200
201 @SuppressWarnings( "checkstyle:linelength" )
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229 @Parameter
230 private List<String> includes;
231
232
233
234
235
236
237
238
239 @Parameter( property = "failsafe.useSystemClassLoader", defaultValue = "true" )
240 private boolean useSystemClassLoader;
241
242
243
244
245
246
247
248
249
250
251
252
253 @Parameter( property = "failsafe.useManifestOnlyJar", defaultValue = "true" )
254 private boolean useManifestOnlyJar;
255
256
257
258
259
260
261
262
263 @Parameter( property = "encoding", defaultValue = "${project.reporting.outputEncoding}" )
264 private String encoding;
265
266
267
268
269
270
271
272 @Parameter( property = "failsafe.rerunFailingTestsCount", defaultValue = "0" )
273 private int rerunFailingTestsCount;
274
275
276
277
278
279
280
281
282
283
284 @Parameter( property = "failsafe.suiteXmlFiles" )
285 private File[] suiteXmlFiles;
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311 @Parameter( property = "failsafe.runOrder", defaultValue = "filesystem" )
312 private String runOrder;
313
314
315
316
317
318
319
320
321
322
323
324 @Parameter( property = "failsafe.includesFile" )
325 private File includesFile;
326
327
328
329
330
331
332
333
334
335
336
337 @Parameter( property = "failsafe.excludesFile" )
338 private File excludesFile;
339
340
341
342
343
344
345
346
347
348
349
350
351 @Parameter( property = "failsafe.skipAfterFailureCount", defaultValue = "0" )
352 private int skipAfterFailureCount;
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370 @Parameter( property = "failsafe.shutdown", defaultValue = "testset" )
371 private String shutdown;
372
373
374
375
376
377
378
379
380
381 @Parameter( property = "failsafe.useModulePath", defaultValue = "true" )
382 private boolean useModulePath;
383
384 @Override
385 protected int getRerunFailingTestsCount()
386 {
387 return rerunFailingTestsCount;
388 }
389
390 @Override
391 @SuppressWarnings( "unchecked" )
392 protected void handleSummary( RunResult summary, Exception firstForkException )
393 throws MojoExecutionException, MojoFailureException
394 {
395 File summaryFile = getSummaryFile();
396 if ( !summaryFile.getParentFile().isDirectory() )
397 {
398
399 summaryFile.getParentFile().mkdirs();
400 }
401
402 try
403 {
404 Object token = getPluginContext().get( FAILSAFE_IN_PROGRESS_CONTEXT_KEY );
405 writeSummary( summary, summaryFile, token != null );
406 }
407 catch ( Exception e )
408 {
409 throw new MojoExecutionException( e.getMessage(), e );
410 }
411
412 getPluginContext().put( FAILSAFE_IN_PROGRESS_CONTEXT_KEY, FAILSAFE_IN_PROGRESS_CONTEXT_KEY );
413 }
414
415 private boolean isJarArtifact( File artifactFile )
416 {
417 return artifactFile != null && artifactFile.isFile() && artifactFile.getName().toLowerCase().endsWith( ".jar" );
418 }
419
420 private static File toAbsoluteCanonical( File f )
421 {
422 try
423 {
424 return f == null ? null : f.getAbsoluteFile().getCanonicalFile();
425 }
426 catch ( IOException e )
427 {
428 throw new IllegalStateException( e.getLocalizedMessage(), e );
429 }
430 }
431
432 @Override
433 @SuppressWarnings( "deprecation" )
434 protected boolean isSkipExecution()
435 {
436 return isSkip() || isSkipTests() || isSkipITs() || isSkipExec();
437 }
438
439 @Override
440 protected String getPluginName()
441 {
442 return "failsafe";
443 }
444
445 @Override
446 protected String[] getDefaultIncludes()
447 {
448 return new String[]{ "**/IT*.java", "**/*IT.java", "**/*ITCase.java" };
449 }
450
451 @Override
452 protected String getReportSchemaLocation()
453 {
454 return "https://maven.apache.org/surefire/maven-failsafe-plugin/xsd/failsafe-test-report-3.0.xsd";
455 }
456
457 @Override
458 public boolean isSkipTests()
459 {
460 return skipTests;
461 }
462
463 @Override
464 @Deprecated
465 public void setSkipTests( boolean skipTests )
466 {
467 this.skipTests = skipTests;
468 }
469
470 public boolean isSkipITs()
471 {
472 return skipITs;
473 }
474
475 public void setSkipITs( boolean skipITs )
476 {
477 this.skipITs = skipITs;
478 }
479
480 @Override
481 @SuppressWarnings( "deprecation" )
482 @Deprecated
483 public boolean isSkipExec()
484 {
485 return skipExec;
486 }
487
488 @Override
489 @SuppressWarnings( "deprecation" )
490 @Deprecated
491 public void setSkipExec( boolean skipExec )
492 {
493 this.skipExec = skipExec;
494 }
495
496 @Override
497 public boolean isSkip()
498 {
499 return skip;
500 }
501
502 @Override
503 public void setSkip( boolean skip )
504 {
505 this.skip = skip;
506 }
507
508 @Override
509 public File getBasedir()
510 {
511 return basedir;
512 }
513
514 @Override
515 public void setBasedir( File basedir )
516 {
517 this.basedir = basedir;
518 }
519
520 @Override
521 public File getTestClassesDirectory()
522 {
523 return testClassesDirectory;
524 }
525
526 @Override
527 public void setTestClassesDirectory( File testClassesDirectory )
528 {
529 this.testClassesDirectory = testClassesDirectory;
530 }
531
532
533
534
535
536
537 @Override
538 public File getClassesDirectory()
539 {
540 File artifact = getProject().getArtifact().getFile();
541 boolean isDefaultClsDir = classesDirectory == null;
542 return isDefaultClsDir ? ( isJarArtifact( artifact ) ? artifact : defaultClassesDirectory ) : classesDirectory;
543 }
544
545 @Override
546 public void setClassesDirectory( File classesDirectory )
547 {
548 this.classesDirectory = toAbsoluteCanonical( classesDirectory );
549 }
550
551 public void setDefaultClassesDirectory( File defaultClassesDirectory )
552 {
553 this.defaultClassesDirectory = toAbsoluteCanonical( defaultClassesDirectory );
554 }
555
556 @Override
557 public File getReportsDirectory()
558 {
559 return reportsDirectory;
560 }
561
562 @Override
563 public void setReportsDirectory( File reportsDirectory )
564 {
565 this.reportsDirectory = reportsDirectory;
566 }
567
568 @Override
569 public String getTest()
570 {
571 return test;
572 }
573
574 @Override
575 public void setTest( String test )
576 {
577 this.test = test;
578 }
579
580 public File getSummaryFile()
581 {
582 return summaryFile;
583 }
584
585 public void setSummaryFile( File summaryFile )
586 {
587 this.summaryFile = summaryFile;
588 }
589
590 @Override
591 public boolean isPrintSummary()
592 {
593 return printSummary;
594 }
595
596 @Override
597 public void setPrintSummary( boolean printSummary )
598 {
599 this.printSummary = printSummary;
600 }
601
602 @Override
603 public String getReportFormat()
604 {
605 return reportFormat;
606 }
607
608 @Override
609 public void setReportFormat( String reportFormat )
610 {
611 this.reportFormat = reportFormat;
612 }
613
614 @Override
615 public boolean isUseFile()
616 {
617 return useFile;
618 }
619
620 @Override
621 public void setUseFile( boolean useFile )
622 {
623 this.useFile = useFile;
624 }
625
626 @Override
627 public String getDebugForkedProcess()
628 {
629 return debugForkedProcess;
630 }
631
632 @Override
633 public void setDebugForkedProcess( String debugForkedProcess )
634 {
635 this.debugForkedProcess = debugForkedProcess;
636 }
637
638 @Override
639 public int getForkedProcessTimeoutInSeconds()
640 {
641 return forkedProcessTimeoutInSeconds;
642 }
643
644 @Override
645 public void setForkedProcessTimeoutInSeconds( int forkedProcessTimeoutInSeconds )
646 {
647 this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
648 }
649
650 @Override
651 public int getForkedProcessExitTimeoutInSeconds()
652 {
653 return forkedProcessExitTimeoutInSeconds;
654 }
655
656 @Override
657 public void setForkedProcessExitTimeoutInSeconds( int forkedProcessExitTimeoutInSeconds )
658 {
659 this.forkedProcessExitTimeoutInSeconds = forkedProcessExitTimeoutInSeconds;
660 }
661
662 @Override
663 public double getParallelTestsTimeoutInSeconds()
664 {
665 return parallelTestsTimeoutInSeconds;
666 }
667
668 @Override
669 public void setParallelTestsTimeoutInSeconds( double parallelTestsTimeoutInSeconds )
670 {
671 this.parallelTestsTimeoutInSeconds = parallelTestsTimeoutInSeconds;
672 }
673
674 @Override
675 public double getParallelTestsTimeoutForcedInSeconds()
676 {
677 return parallelTestsTimeoutForcedInSeconds;
678 }
679
680 @Override
681 public void setParallelTestsTimeoutForcedInSeconds( double parallelTestsTimeoutForcedInSeconds )
682 {
683 this.parallelTestsTimeoutForcedInSeconds = parallelTestsTimeoutForcedInSeconds;
684 }
685
686 @Override
687 public boolean isUseSystemClassLoader()
688 {
689 return useSystemClassLoader;
690 }
691
692 @Override
693 public void setUseSystemClassLoader( boolean useSystemClassLoader )
694 {
695 this.useSystemClassLoader = useSystemClassLoader;
696 }
697
698 @Override
699 public boolean isUseManifestOnlyJar()
700 {
701 return useManifestOnlyJar;
702 }
703
704 @Override
705 public void setUseManifestOnlyJar( boolean useManifestOnlyJar )
706 {
707 this.useManifestOnlyJar = useManifestOnlyJar;
708 }
709
710 @Override
711 public String getEncoding()
712 {
713 return encoding;
714 }
715
716 @Override
717 public void setEncoding( String encoding )
718 {
719 this.encoding = encoding;
720 }
721
722
723
724 public boolean isTestFailureIgnore()
725 {
726 return true;
727 }
728
729 public void setTestFailureIgnore( boolean testFailureIgnore )
730 {
731
732 }
733
734 @Override
735 protected void addPluginSpecificChecksumItems( ChecksumCalculator checksum )
736 {
737 checksum.add( skipITs );
738 checksum.add( summaryFile );
739 }
740
741 @Override
742 public Boolean getFailIfNoSpecifiedTests()
743 {
744 return failIfNoSpecifiedTests;
745 }
746
747 @Override
748 public void setFailIfNoSpecifiedTests( boolean failIfNoSpecifiedTests )
749 {
750 this.failIfNoSpecifiedTests = failIfNoSpecifiedTests;
751 }
752
753 @Override
754 public int getSkipAfterFailureCount()
755 {
756 return skipAfterFailureCount;
757 }
758
759 @Override
760 public String getShutdown()
761 {
762 return shutdown;
763 }
764
765 @Override
766 public List<String> getIncludes()
767 {
768 return includes;
769 }
770
771 @Override
772 public void setIncludes( List<String> includes )
773 {
774 this.includes = includes;
775 }
776
777 @Override
778 public File[] getSuiteXmlFiles()
779 {
780 return suiteXmlFiles.clone();
781 }
782
783 @Override
784 @SuppressWarnings( "UnusedDeclaration" )
785 public void setSuiteXmlFiles( File[] suiteXmlFiles )
786 {
787 this.suiteXmlFiles = suiteXmlFiles.clone();
788 }
789
790 @Override
791 public String getRunOrder()
792 {
793 return runOrder;
794 }
795
796 @Override
797 @SuppressWarnings( "UnusedDeclaration" )
798 public void setRunOrder( String runOrder )
799 {
800 this.runOrder = runOrder;
801 }
802
803 @Override
804 public File getIncludesFile()
805 {
806 return includesFile;
807 }
808
809 @Override
810 public File getExcludesFile()
811 {
812 return excludesFile;
813 }
814
815 @Override
816 protected boolean useModulePath()
817 {
818 return useModulePath;
819 }
820
821 @Override
822 protected void setUseModulePath( boolean useModulePath )
823 {
824 this.useModulePath = useModulePath;
825 }
826
827 @Override
828 protected final List<File> suiteXmlFiles()
829 {
830 return hasSuiteXmlFiles() ? Arrays.asList( suiteXmlFiles ) : Collections.<File>emptyList();
831 }
832
833 @Override
834 protected final boolean hasSuiteXmlFiles()
835 {
836 return suiteXmlFiles != null && suiteXmlFiles.length != 0;
837 }
838
839 static Charset toCharset( String encoding )
840 {
841 return Charset.forName( Charset.isSupported( encoding ) ? encoding : encoding.toUpperCase( Locale.ROOT ) );
842 }
843 }