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