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