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 org.apache.maven.artifact.Artifact;
23  import org.apache.maven.artifact.factory.ArtifactFactory;
24  import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
25  import org.apache.maven.artifact.repository.ArtifactRepository;
26  import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
27  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
28  import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
29  import org.apache.maven.artifact.resolver.ArtifactResolver;
30  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
31  import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
32  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
33  import org.apache.maven.artifact.versioning.VersionRange;
34  import org.apache.maven.plugin.AbstractMojo;
35  import org.apache.maven.plugin.MojoExecutionException;
36  import org.apache.maven.plugin.MojoFailureException;
37  import org.apache.maven.surefire.booter.ForkConfiguration;
38  import org.apache.maven.surefire.booter.SurefireBooter;
39  import org.apache.maven.surefire.booter.SurefireBooterForkException;
40  import org.apache.maven.surefire.booter.SurefireExecutionException;
41  import org.apache.maven.surefire.report.BriefConsoleReporter;
42  import org.apache.maven.surefire.report.BriefFileReporter;
43  import org.apache.maven.surefire.report.ConsoleReporter;
44  import org.apache.maven.surefire.report.DetailedConsoleReporter;
45  import org.apache.maven.surefire.report.FileReporter;
46  import org.apache.maven.surefire.report.ForkingConsoleReporter;
47  import org.apache.maven.surefire.report.XMLReporter;
48  import org.codehaus.plexus.util.StringUtils;
49  
50  import java.io.File;
51  import java.util.ArrayList;
52  import java.util.Arrays;
53  import java.util.Collections;
54  import java.util.HashMap;
55  import java.util.Iterator;
56  import java.util.List;
57  import java.util.Map;
58  import java.util.Properties;
59  
60  /**
61   * Run tests using Surefire.
62   *
63   * @author Jason van Zyl
64   * @version $Id: SurefirePlugin.java 493522 2007-01-06 18:08:15Z jvanzyl $
65   * @requiresDependencyResolution test
66   * @goal test
67   * @phase test
68   */
69  public class SurefirePlugin
70      extends AbstractMojo
71  {
72      /**
73       * Set this to 'true' to bypass unit tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion.
74       *
75       * @parameter expression="${maven.test.skip}"
76       */
77      private boolean skip;
78  
79      /**
80       * Set this to 'true' to bypass unit tests execution, but still compile them. Its use is NOT RECOMMENDED, but quite convenient on occasion.
81       *
82       * @parameter expression="${maven.test.skip.exec}"
83       */
84      private boolean skipExec;
85  
86      /**
87       * Set this to true to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on occasion.
88       *
89       * @parameter expression="${maven.test.failure.ignore}"
90       */
91      private boolean testFailureIgnore;
92  
93      /**
94       * The base directory of the project being tested. This can be obtained in your unit test by System.getProperty("basedir").
95       *
96       * @parameter expression="${basedir}"
97       * @required
98       */
99      private File basedir;
100 
101     // FIXME this field is not used
102     /**
103      * The directory containing generated classes of the project being tested.
104      *
105      * @parameter expression="${project.build.outputDirectory}"
106      * @required
107      */
108     private File classesDirectory;
109 
110     /**
111      * The directory containing generated test classes of the project being tested.
112      *
113      * @parameter expression="${project.build.testOutputDirectory}"
114      * @required
115      */
116     private File testClassesDirectory;
117 
118     /**
119      * The classpath elements of the project being tested.
120      *
121      * @parameter expression="${project.testClasspathElements}"
122      * @required
123      * @readonly
124      */
125     private List classpathElements;
126 
127     /**
128      * Base directory where all reports are written to.
129      *
130      * @parameter expression="${project.build.directory}/surefire-reports"
131      */
132     private File reportsDirectory;
133 
134     /**
135      * The test source directory containing test class sources.
136      *
137      * @parameter expression="${project.build.testSourceDirectory}"
138      * @required
139      */
140     private File testSourceDirectory;
141 
142     /**
143      * Specify this parameter(can be a comma separated list) if you want to use the test pattern matching notation, Ant pattern matching, to select tests to run.
144      * The Ant pattern will be used to create an include pattern formatted like <code>**&#47;${test}.java</code>
145      * When used, the <code>includes</code> and <code>excludes</code> patterns parameters are ignored.
146      *
147      * @parameter expression="${test}"
148      */
149     private String test;
150 
151     /**
152      * List of patterns (separated by commas) used to specify the tests that should be included in testing.
153      * When not specified and when the <code>test</code> parameter is not specified, the default includes will be
154      * <code>**&#47;Test*.java   **&#47;*Test.java   **&#47;*TestCase.java</code>
155      *
156      * @parameter
157      */
158     private List includes;
159 
160     /**
161      * List of patterns (separated by commas) used to specify the tests that should be excluded in testing.
162      * When not specified and when the <code>test</code> parameter is not specified, the default excludes will be
163      * <code>**&#47;Abstract*Test.java  **&#47;Abstract*TestCase.java **&#47;*$*</code>
164      *
165      * @parameter
166      */
167     private List excludes;
168 
169     /**
170      * ArtifactRepository of the localRepository. To obtain the directory of localRepository in unit tests use System.setProperty( "localRepository").
171      *
172      * @parameter expression="${localRepository}"
173      * @required
174      * @readonly
175      */
176     private ArtifactRepository localRepository;
177 
178     /**
179      * List of System properties to pass to the JUnit tests.
180      *
181      * @parameter
182      */
183     private Properties systemProperties;
184 
185     /**
186      * Map of of plugin artifacts.
187      *
188      * @parameter expression="${plugin.artifactMap}"
189      * @required
190      * @readonly
191      */
192     private Map pluginArtifactMap;
193 
194     /**
195      * Map of of project artifacts.
196      *
197      * @parameter expression="${project.artifactMap}"
198      * @required
199      * @readonly
200      */
201     private Map projectArtifactMap;
202 
203     /**
204      * Option to print summary of test suites or just print the test cases that has errors.
205      *
206      * @parameter expression="${surefire.printSummary}"
207      * default-value="true"
208      */
209     private boolean printSummary;
210 
211     /**
212      * Selects the formatting for the test report to be generated.  Can be set as brief or plain.
213      *
214      * @parameter expression="${surefire.reportFormat}"
215      * default-value="brief"
216      */
217     private String reportFormat;
218 
219     /**
220      * Option to generate a file test report or just output the test report to the console.
221      *
222      * @parameter expression="${surefire.useFile}"
223      * default-value="true"
224      */
225     private boolean useFile;
226 
227     /**
228      * When forking, set this to true to redirect the unit test standard output to a file
229      * (found in reportsDirectory/testName-output.txt).
230      *
231      * @parameter expression="${maven.test.redirectTestOutputToFile}" default-value="false"
232      */
233     private boolean redirectTestOutputToFile;
234 
235     /**
236      * Option to specify the forking mode. Can be "never", "once" or "always".
237      * "none" and "pertest" are also accepted for backwards compatibility.
238      *
239      * @parameter expression="${forkMode}" default-value="once"
240      */
241     private String forkMode;
242 
243     /**
244      * Option to specify the jvm (or path to the java executable) to use with
245      * the forking options. For the default, the jvm will be the same as the one
246      * used to run Maven.
247      *
248      * @parameter expression="${jvm}"
249      */
250     private String jvm;
251 
252     /**
253      * Arbitrary options to set on the command line.
254      *
255      * @parameter expression="${argLine}"
256      */
257     private String argLine;
258 
259     /**
260      * Additional environments to set on the command line.
261      *
262      * @parameter
263      */
264     private Map environmentVariables = new HashMap();
265 
266     /**
267      * Command line working directory.
268      *
269      * @parameter
270      */
271     private File workingDirectory;
272 
273     /**
274      * When false it makes tests run using the standard classloader delegation instead of the default
275      * Maven isolated classloader. Only used when forking (forkMode is not "none").<br/>
276      * Setting it to false helps with some problems caused by conflicts between
277      * xml parsers in the classpath and the Java 5 provider parser.
278      *
279      * @parameter expression="${childDelegation}"
280      * default-value="false"
281      */
282     private boolean childDelegation;
283 
284     /**
285      * Groups for this test. Only classes/methods/etc decorated with one of the
286      * groups specified here will be included in test run, if specified.
287      *
288      * @parameter expression="${groups}"
289      */
290     private String groups;
291 
292     /**
293      * Excluded groups. Any methods/classes/etc with one of the groups specified in this
294      * list will specifically not be run.
295      *
296      * @parameter expression="${excludedGroups}"
297      */
298     private String excludedGroups;
299 
300     /**
301      * List of TestNG suite xml file locations, seperated by commas. It should be noted that
302      * if suiteXmlFiles is specified, <b>no</b> other tests will be run, ignoring other parameters,
303      * like includes and excludes.
304      *
305      * @parameter
306      */
307     private File[] suiteXmlFiles;
308 
309     /**
310      * The attribute thread-count allows you to specify how many threads should be allocated
311      * for this execution. Only makes sense to use in conjunction with parallel.
312      *
313      * @parameter expression="${threadCount}"
314      * default-value="5"
315      */
316     private int threadCount;
317 
318     /**
319      * When you use the parallel attribute, TestNG will try to run all your test methods in
320      * separate threads, except for methods that depend on each other, which will be run in
321      * the same thread in order to respect their order of execution.
322      *
323      * @parameter expression="${parallel}"
324      * default-value="false"
325      * @todo test how this works with forking, and console/file output parallelism
326      */
327     private boolean parallel;
328 
329     /**
330      * Whether to trim the stack trace in the reports to just the lines within the test, or show the full trace.
331      *
332      * @parameter expression="${trimStackTrace}" default-value="true"
333      */
334     private boolean trimStackTrace;
335 
336     /**
337      * Resolves the artifacts needed.
338      *
339      * @component
340      */
341     private ArtifactResolver artifactResolver;
342 
343     /**
344      * Creates the artifact
345      *
346      * @component
347      */
348     private ArtifactFactory artifactFactory;
349 
350     /**
351      * The plugin remote repositories declared in the pom.
352      *
353      * @parameter expression="${project.pluginArtifactRepositories}"
354      */
355     private List remoteRepositories;
356 
357     /**
358      * For retrieval of artifact's metadata.
359      *
360      * @component
361      */
362     private ArtifactMetadataSource metadataSource;
363 
364     private static final String BRIEF_REPORT_FORMAT = "brief";
365 
366     private static final String PLAIN_REPORT_FORMAT = "plain";
367 
368     private Properties originalSystemProperties;
369 
370     /**
371      * Flag to disable the generation of report files in xml format.
372      *
373      * @parameter expression="${disableXmlReport}" default-value="false"
374      */
375     private boolean disableXmlReport;
376 
377     /**
378      * Option to pass dependencies to the system's classloader instead of using an isolated class loader when
379      * forking. Prevents problems with JDKs which implement the service provider lookup mechanism by using
380      * the system's classloader.
381      *
382      * @parameter expression="${surefire.useSystemClassLoader}" default-value="false"
383      */
384     private boolean useSystemClassLoader;
385 
386     public void execute()
387         throws MojoExecutionException, MojoFailureException
388     {
389         if ( verifyParameters() )
390         {
391             SurefireBooter surefireBooter = constructSurefireBooter();
392 
393             getLog().info( "Surefire report directory: " + reportsDirectory );
394 
395             boolean success;
396             try
397             {
398                 success = surefireBooter.run();
399             }
400             catch ( SurefireBooterForkException e )
401             {
402                 throw new MojoExecutionException( e.getMessage(), e );
403             }
404             catch ( SurefireExecutionException e )
405             {
406                 throw new MojoExecutionException( e.getMessage(), e );
407             }
408 
409             if ( originalSystemProperties != null )
410             {
411                 // restore system properties
412                 System.setProperties( originalSystemProperties );
413             }
414 
415             if ( !success )
416             {
417                 String msg = "There are test failures.";
418 
419                 if ( testFailureIgnore )
420                 {
421                     getLog().error( msg );
422                 }
423                 else
424                 {
425                     throw new MojoFailureException( msg );
426                 }
427             }
428         }
429     }
430 
431     private boolean verifyParameters()
432         throws MojoFailureException
433     {
434         if ( skip || skipExec )
435         {
436             getLog().info( "Tests are skipped." );
437             return false;
438         }
439         else if ( !testClassesDirectory.exists() )
440         {
441             getLog().info( "No tests to run." );
442             return false;
443         }
444 
445         if ( parallel )
446         {
447             if ( threadCount < 1 )
448             {
449                 throw new MojoFailureException( "Must have at least one thread in parallel mode" );
450             }
451         }
452 
453         if ( useSystemClassLoader && ForkConfiguration.FORK_NEVER.equals( forkMode ) )
454         {
455             getLog().warn( "useSystemClassloader=true setting has no effect when not forking" );
456         }
457 
458         return true;
459     }
460 
461     private SurefireBooter constructSurefireBooter()
462         throws MojoExecutionException, MojoFailureException
463     {
464         SurefireBooter surefireBooter = new SurefireBooter();
465 
466         Artifact surefireArtifact = (Artifact) pluginArtifactMap.get( "org.apache.maven.surefire:surefire-booter" );
467         if ( surefireArtifact == null )
468         {
469             throw new MojoExecutionException( "Unable to locate surefire-booter in the list of plugin artifacts" );
470         }
471 
472         surefireArtifact.isSnapshot(); // TODO: this is ridiculous, but it fixes getBaseVersion to be -SNAPSHOT if needed
473 
474         Artifact junitArtifact;
475         Artifact testNgArtifact;
476         try
477         {
478             addArtifact( surefireBooter, surefireArtifact );
479 
480             junitArtifact = (Artifact) projectArtifactMap.get( "junit:junit" );
481 
482             // TODO: this is pretty manual, but I'd rather not require the plugin > dependencies section right now
483             testNgArtifact = (Artifact) projectArtifactMap.get( "org.testng:testng" );
484 
485             if ( testNgArtifact != null )
486             {
487                 addArtifact(surefireBooter, testNgArtifact);
488 
489                 VersionRange range = VersionRange.createFromVersionSpec( "[4.7,)" );
490                 if ( !range.containsVersion( testNgArtifact.getSelectedVersion() ) )
491                 {
492                     throw new MojoFailureException(
493                         "TestNG support requires version 4.7 or above. You have declared version " +
494                             testNgArtifact.getVersion() );
495                 }
496 
497                 // The plugin uses a JDK based profile to select the right testng. We might be explicity using a
498                 // different one since its based on the source level, not the JVM. Prune using the filter.
499                 addProvider( surefireBooter, "surefire-testng", surefireArtifact.getBaseVersion(), testNgArtifact );
500             }
501             else if (junitArtifact != null && junitArtifact.getBaseVersion().startsWith("4"))
502             {
503                 addProvider( surefireBooter, "surefire-junit4", surefireArtifact.getBaseVersion(), null );
504             }
505             else
506             {
507                 // add the JUnit provider as default - it doesn't require JUnit to be present,
508                 // since it supports POJO tests.
509                 addProvider( surefireBooter, "surefire-junit", surefireArtifact.getBaseVersion(), null );
510             }
511         }
512         catch ( ArtifactNotFoundException e )
513         {
514             throw new MojoExecutionException(
515                 "Unable to locate required surefire provider dependency: " + e.getMessage(), e );
516         }
517         catch ( InvalidVersionSpecificationException e )
518         {
519             throw new MojoExecutionException( "Error determining the TestNG version requested: " + e.getMessage(), e );
520         }
521         catch ( ArtifactResolutionException e )
522         {
523             throw new MojoExecutionException( "Error to resolving surefire provider dependency: " + e.getMessage(), e );
524         }
525 
526         if ( suiteXmlFiles != null && suiteXmlFiles.length > 0 )
527         {
528             if ( testNgArtifact == null )
529             {
530                 throw new MojoExecutionException( "suiteXmlFiles is configured, but there is no TestNG dependency" );
531             }
532             for ( int i = 0; i < suiteXmlFiles.length; i++ )
533             {
534                 File file = suiteXmlFiles[i];
535                 if ( file.exists() )
536                 {
537                     surefireBooter.addTestSuite( "org.apache.maven.surefire.testng.TestNGXmlTestSuite",
538                                                  new Object[]{file, testSourceDirectory.getAbsolutePath()} );
539                 }
540             }
541         }
542         else
543         {
544             List includes;
545             List excludes;
546 
547             if ( test != null )
548             {
549                 // Check to see if we are running a single test. The raw parameter will
550                 // come through if it has not been set.
551 
552                 // FooTest -> **/FooTest.java
553 
554                 includes = new ArrayList();
555 
556                 excludes = new ArrayList();
557 
558                 String[] testRegexes = StringUtils.split( test, "," );
559 
560                 for ( int i = 0; i < testRegexes.length; i++ )
561                 {
562                     includes.add( "**/" + testRegexes[i] + ".java" );
563                 }
564             }
565             else
566             {
567                 includes = this.includes;
568 
569                 excludes = this.excludes;
570 
571                 // defaults here, qdox doesn't like the end javadoc value
572                 // Have to wrap in an ArrayList as surefire expects an ArrayList instead of a List for some reason
573                 if ( includes == null || includes.size() == 0 )
574                 {
575                     includes = new ArrayList(
576                         Arrays.asList( new String[]{"**/Test*.java", "**/*Test.java", "**/*TestCase.java"} ) );
577                 }
578                 if ( excludes == null || excludes.size() == 0 )
579                 {
580                     excludes = new ArrayList(
581                         Arrays.asList( new String[]{"**/Abstract*Test.java", "**/Abstract*TestCase.java", "**/*$*"} ) );
582                 }
583             }
584 
585             if ( testNgArtifact != null )
586             {
587                 surefireBooter.addTestSuite( "org.apache.maven.surefire.testng.TestNGDirectoryTestSuite", new Object[]{
588                     testClassesDirectory, includes, excludes, groups, excludedGroups, Boolean.valueOf( parallel ),
589                     new Integer( threadCount ), testSourceDirectory.getAbsolutePath()} );
590             }
591             else
592             {
593             	String junitDirectoryTestSuite;
594             	if (junitArtifact.getBaseVersion().startsWith("4")) 
595             	{
596             		junitDirectoryTestSuite = "org.apache.maven.surefire.junit4.JUnit4DirectoryTestSuite";
597             	} 
598             	else
599             	{
600             		junitDirectoryTestSuite = "org.apache.maven.surefire.junit.JUnitDirectoryTestSuite";
601             	}
602             		
603                 // fall back to JUnit, which also contains POJO support. Also it can run
604                 // classes compiled against JUnit since it has a dependency on JUnit itself.
605                 surefireBooter.addTestSuite( junitDirectoryTestSuite,
606                                              new Object[]{testClassesDirectory, includes, excludes} );
607             }
608         }
609 
610         // ----------------------------------------------------------------------
611         //
612         // ----------------------------------------------------------------------
613 
614         getLog().debug( "Test Classpath :" );
615 
616         // no need to add classes/test classes directory here - they are in the classpath elements already
617 
618         for ( Iterator i = classpathElements.iterator(); i.hasNext(); )
619         {
620             String classpathElement = (String) i.next();
621 
622             getLog().debug( "  " + classpathElement );
623 
624             surefireBooter.addClassPathUrl( classpathElement );
625         }
626 
627         // ----------------------------------------------------------------------
628         // Forking
629         // ----------------------------------------------------------------------
630 
631         ForkConfiguration fork = new ForkConfiguration();
632 
633         fork.setForkMode( forkMode );
634 
635         processSystemProperties( !fork.isForking() );
636 
637         if ( getLog().isDebugEnabled() )
638         {
639             showMap( systemProperties, "system property" );
640         }
641 
642         if ( fork.isForking() )
643         {
644             fork.setSystemProperties( systemProperties );
645 
646             if ( jvm == null || "".equals( jvm ) )
647             {
648                 // use the same JVM as the one used to run Maven (the "java.home" one)
649                 jvm = System.getProperty( "java.home" ) + File.separator + "bin" + File.separator + "java";
650                 getLog().debug( "Using JVM: " + jvm );
651             }
652 
653             fork.setJvmExecutable( jvm );
654 
655             if ( workingDirectory != null )
656             {
657                 fork.setWorkingDirectory( workingDirectory );
658             }
659             else
660             {
661                 fork.setWorkingDirectory( basedir );
662             }
663 
664             fork.setArgLine( argLine );
665 
666             fork.setEnvironmentVariables( environmentVariables );
667 
668             if ( getLog().isDebugEnabled() )
669             {
670                 showMap( environmentVariables, "environment variable" );
671 
672                 fork.setDebug( true );
673             }
674         }
675 
676         surefireBooter.setRedirectTestOutputToFile( redirectTestOutputToFile );
677 
678         surefireBooter.setForkConfiguration( fork );
679 
680         surefireBooter.setChildDelegation( childDelegation );
681 
682         surefireBooter.setReportsDirectory( reportsDirectory );
683 
684         surefireBooter.setUseSystemClassLoader( useSystemClassLoader );
685 
686         addReporters( surefireBooter, fork.isForking() );
687 
688         return surefireBooter;
689     }
690 
691     private void showMap( Map map, String setting )
692     {
693         for ( Iterator i = map.keySet().iterator(); i.hasNext(); )
694         {
695             String key = (String) i.next();
696             String value = (String) map.get( key );
697             getLog().debug( "Setting " + setting + " [" + key + "]=[" + value + "]" );
698         }
699     }
700 
701     private void addProvider( SurefireBooter surefireBooter, String provider, String version,
702                               Artifact filteredArtifact )
703         throws ArtifactNotFoundException, ArtifactResolutionException
704     {
705         Artifact providerArtifact = artifactFactory.createDependencyArtifact( "org.apache.maven.surefire", provider,
706                                                                               VersionRange.createFromVersion( version ),
707                                                                               "jar", null, Artifact.SCOPE_TEST );
708         ArtifactResolutionResult result = resolveArtifact( filteredArtifact, providerArtifact );
709 
710         for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
711         {
712             Artifact artifact = (Artifact) i.next();
713 
714             getLog().debug( "Adding to surefire test classpath: " + artifact.getFile().getAbsolutePath() );
715 
716             surefireBooter.addSurefireClassPathUrl( artifact.getFile().getAbsolutePath() );
717         }
718     }
719 
720     private ArtifactResolutionResult resolveArtifact( Artifact filteredArtifact, Artifact providerArtifact )
721         throws ArtifactResolutionException, ArtifactNotFoundException
722     {
723         ArtifactFilter filter = null;
724         if ( filteredArtifact != null )
725         {
726             filter = new ExcludesArtifactFilter(
727                 Collections.singletonList( filteredArtifact.getGroupId() + ":" + filteredArtifact.getArtifactId() ) );
728         }
729 
730         Artifact originatingArtifact = artifactFactory.createBuildArtifact( "dummy", "dummy", "1.0", "jar" );
731 
732         return artifactResolver.resolveTransitively( Collections.singleton( providerArtifact ), originatingArtifact,
733                                                      localRepository, remoteRepositories, metadataSource, filter );
734     }
735 
736     private void addArtifact( SurefireBooter surefireBooter, Artifact surefireArtifact )
737         throws ArtifactNotFoundException, ArtifactResolutionException
738     {
739         ArtifactResolutionResult result = resolveArtifact( null, surefireArtifact );
740 
741         for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
742         {
743             Artifact artifact = (Artifact) i.next();
744 
745             getLog().debug( "Adding to surefire booter test classpath: " + artifact.getFile().getAbsolutePath() );
746 
747             surefireBooter.addSurefireBootClassPathUrl( artifact.getFile().getAbsolutePath() );
748         }
749     }
750 
751     protected void processSystemProperties( boolean setInSystem )
752     {
753         if ( systemProperties == null )
754         {
755             systemProperties = new Properties();
756         }
757 
758         originalSystemProperties = (Properties) System.getProperties().clone();
759 
760         systemProperties.setProperty( "basedir", basedir.getAbsolutePath() );
761 
762         systemProperties.setProperty( "localRepository", localRepository.getBasedir() );
763 
764         if ( setInSystem )
765         {
766             // Add all system properties configured by the user
767             Iterator iter = systemProperties.keySet().iterator();
768 
769             while ( iter.hasNext() )
770             {
771                 String key = (String) iter.next();
772 
773                 String value = systemProperties.getProperty( key );
774 
775                 System.setProperty( key, value );
776             }
777         }
778     }
779 
780     /**
781      * <p> Adds Reporters that will generate reports with different formatting.
782      * <p> The Reporter that will be added will be based on the value of the parameter
783      * useFile, reportFormat, and printSummary.
784      *
785      * @param surefireBooter The surefire booter that will run tests.
786      * @param forking
787      */
788     private void addReporters( SurefireBooter surefireBooter, boolean forking )
789     {
790         Boolean trimStackTrace = Boolean.valueOf( this.trimStackTrace );
791         if ( useFile )
792         {
793             if ( printSummary )
794             {
795                 if ( forking )
796                 {
797                     surefireBooter.addReport( ForkingConsoleReporter.class.getName(), new Object[]{trimStackTrace} );
798                 }
799                 else
800                 {
801                     surefireBooter.addReport( ConsoleReporter.class.getName(), new Object[]{trimStackTrace} );
802                 }
803             }
804 
805             if ( BRIEF_REPORT_FORMAT.equals( reportFormat ) )
806             {
807                 surefireBooter.addReport( BriefFileReporter.class.getName(),
808                                           new Object[]{reportsDirectory, trimStackTrace} );
809             }
810             else if ( PLAIN_REPORT_FORMAT.equals( reportFormat ) )
811             {
812                 surefireBooter.addReport( FileReporter.class.getName(),
813                                           new Object[]{reportsDirectory, trimStackTrace} );
814             }
815         }
816         else
817         {
818             if ( BRIEF_REPORT_FORMAT.equals( reportFormat ) )
819             {
820                 surefireBooter.addReport( BriefConsoleReporter.class.getName(), new Object[]{trimStackTrace} );
821             }
822             else if ( PLAIN_REPORT_FORMAT.equals( reportFormat ) )
823             {
824                 surefireBooter.addReport( DetailedConsoleReporter.class.getName(), new Object[]{trimStackTrace} );
825             }
826         }
827 
828         if ( !disableXmlReport )
829         {
830             surefireBooter.addReport( XMLReporter.class.getName(), new Object[]{reportsDirectory, trimStackTrace} );
831         }
832     }
833 
834     /**
835      * @return SurefirePlugin Returns the skipExec.
836      */
837     public boolean isSkipExec()
838     {
839         return this.skipExec;
840     }
841 
842     /**
843      * @param skipExec the skipExec to set
844      */
845     public void setSkipExec( boolean skipExec )
846     {
847         this.skipExec = skipExec;
848     }
849 }