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 @Parameter( property = "encoding", defaultValue = "${project.reporting.outputEncoding}" )
265 private String encoding;
266
267
268
269
270
271
272
273 @Parameter( property = "failsafe.rerunFailingTestsCount", defaultValue = "0" )
274 private int rerunFailingTestsCount;
275
276
277
278
279
280
281
282
283
284
285 @Parameter( property = "failsafe.suiteXmlFiles" )
286 private File[] suiteXmlFiles;
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
312 @Parameter( property = "failsafe.runOrder", defaultValue = "filesystem" )
313 private String runOrder;
314
315
316
317
318
319
320
321
322
323
324
325 @Parameter( property = "failsafe.includesFile" )
326 private File includesFile;
327
328
329
330
331
332
333
334
335
336
337
338 @Parameter( property = "failsafe.excludesFile" )
339 private File excludesFile;
340
341
342
343
344
345
346
347
348
349
350
351
352 @Parameter( property = "failsafe.skipAfterFailureCount", defaultValue = "0" )
353 private int skipAfterFailureCount;
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371 @Parameter( property = "failsafe.shutdown", defaultValue = "testset" )
372 private String shutdown;
373
374 @Override
375 protected int getRerunFailingTestsCount()
376 {
377 return rerunFailingTestsCount;
378 }
379
380 @Override
381 @SuppressWarnings( "unchecked" )
382 protected void handleSummary( RunResult summary, Exception firstForkException )
383 throws MojoExecutionException, MojoFailureException
384 {
385 File summaryFile = getSummaryFile();
386 if ( !summaryFile.getParentFile().isDirectory() )
387 {
388
389 summaryFile.getParentFile().mkdirs();
390 }
391
392 try
393 {
394 Object token = getPluginContext().get( FAILSAFE_IN_PROGRESS_CONTEXT_KEY );
395 writeSummary( summary, summaryFile, token != null );
396 }
397 catch ( Exception e )
398 {
399 throw new MojoExecutionException( e.getMessage(), e );
400 }
401
402 getPluginContext().put( FAILSAFE_IN_PROGRESS_CONTEXT_KEY, FAILSAFE_IN_PROGRESS_CONTEXT_KEY );
403 }
404
405 private boolean isJarArtifact( File artifactFile )
406 {
407 return artifactFile != null && artifactFile.isFile() && artifactFile.getName().toLowerCase().endsWith( ".jar" );
408 }
409
410 private static File toAbsoluteCanonical( File f )
411 {
412 try
413 {
414 return f == null ? null : f.getAbsoluteFile().getCanonicalFile();
415 }
416 catch ( IOException e )
417 {
418 throw new IllegalStateException( e.getLocalizedMessage(), e );
419 }
420 }
421
422 @Override
423 @SuppressWarnings( "deprecation" )
424 protected boolean isSkipExecution()
425 {
426 return isSkip() || isSkipTests() || isSkipITs() || isSkipExec();
427 }
428
429 @Override
430 protected String getPluginName()
431 {
432 return "failsafe";
433 }
434
435 @Override
436 protected String[] getDefaultIncludes()
437 {
438 return new String[]{ "**/IT*.java", "**/*IT.java", "**/*ITCase.java" };
439 }
440
441 @Override
442 protected String getReportSchemaLocation()
443 {
444 return "https://maven.apache.org/surefire/maven-failsafe-plugin/xsd/failsafe-test-report.xsd";
445 }
446
447 @Override
448 protected Artifact getMojoArtifact()
449 {
450 final Map<String, Artifact> pluginArtifactMap = getPluginArtifactMap();
451 return pluginArtifactMap.get( "org.apache.maven.plugins:maven-failsafe-plugin" );
452 }
453
454 @Override
455 public boolean isSkipTests()
456 {
457 return skipTests;
458 }
459
460 @Override
461 public void setSkipTests( boolean skipTests )
462 {
463 this.skipTests = skipTests;
464 }
465
466 public boolean isSkipITs()
467 {
468 return skipITs;
469 }
470
471 public void setSkipITs( boolean skipITs )
472 {
473 this.skipITs = skipITs;
474 }
475
476 @Override
477 @SuppressWarnings( "deprecation" )
478 @Deprecated
479 public boolean isSkipExec()
480 {
481 return skipExec;
482 }
483
484 @Override
485 @SuppressWarnings( "deprecation" )
486 @Deprecated
487 public void setSkipExec( boolean skipExec )
488 {
489 this.skipExec = skipExec;
490 }
491
492 @Override
493 public boolean isSkip()
494 {
495 return skip;
496 }
497
498 @Override
499 public void setSkip( boolean skip )
500 {
501 this.skip = skip;
502 }
503
504 @Override
505 public File getBasedir()
506 {
507 return basedir;
508 }
509
510 @Override
511 public void setBasedir( File basedir )
512 {
513 this.basedir = basedir;
514 }
515
516 @Override
517 public File getTestClassesDirectory()
518 {
519 return testClassesDirectory;
520 }
521
522 @Override
523 public void setTestClassesDirectory( File testClassesDirectory )
524 {
525 this.testClassesDirectory = testClassesDirectory;
526 }
527
528
529
530
531
532
533 @Override
534 public File getClassesDirectory()
535 {
536 File artifact = getProject().getArtifact().getFile();
537 boolean isDefaultClsDir = classesDirectory == null;
538 return isDefaultClsDir ? ( isJarArtifact( artifact ) ? artifact : defaultClassesDirectory ) : classesDirectory;
539 }
540
541 @Override
542 public void setClassesDirectory( File classesDirectory )
543 {
544 this.classesDirectory = toAbsoluteCanonical( classesDirectory );
545 }
546
547 public void setDefaultClassesDirectory( File defaultClassesDirectory )
548 {
549 this.defaultClassesDirectory = toAbsoluteCanonical( defaultClassesDirectory );
550 }
551
552 @Override
553 public File getReportsDirectory()
554 {
555 return reportsDirectory;
556 }
557
558 @Override
559 public void setReportsDirectory( File reportsDirectory )
560 {
561 this.reportsDirectory = reportsDirectory;
562 }
563
564 @Override
565 public String getTest()
566 {
567 return test;
568 }
569
570 @Override
571 public void setTest( String test )
572 {
573 this.test = test;
574 }
575
576 public File getSummaryFile()
577 {
578 return summaryFile;
579 }
580
581 public void setSummaryFile( File summaryFile )
582 {
583 this.summaryFile = summaryFile;
584 }
585
586 @Override
587 public boolean isPrintSummary()
588 {
589 return printSummary;
590 }
591
592 @Override
593 public void setPrintSummary( boolean printSummary )
594 {
595 this.printSummary = printSummary;
596 }
597
598 @Override
599 public String getReportFormat()
600 {
601 return reportFormat;
602 }
603
604 @Override
605 public void setReportFormat( String reportFormat )
606 {
607 this.reportFormat = reportFormat;
608 }
609
610 @Override
611 public boolean isUseFile()
612 {
613 return useFile;
614 }
615
616 @Override
617 public void setUseFile( boolean useFile )
618 {
619 this.useFile = useFile;
620 }
621
622 @Override
623 public String getDebugForkedProcess()
624 {
625 return debugForkedProcess;
626 }
627
628 @Override
629 public void setDebugForkedProcess( String debugForkedProcess )
630 {
631 this.debugForkedProcess = debugForkedProcess;
632 }
633
634 @Override
635 public int getForkedProcessTimeoutInSeconds()
636 {
637 return forkedProcessTimeoutInSeconds;
638 }
639
640 @Override
641 public void setForkedProcessTimeoutInSeconds( int forkedProcessTimeoutInSeconds )
642 {
643 this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
644 }
645
646 @Override
647 public int getForkedProcessExitTimeoutInSeconds()
648 {
649 return forkedProcessExitTimeoutInSeconds;
650 }
651
652 @Override
653 public void setForkedProcessExitTimeoutInSeconds( int forkedProcessExitTimeoutInSeconds )
654 {
655 this.forkedProcessExitTimeoutInSeconds = forkedProcessExitTimeoutInSeconds;
656 }
657
658 @Override
659 public double getParallelTestsTimeoutInSeconds()
660 {
661 return parallelTestsTimeoutInSeconds;
662 }
663
664 @Override
665 public void setParallelTestsTimeoutInSeconds( double parallelTestsTimeoutInSeconds )
666 {
667 this.parallelTestsTimeoutInSeconds = parallelTestsTimeoutInSeconds;
668 }
669
670 @Override
671 public double getParallelTestsTimeoutForcedInSeconds()
672 {
673 return parallelTestsTimeoutForcedInSeconds;
674 }
675
676 @Override
677 public void setParallelTestsTimeoutForcedInSeconds( double parallelTestsTimeoutForcedInSeconds )
678 {
679 this.parallelTestsTimeoutForcedInSeconds = parallelTestsTimeoutForcedInSeconds;
680 }
681
682 @Override
683 public boolean isUseSystemClassLoader()
684 {
685 return useSystemClassLoader;
686 }
687
688 @Override
689 public void setUseSystemClassLoader( boolean useSystemClassLoader )
690 {
691 this.useSystemClassLoader = useSystemClassLoader;
692 }
693
694 @Override
695 public boolean isUseManifestOnlyJar()
696 {
697 return useManifestOnlyJar;
698 }
699
700 @Override
701 public void setUseManifestOnlyJar( boolean useManifestOnlyJar )
702 {
703 this.useManifestOnlyJar = useManifestOnlyJar;
704 }
705
706
707
708 public boolean isTestFailureIgnore()
709 {
710 return true;
711 }
712
713 public void setTestFailureIgnore( boolean testFailureIgnore )
714 {
715
716 }
717
718 @Override
719 protected void addPluginSpecificChecksumItems( ChecksumCalculator checksum )
720 {
721 checksum.add( skipITs );
722 checksum.add( summaryFile );
723 }
724
725 @Override
726 public Boolean getFailIfNoSpecifiedTests()
727 {
728 return failIfNoSpecifiedTests;
729 }
730
731 @Override
732 public void setFailIfNoSpecifiedTests( boolean failIfNoSpecifiedTests )
733 {
734 this.failIfNoSpecifiedTests = failIfNoSpecifiedTests;
735 }
736
737 @Override
738 public int getSkipAfterFailureCount()
739 {
740 return skipAfterFailureCount;
741 }
742
743 @Override
744 public String getShutdown()
745 {
746 return shutdown;
747 }
748
749 @Override
750 public List<String> getIncludes()
751 {
752 return includes;
753 }
754
755 @Override
756 public void setIncludes( List<String> includes )
757 {
758 this.includes = includes;
759 }
760
761 @Override
762 public File[] getSuiteXmlFiles()
763 {
764 return suiteXmlFiles.clone();
765 }
766
767 @Override
768 @SuppressWarnings( "UnusedDeclaration" )
769 public void setSuiteXmlFiles( File[] suiteXmlFiles )
770 {
771 this.suiteXmlFiles = suiteXmlFiles.clone();
772 }
773
774 @Override
775 public String getRunOrder()
776 {
777 return runOrder;
778 }
779
780 @Override
781 @SuppressWarnings( "UnusedDeclaration" )
782 public void setRunOrder( String runOrder )
783 {
784 this.runOrder = runOrder;
785 }
786
787 @Override
788 public File getIncludesFile()
789 {
790 return includesFile;
791 }
792
793 @Override
794 public File getExcludesFile()
795 {
796 return excludesFile;
797 }
798
799 @Override
800 protected final List<File> suiteXmlFiles()
801 {
802 return hasSuiteXmlFiles() ? Arrays.asList( suiteXmlFiles ) : Collections.<File>emptyList();
803 }
804
805 @Override
806 protected final boolean hasSuiteXmlFiles()
807 {
808 return suiteXmlFiles != null && suiteXmlFiles.length != 0;
809 }
810
811 static Charset toCharset( String encoding )
812 {
813 return Charset.forName( Charset.isSupported( encoding ) ? encoding : encoding.toUpperCase( Locale.ROOT ) );
814 }
815 }