View Javadoc
1   package org.apache.maven.plugin.surefire;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.util.List;
24  import org.apache.maven.plugin.MojoExecutionException;
25  import org.apache.maven.plugin.MojoFailureException;
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  import org.apache.maven.surefire.util.internal.StringUtils;
32  
33  /**
34   * Run tests using Surefire.
35   *
36   * @author Jason van Zyl
37   * @noinspection JavaDoc
38   */
39  @Mojo( name = "test", defaultPhase = LifecyclePhase.TEST, threadSafe = true,
40         requiresDependencyResolution = ResolutionScope.TEST )
41  public class SurefirePlugin
42      extends AbstractSurefireMojo
43      implements SurefireReportParameters
44  {
45  
46      /**
47       * Set this to "true" to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on
48       * occasion.
49       */
50      @Parameter( property = "maven.test.failure.ignore", defaultValue = "false" )
51      private boolean testFailureIgnore;
52  
53      /**
54       * Base directory where all reports are written to.
55       */
56      @Parameter( defaultValue = "${project.build.directory}/surefire-reports" )
57      private File reportsDirectory;
58  
59      /**
60       * Specify this parameter to run individual tests by file name, overriding the <code>includes/excludes</code>
61       * parameters. Each pattern you specify here will be used to create an include pattern formatted like
62       * <code>**&#47;${test}.java</code>, so you can just type "-Dtest=MyTest" to run a single test called
63       * "foo/MyTest.java". The test patterns prefixed with a <code>!</code> will be excluded.<br/>
64       * This parameter overrides the <code>includes/excludes</code> parameters, and the TestNG <code>suiteXmlFiles</code>
65       * parameter.
66       * <p/>
67       * Since 2.7.3, you can execute a limited number of methods in the test by adding #myMethod or #my*ethod. For
68       * example, "-Dtest=MyTest#myMethod". This is supported for junit 4.x and testNg.
69       */
70      @Parameter( property = "test" )
71      private String test;
72  
73      /**
74       * Option to print summary of test suites or just print the test cases that have errors.
75       */
76      @Parameter( property = "surefire.printSummary", defaultValue = "true" )
77      private boolean printSummary;
78  
79      /**
80       * Selects the formatting for the test report to be generated. Can be set as "brief" or "plain".
81       * Only applies to the output format of the output files  (target/surefire-reports/testName.txt)
82       */
83      @Parameter( property = "surefire.reportFormat", defaultValue = "brief" )
84      private String reportFormat;
85  
86      /**
87       * Option to generate a file test report or just output the test report to the console.
88       */
89      @Parameter( property = "surefire.useFile", defaultValue = "true" )
90      private boolean useFile;
91  
92  
93      /**
94       * Set this to "true" to cause a failure if the none of the tests specified in -Dtest=... are run. Defaults to
95       * "true".
96       *
97       * @since 2.12
98       */
99      @Parameter( property = "surefire.failIfNoSpecifiedTests" )
100     private Boolean failIfNoSpecifiedTests;
101 
102     /**
103      * Attach a debugger to the forked JVM. If set to "true", the process will suspend and wait for a debugger to attach
104      * on port 5005. If set to some other string, that string will be appended to the argLine, allowing you to configure
105      * arbitrary debuggability options (without overwriting the other options specified through the <code>argLine</code>
106      * parameter).
107      *
108      * @since 2.4
109      */
110     @Parameter( property = "maven.surefire.debug" )
111     private String debugForkedProcess;
112 
113     /**
114      * Kill the forked test process after a certain number of seconds. If set to 0, wait forever for the process, never
115      * timing out.
116      *
117      * @since 2.4
118      */
119     @Parameter( property = "surefire.timeout" )
120     private int forkedProcessTimeoutInSeconds;
121 
122     /**
123      * Stop executing queued parallel JUnit tests after a certain number of seconds.
124      * <br/>
125      * Example values: "3.5", "4"<br/>
126      * <br/>
127      * If set to 0, wait forever, never timing out.
128      * Makes sense with specified <code>parallel</code> different from "none".
129      *
130      * @since 2.16
131      */
132     @Parameter( property = "surefire.parallel.timeout" )
133     private double parallelTestsTimeoutInSeconds;
134 
135     /**
136      * Stop executing queued parallel JUnit tests
137      * and <em>interrupt</em> currently running tests after a certain number of seconds.
138      * <br/>
139      * Example values: "3.5", "4"<br/>
140      * <br/>
141      * If set to 0, wait forever, never timing out.
142      * Makes sense with specified <code>parallel</code> different from "none".
143      *
144      * @since 2.16
145      */
146     @Parameter( property = "surefire.parallel.forcedTimeout" )
147     private double parallelTestsTimeoutForcedInSeconds;
148 
149     /**
150      * A list of &lt;include> elements specifying the tests (by pattern) that should be included in testing. When not
151      * specified and when the <code>test</code> parameter is not specified, the default includes will be <code><br/>
152      * &lt;includes><br/>
153      * &nbsp;&lt;include>**&#47;Test*.java&lt;/include><br/>
154      * &nbsp;&lt;include>**&#47;*Test.java&lt;/include><br/>
155      * &nbsp;&lt;include>**&#47;*TestCase.java&lt;/include><br/>
156      * &lt;/includes><br/>
157      * </code>
158      * <p/>
159      * Each include item may also contain a comma-separated sublist of items, which will be treated as multiple
160      * &nbsp;&lt;include> entries.<br/>
161      * <p/>
162      * This parameter is ignored if the TestNG <code>suiteXmlFiles</code> parameter is specified.<br/>
163      * <br/>
164      * <em>Notice that</em> these values are relative to the directory containing generated test classes of the project
165      * being tested. This directory is declared by the parameter <code>testClassesDirectory</code> which defaults
166      * to the POM property <code>${project.build.testOutputDirectory}</code>, typically <em>src/test/java</em>
167      * unless overridden.
168      */
169     @Parameter
170     private List<String> includes;
171 
172     /**
173      * Option to pass dependencies to the system's classloader instead of using an isolated class loader when forking.
174      * Prevents problems with JDKs which implement the service provider lookup mechanism by using the system's
175      * classloader.
176      *
177      * @since 2.3
178      */
179     @Parameter( property = "surefire.useSystemClassLoader", defaultValue = "true" )
180     private boolean useSystemClassLoader;
181 
182     /**
183      * By default, Surefire forks your tests using a manifest-only JAR; set this parameter to "false" to force it to
184      * launch your tests with a plain old Java classpath. (See the
185      * <a href="http://maven.apache.org/plugins/maven-surefire-plugin/examples/class-loading.html">
186      *     http://maven.apache.org/plugins/maven-surefire-plugin/examples/class-loading.html</a>;
187      * for a more detailed explanation of manifest-only JARs and their benefits.)
188      * <br/>
189      * Beware, setting this to "false" may cause your tests to fail on Windows if your classpath is too long.
190      *
191      * @since 2.4.3
192      */
193     @Parameter( property = "surefire.useManifestOnlyJar", defaultValue = "true" )
194     private boolean useManifestOnlyJar;
195 
196     /**
197      * (JUnit 4+ providers)
198      * The number of times each failing test will be rerun. If set larger than 0, rerun failing tests immediately after
199      * they fail. If a failing test passes in any of those reruns, it will be marked as pass and reported as a "flake".
200      * However, all the failing attempts will be recorded.
201      */
202     @Parameter( property = "surefire.rerunFailingTestsCount", defaultValue = "0" )
203     protected int rerunFailingTestsCount;
204 
205     /**
206      * (TestNG) List of &lt;suiteXmlFile> elements specifying TestNG suite xml file locations. Note that
207      * <code>suiteXmlFiles</code> is incompatible with several other parameters of this plugin, like
208      * <code>includes/excludes</code>.<br/>
209      * This parameter is ignored if the <code>test</code> parameter is specified (allowing you to run a single test
210      * instead of an entire suite).
211      *
212      * @since 2.2
213      */
214     @Parameter( property = "surefire.suiteXmlFiles" )
215     private File[] suiteXmlFiles;
216 
217     /**
218      * Defines the order the tests will be run in. Supported values are "alphabetical", "reversealphabetical", "random",
219      * "hourly" (alphabetical on even hours, reverse alphabetical on odd hours), "failedfirst", "balanced" and
220      * "filesystem".
221      * <br/>
222      * <br/>
223      * Odd/Even for hourly is determined at the time the of scanning the classpath, meaning it could change during a
224      * multi-module build.
225      * <br/>
226      * <br/>
227      * Failed first will run tests that failed on previous run first, as well as new tests for this run.
228      * <br/>
229      * <br/>
230      * Balanced is only relevant with parallel=classes, and will try to optimize the run-order of the tests reducing the
231      * overall execution time. Initially a statistics file is created and every next test run will reorder classes.
232      * <br/>
233      * <br/>
234      * Note that the statistics are stored in a file named .surefire-XXXXXXXXX beside pom.xml, and should not be checked
235      * into version control. The "XXXXX" is the SHA1 checksum of the entire surefire configuration, so different
236      * configurations will have different statistics files, meaning if you change any config settings you will re-run
237      * once before new statistics data can be established.
238      *
239      * @since 2.7
240      */
241     @Parameter( property = "surefire.runOrder", defaultValue = "filesystem" )
242     protected String runOrder;
243 
244     protected int getRerunFailingTestsCount()
245     {
246         return rerunFailingTestsCount;
247     }
248 
249     protected void handleSummary( RunResult summary, Exception firstForkException )
250         throws MojoExecutionException, MojoFailureException
251     {
252         assertNoException( firstForkException );
253 
254         SurefireHelper.reportExecution( this, summary, getLog() );
255     }
256 
257     private void assertNoException( Exception firstForkException )
258         throws MojoFailureException
259     {
260         if ( firstForkException != null )
261         {
262             throw new MojoFailureException( firstForkException.getMessage(), firstForkException );
263         }
264     }
265 
266     private void assertNoFailureOrTimeout( Exception summary )
267         throws MojoFailureException
268     {
269         if ( summary != null )
270         {
271             throw new MojoFailureException( "Failure or timeout" );
272         }
273     }
274 
275     protected boolean isSkipExecution()
276     {
277         return isSkip() || isSkipTests() || isSkipExec();
278     }
279 
280     protected String getPluginName()
281     {
282         return "surefire";
283     }
284 
285     protected String[] getDefaultIncludes()
286     {
287         return new String[]{ "**/Test*.java", "**/*Test.java", "**/*TestCase.java" };
288     }
289 
290     // now for the implementation of the field accessors
291 
292     public boolean isSkipTests()
293     {
294         return skipTests;
295     }
296 
297     public void setSkipTests( boolean skipTests )
298     {
299         this.skipTests = skipTests;
300     }
301 
302     /**
303      * @noinspection deprecation
304      */
305     public boolean isSkipExec()
306     {
307         return skipExec;
308     }
309 
310     /**
311      * @noinspection deprecation
312      */
313     public void setSkipExec( boolean skipExec )
314     {
315         this.skipExec = skipExec;
316     }
317 
318     public boolean isSkip()
319     {
320         return skip;
321     }
322 
323     public void setSkip( boolean skip )
324     {
325         this.skip = skip;
326     }
327 
328     public boolean isTestFailureIgnore()
329     {
330         return testFailureIgnore;
331     }
332 
333     public void setTestFailureIgnore( boolean testFailureIgnore )
334     {
335         this.testFailureIgnore = testFailureIgnore;
336     }
337 
338     public File getBasedir()
339     {
340         return basedir;
341     }
342 
343     public void setBasedir( File basedir )
344     {
345         this.basedir = basedir;
346     }
347 
348     public File getTestClassesDirectory()
349     {
350         return testClassesDirectory;
351     }
352 
353     public void setTestClassesDirectory( File testClassesDirectory )
354     {
355         this.testClassesDirectory = testClassesDirectory;
356     }
357 
358     public File getClassesDirectory()
359     {
360         return classesDirectory;
361     }
362 
363     public void setClassesDirectory( File classesDirectory )
364     {
365         this.classesDirectory = classesDirectory;
366     }
367 
368     public File getReportsDirectory()
369     {
370         return reportsDirectory;
371     }
372 
373     public void setReportsDirectory( File reportsDirectory )
374     {
375         this.reportsDirectory = reportsDirectory;
376     }
377 
378     public String getTest()
379     {
380         if ( StringUtils.isBlank( test ) )
381         {
382             return null;
383         }
384         String[] testArray = StringUtils.split( test, "," );
385         StringBuilder tests = new StringBuilder();
386         for ( String aTestArray : testArray )
387         {
388             String singleTest = aTestArray;
389             int index = singleTest.indexOf( '#' );
390             if ( index >= 0 )
391             { // the way version 2.7.3. support single test method
392                 singleTest = singleTest.substring( 0, index );
393             }
394             tests.append( singleTest );
395             tests.append( "," );
396         }
397         return tests.toString();
398     }
399 
400     /**
401      * @since 2.7.3
402      */
403     public String getTestMethod()
404     {
405         if ( StringUtils.isBlank( test ) )
406         {
407             return null;
408         }
409         //modified by rainLee, see http://jira.codehaus.org/browse/SUREFIRE-745
410         int index = this.test.indexOf( '#' );
411         int index2 = this.test.indexOf( "," );
412         if ( index >= 0 )
413         {
414             if ( index2 < 0 )
415             {
416                 String testStrAfterFirstSharp = this.test.substring( index + 1, this.test.length() );
417                 if ( !testStrAfterFirstSharp.contains( "+" ) )
418                 { //the original way
419                     return testStrAfterFirstSharp;
420                 }
421                 else
422                 {
423                     return this.test;
424                 }
425             }
426             else
427             {
428                 return this.test;
429             }
430         }
431         return null;
432     }
433 
434     public boolean isUseSystemClassLoader()
435     {
436         return useSystemClassLoader;
437     }
438 
439     public void setUseSystemClassLoader( boolean useSystemClassLoader )
440     {
441         this.useSystemClassLoader = useSystemClassLoader;
442     }
443 
444     public boolean isUseManifestOnlyJar()
445     {
446         return useManifestOnlyJar;
447     }
448 
449     public void setUseManifestOnlyJar( boolean useManifestOnlyJar )
450     {
451         this.useManifestOnlyJar = useManifestOnlyJar;
452     }
453 
454     public Boolean getFailIfNoSpecifiedTests()
455     {
456         return failIfNoSpecifiedTests;
457     }
458 
459     public void setFailIfNoSpecifiedTests( Boolean failIfNoSpecifiedTests )
460     {
461         this.failIfNoSpecifiedTests = failIfNoSpecifiedTests;
462     }
463 
464     public boolean isPrintSummary()
465     {
466         return printSummary;
467     }
468 
469     public void setPrintSummary( boolean printSummary )
470     {
471         this.printSummary = printSummary;
472     }
473 
474     public String getReportFormat()
475     {
476         return reportFormat;
477     }
478 
479     public void setReportFormat( String reportFormat )
480     {
481         this.reportFormat = reportFormat;
482     }
483 
484     public boolean isUseFile()
485     {
486         return useFile;
487     }
488 
489     public void setUseFile( boolean useFile )
490     {
491         this.useFile = useFile;
492     }
493 
494     public String getDebugForkedProcess()
495     {
496         return debugForkedProcess;
497     }
498 
499     public void setDebugForkedProcess( String debugForkedProcess )
500     {
501         this.debugForkedProcess = debugForkedProcess;
502     }
503 
504     public int getForkedProcessTimeoutInSeconds()
505     {
506         return forkedProcessTimeoutInSeconds;
507     }
508 
509     public void setForkedProcessTimeoutInSeconds( int forkedProcessTimeoutInSeconds )
510     {
511         this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
512     }
513 
514     public double getParallelTestsTimeoutInSeconds()
515     {
516         return parallelTestsTimeoutInSeconds;
517     }
518 
519     public void setParallelTestsTimeoutInSeconds( double parallelTestsTimeoutInSeconds )
520     {
521         this.parallelTestsTimeoutInSeconds = parallelTestsTimeoutInSeconds;
522     }
523 
524     public double getParallelTestsTimeoutForcedInSeconds()
525     {
526         return parallelTestsTimeoutForcedInSeconds;
527     }
528 
529     public void setParallelTestsTimeoutForcedInSeconds( double parallelTestsTimeoutForcedInSeconds )
530     {
531         this.parallelTestsTimeoutForcedInSeconds = parallelTestsTimeoutForcedInSeconds;
532     }
533 
534     public void setTest( String test )
535     {
536         this.test = test;
537     }
538 
539     @Override
540     public List<String> getIncludes()
541     {
542         return includes;
543     }
544 
545     @Override
546     public void setIncludes( List<String> includes )
547     {
548         this.includes = includes;
549     }
550 
551     public File[] getSuiteXmlFiles()
552     {
553         return suiteXmlFiles;
554     }
555 
556     @SuppressWarnings( "UnusedDeclaration" )
557     public void setSuiteXmlFiles( File[] suiteXmlFiles )
558     {
559         this.suiteXmlFiles = suiteXmlFiles;
560     }
561 
562     public String getRunOrder()
563     {
564         return runOrder;
565     }
566 
567     @SuppressWarnings( "UnusedDeclaration" )
568     public void setRunOrder( String runOrder )
569     {
570         this.runOrder = runOrder;
571     }
572 }