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 public void setSkipTests( boolean skipTests )
465 {
466 this.skipTests = skipTests;
467 }
468
469 public boolean isSkipITs()
470 {
471 return skipITs;
472 }
473
474 public void setSkipITs( boolean skipITs )
475 {
476 this.skipITs = skipITs;
477 }
478
479 @Override
480 @SuppressWarnings( "deprecation" )
481 @Deprecated
482 public boolean isSkipExec()
483 {
484 return skipExec;
485 }
486
487 @Override
488 @SuppressWarnings( "deprecation" )
489 @Deprecated
490 public void setSkipExec( boolean skipExec )
491 {
492 this.skipExec = skipExec;
493 }
494
495 @Override
496 public boolean isSkip()
497 {
498 return skip;
499 }
500
501 @Override
502 public void setSkip( boolean skip )
503 {
504 this.skip = skip;
505 }
506
507 @Override
508 public File getBasedir()
509 {
510 return basedir;
511 }
512
513 @Override
514 public void setBasedir( File basedir )
515 {
516 this.basedir = basedir;
517 }
518
519 @Override
520 public File getTestClassesDirectory()
521 {
522 return testClassesDirectory;
523 }
524
525 @Override
526 public void setTestClassesDirectory( File testClassesDirectory )
527 {
528 this.testClassesDirectory = testClassesDirectory;
529 }
530
531
532
533
534
535
536 @Override
537 public File getClassesDirectory()
538 {
539 File artifact = getProject().getArtifact().getFile();
540 boolean isDefaultClsDir = classesDirectory == null;
541 return isDefaultClsDir ? ( isJarArtifact( artifact ) ? artifact : defaultClassesDirectory ) : classesDirectory;
542 }
543
544 @Override
545 public void setClassesDirectory( File classesDirectory )
546 {
547 this.classesDirectory = toAbsoluteCanonical( classesDirectory );
548 }
549
550 public void setDefaultClassesDirectory( File defaultClassesDirectory )
551 {
552 this.defaultClassesDirectory = toAbsoluteCanonical( defaultClassesDirectory );
553 }
554
555 @Override
556 public File getReportsDirectory()
557 {
558 return reportsDirectory;
559 }
560
561 @Override
562 public void setReportsDirectory( File reportsDirectory )
563 {
564 this.reportsDirectory = reportsDirectory;
565 }
566
567 @Override
568 public String getTest()
569 {
570 return test;
571 }
572
573 @Override
574 public void setTest( String test )
575 {
576 this.test = test;
577 }
578
579 public File getSummaryFile()
580 {
581 return summaryFile;
582 }
583
584 public void setSummaryFile( File summaryFile )
585 {
586 this.summaryFile = summaryFile;
587 }
588
589 @Override
590 public boolean isPrintSummary()
591 {
592 return printSummary;
593 }
594
595 @Override
596 public void setPrintSummary( boolean printSummary )
597 {
598 this.printSummary = printSummary;
599 }
600
601 @Override
602 public String getReportFormat()
603 {
604 return reportFormat;
605 }
606
607 @Override
608 public void setReportFormat( String reportFormat )
609 {
610 this.reportFormat = reportFormat;
611 }
612
613 @Override
614 public boolean isUseFile()
615 {
616 return useFile;
617 }
618
619 @Override
620 public void setUseFile( boolean useFile )
621 {
622 this.useFile = useFile;
623 }
624
625 @Override
626 public String getDebugForkedProcess()
627 {
628 return debugForkedProcess;
629 }
630
631 @Override
632 public void setDebugForkedProcess( String debugForkedProcess )
633 {
634 this.debugForkedProcess = debugForkedProcess;
635 }
636
637 @Override
638 public int getForkedProcessTimeoutInSeconds()
639 {
640 return forkedProcessTimeoutInSeconds;
641 }
642
643 @Override
644 public void setForkedProcessTimeoutInSeconds( int forkedProcessTimeoutInSeconds )
645 {
646 this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
647 }
648
649 @Override
650 public int getForkedProcessExitTimeoutInSeconds()
651 {
652 return forkedProcessExitTimeoutInSeconds;
653 }
654
655 @Override
656 public void setForkedProcessExitTimeoutInSeconds( int forkedProcessExitTimeoutInSeconds )
657 {
658 this.forkedProcessExitTimeoutInSeconds = forkedProcessExitTimeoutInSeconds;
659 }
660
661 @Override
662 public double getParallelTestsTimeoutInSeconds()
663 {
664 return parallelTestsTimeoutInSeconds;
665 }
666
667 @Override
668 public void setParallelTestsTimeoutInSeconds( double parallelTestsTimeoutInSeconds )
669 {
670 this.parallelTestsTimeoutInSeconds = parallelTestsTimeoutInSeconds;
671 }
672
673 @Override
674 public double getParallelTestsTimeoutForcedInSeconds()
675 {
676 return parallelTestsTimeoutForcedInSeconds;
677 }
678
679 @Override
680 public void setParallelTestsTimeoutForcedInSeconds( double parallelTestsTimeoutForcedInSeconds )
681 {
682 this.parallelTestsTimeoutForcedInSeconds = parallelTestsTimeoutForcedInSeconds;
683 }
684
685 @Override
686 public boolean isUseSystemClassLoader()
687 {
688 return useSystemClassLoader;
689 }
690
691 @Override
692 public void setUseSystemClassLoader( boolean useSystemClassLoader )
693 {
694 this.useSystemClassLoader = useSystemClassLoader;
695 }
696
697 @Override
698 public boolean isUseManifestOnlyJar()
699 {
700 return useManifestOnlyJar;
701 }
702
703 @Override
704 public void setUseManifestOnlyJar( boolean useManifestOnlyJar )
705 {
706 this.useManifestOnlyJar = useManifestOnlyJar;
707 }
708
709 @Override
710 public String getEncoding()
711 {
712 return encoding;
713 }
714
715 @Override
716 public void setEncoding( String encoding )
717 {
718 this.encoding = encoding;
719 }
720
721
722
723 public boolean isTestFailureIgnore()
724 {
725 return true;
726 }
727
728 public void setTestFailureIgnore( boolean testFailureIgnore )
729 {
730
731 }
732
733 @Override
734 protected void addPluginSpecificChecksumItems( ChecksumCalculator checksum )
735 {
736 checksum.add( skipITs );
737 checksum.add( summaryFile );
738 }
739
740 @Override
741 public Boolean getFailIfNoSpecifiedTests()
742 {
743 return failIfNoSpecifiedTests;
744 }
745
746 @Override
747 public void setFailIfNoSpecifiedTests( boolean failIfNoSpecifiedTests )
748 {
749 this.failIfNoSpecifiedTests = failIfNoSpecifiedTests;
750 }
751
752 @Override
753 public int getSkipAfterFailureCount()
754 {
755 return skipAfterFailureCount;
756 }
757
758 @Override
759 public String getShutdown()
760 {
761 return shutdown;
762 }
763
764 @Override
765 public List<String> getIncludes()
766 {
767 return includes;
768 }
769
770 @Override
771 public void setIncludes( List<String> includes )
772 {
773 this.includes = includes;
774 }
775
776 @Override
777 public File[] getSuiteXmlFiles()
778 {
779 return suiteXmlFiles.clone();
780 }
781
782 @Override
783 @SuppressWarnings( "UnusedDeclaration" )
784 public void setSuiteXmlFiles( File[] suiteXmlFiles )
785 {
786 this.suiteXmlFiles = suiteXmlFiles.clone();
787 }
788
789 @Override
790 public String getRunOrder()
791 {
792 return runOrder;
793 }
794
795 @Override
796 @SuppressWarnings( "UnusedDeclaration" )
797 public void setRunOrder( String runOrder )
798 {
799 this.runOrder = runOrder;
800 }
801
802 @Override
803 public File getIncludesFile()
804 {
805 return includesFile;
806 }
807
808 @Override
809 public File getExcludesFile()
810 {
811 return excludesFile;
812 }
813
814 @Override
815 protected boolean useModulePath()
816 {
817 return useModulePath;
818 }
819
820 @Override
821 protected void setUseModulePath( boolean useModulePath )
822 {
823 this.useModulePath = useModulePath;
824 }
825
826 @Override
827 protected final List<File> suiteXmlFiles()
828 {
829 return hasSuiteXmlFiles() ? Arrays.asList( suiteXmlFiles ) : Collections.<File>emptyList();
830 }
831
832 @Override
833 protected final boolean hasSuiteXmlFiles()
834 {
835 return suiteXmlFiles != null && suiteXmlFiles.length != 0;
836 }
837
838 static Charset toCharset( String encoding )
839 {
840 return Charset.forName( Charset.isSupported( encoding ) ? encoding : encoding.toUpperCase( Locale.ROOT ) );
841 }
842 }