View Javadoc

1   package org.apache.maven.surefire.testng;
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.ArrayList;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Properties;
30  import java.util.SortedMap;
31  import java.util.TreeMap;
32  import org.apache.maven.artifact.versioning.ArtifactVersion;
33  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
34  import org.apache.maven.surefire.NonAbstractClassFilter;
35  import org.apache.maven.surefire.report.ConsoleOutputCapture;
36  import org.apache.maven.surefire.report.ConsoleOutputReceiver;
37  import org.apache.maven.surefire.report.ReportEntry;
38  import org.apache.maven.surefire.report.ReporterException;
39  import org.apache.maven.surefire.report.ReporterFactory;
40  import org.apache.maven.surefire.report.RunListener;
41  import org.apache.maven.surefire.report.SimpleReportEntry;
42  import org.apache.maven.surefire.testset.TestSetFailedException;
43  import org.apache.maven.surefire.util.LazyTestsToRun;
44  import org.apache.maven.surefire.util.RunOrderCalculator;
45  import org.apache.maven.surefire.util.ScanResult;
46  import org.apache.maven.surefire.util.TestsToRun;
47  
48  /**
49   * Test suite for TestNG based on a directory of Java test classes. Can also execute JUnit tests.
50   *
51   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
52   * @author <a href='mailto:the[dot]mindstorm[at]gmail[dot]com'>Alex Popescu</a>
53   */
54  public class TestNGDirectoryTestSuite
55      implements TestNgTestSuite
56  {
57      private final ArtifactVersion version;
58  
59      private final Map options;
60  
61      private final Map junitOptions;
62  
63      private final String testSourceDirectory;
64  
65      private final File reportsDirectory;
66  
67      private SortedMap testSets;
68  
69      private final ScanResult scanResult;
70  
71      private final String testMethodPattern;
72  
73      private final RunOrderCalculator runOrderCalculator;
74  
75      private final Class junitTestClass;
76  
77      public TestNGDirectoryTestSuite( String testSourceDirectory, String artifactVersion, Properties confOptions,
78                                       File reportsDirectory, String testMethodPattern,
79                                       RunOrderCalculator runOrderCalculator, ScanResult scanResult )
80      {
81  
82          this.runOrderCalculator = runOrderCalculator;
83  
84          this.options = confOptions;
85  
86          this.testSourceDirectory = testSourceDirectory;
87          this.reportsDirectory = reportsDirectory;
88          this.scanResult = scanResult;
89          this.version = new DefaultArtifactVersion( artifactVersion );
90          this.testMethodPattern = testMethodPattern;
91          this.junitTestClass = findJUnitTestClass();
92          this.junitOptions = createJUnitOptions();
93      }
94  
95      public void execute( TestsToRun testsToRun, ReporterFactory reporterManagerFactory )
96          throws ReporterException, TestSetFailedException
97      {
98  
99          if ( !testsToRun.allowEagerReading() )
100         {
101             executeLazy( testsToRun, reporterManagerFactory );
102         }
103         else if ( testsToRun.containsAtLeast( 2 ) )
104         {
105             executeMulti( testsToRun, reporterManagerFactory );
106         }
107         else if ( testsToRun.containsAtLeast( 1 ) )
108         {
109             Class testClass = (Class) testsToRun.iterator().next();
110             executeSingleClass( reporterManagerFactory, testClass );
111         }
112     }
113 
114     private void executeSingleClass( ReporterFactory reporterManagerFactory, Class testClass )
115         throws TestSetFailedException
116     {
117         this.options.put( "suitename", testClass.getName() );
118 
119         RunListener reporter = reporterManagerFactory.createReporter();
120         ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporter );
121 
122         startTestSuite( reporter, this );
123 
124         final Map optionsToUse = isJUnitTest( testClass ) ? junitOptions : options;
125 
126         TestNGExecutor.run( new Class[]{ testClass }, testSourceDirectory, optionsToUse, version, reporter, this,
127                             reportsDirectory, testMethodPattern );
128 
129         finishTestSuite( reporter, this );
130     }
131 
132     public void executeLazy( TestsToRun testsToRun, ReporterFactory reporterFactory )
133         throws ReporterException, TestSetFailedException
134     {
135 
136         for ( Iterator testClassIt = testsToRun.iterator(); testClassIt.hasNext(); )
137         {
138             Class c = (Class) testClassIt.next();
139             executeSingleClass( reporterFactory, c );
140         }
141     }
142 
143     private Class findJUnitTestClass()
144     {
145         Class junitTest;
146         try
147         {
148             junitTest = Class.forName( "junit.framework.Test" );
149         }
150         catch ( ClassNotFoundException e )
151         {
152             junitTest = null;
153         }
154         return junitTest;
155     }
156 
157     public void executeMulti( TestsToRun testsToRun, ReporterFactory reporterFactory )
158         throws ReporterException, TestSetFailedException
159     {
160         List testNgTestClasses = new ArrayList();
161         List junitTestClasses = new ArrayList();
162         for ( Iterator it = testsToRun.iterator(); it.hasNext(); )
163         {
164             Class c = (Class) it.next();
165             if ( isJUnitTest( c ) )
166             {
167                 junitTestClasses.add( c );
168             }
169             else
170             {
171                 testNgTestClasses.add( c );
172             }
173         }
174 
175         File testNgReportsDirectory = reportsDirectory, junitReportsDirectory = reportsDirectory;
176 
177         if ( junitTestClasses.size() > 0 && testNgTestClasses.size() > 0 )
178         {
179             testNgReportsDirectory = new File( reportsDirectory, "testng-native-results" );
180             junitReportsDirectory = new File( reportsDirectory, "testng-junit-results" );
181         }
182 
183         RunListener reporterManager = reporterFactory.createReporter();
184         ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporterManager );
185         startTestSuite( reporterManager, this );
186 
187         Class[] testClasses = (Class[]) testNgTestClasses.toArray( new Class[testNgTestClasses.size()] );
188 
189         TestNGExecutor.run( testClasses, this.testSourceDirectory, options, version, reporterManager, this,
190                             testNgReportsDirectory, testMethodPattern );
191 
192         if ( junitTestClasses.size() > 0 )
193         {
194             testClasses = (Class[]) junitTestClasses.toArray( new Class[junitTestClasses.size()] );
195 
196             TestNGExecutor.run( testClasses, testSourceDirectory, junitOptions, version, reporterManager, this,
197                                 junitReportsDirectory, testMethodPattern );
198         }
199 
200         finishTestSuite( reporterManager, this );
201     }
202 
203     private boolean isJUnitTest( Class c )
204     {
205         return junitTestClass != null && junitTestClass.isAssignableFrom( c );
206     }
207 
208     private Map createJUnitOptions()
209     {
210         Map junitOptions = new HashMap( this.options );
211         junitOptions.put( "junit", Boolean.TRUE );
212         return junitOptions;
213     }
214 
215     // single class test
216     public void execute( String testSetName, ReporterFactory reporterManagerFactory )
217         throws ReporterException, TestSetFailedException
218     {
219         if ( testSets == null )
220         {
221             throw new IllegalStateException( "You must call locateTestSets before calling execute" );
222         }
223         TestNGTestSet testSet = (TestNGTestSet) testSets.get( testSetName );
224 
225         if ( testSet == null )
226         {
227             throw new TestSetFailedException( "Unable to find test set '" + testSetName + "' in suite" );
228         }
229 
230         RunListener reporter = reporterManagerFactory.createReporter();
231         ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporter );
232 
233         startTestSuite( reporter, this );
234 
235         TestNGExecutor.run( new Class[]{ testSet.getTestClass() }, this.testSourceDirectory, this.options, this.version,
236                             reporter, this, reportsDirectory, testMethodPattern );
237 
238         finishTestSuite( reporter, this );
239     }
240 
241     public static void startTestSuite( RunListener reporter, Object suite )
242     {
243         ReportEntry report = new SimpleReportEntry( suite.getClass().getName(), getSuiteName( suite ) );
244 
245         try
246         {
247             reporter.testSetStarting( report );
248         }
249         catch ( ReporterException e )
250         {
251             // TODO: remove this exception from the report manager
252         }
253     }
254 
255     public static void finishTestSuite( RunListener reporterManager, Object suite )
256         throws ReporterException
257     {
258         ReportEntry report = new SimpleReportEntry( suite.getClass().getName(), getSuiteName( suite ) );
259 
260         reporterManager.testSetCompleted( report );
261     }
262 
263     public String getSuiteName()
264     {
265         String result = (String) options.get( "suitename" );
266         if ( result == null )
267         {
268             result = "TestSuite";
269         }
270         return result;
271     }
272 
273     private static String getSuiteName( Object suite )
274     {
275         String result;
276         if ( suite instanceof TestNGDirectoryTestSuite )
277         {
278             return ( (TestNGDirectoryTestSuite) suite ).getSuiteName();
279         }
280         else if ( suite instanceof TestNGXmlTestSuite )
281         {
282             return ( (TestNGXmlTestSuite) suite ).getSuiteName();
283         }
284         else
285         {
286             result = "TestSuite";
287         }
288 
289         return result;
290     }
291 
292     public Map locateTestSets( ClassLoader classLoader )
293         throws TestSetFailedException
294     {
295         if ( testSets != null )
296         {
297             throw new IllegalStateException( "You can't call locateTestSets twice" );
298         }
299         testSets = new TreeMap();
300 
301         final TestsToRun scanned = scanResult.applyFilter( new NonAbstractClassFilter(), classLoader );
302 
303         final TestsToRun testsToRun = runOrderCalculator.orderTestClasses( scanned );
304 
305         for ( Iterator it = testsToRun.iterator(); it.hasNext(); )
306         {
307             Class testClass = (Class) it.next();
308             TestNGTestSet testSet = new TestNGTestSet( testClass );
309 
310             if ( testSets.containsKey( testSet.getName() ) )
311             {
312                 throw new TestSetFailedException( "Duplicate test set '" + testSet.getName() + "'" );
313             }
314             testSets.put( testSet.getName(), testSet );
315 
316         }
317 
318         return Collections.unmodifiableSortedMap( testSets );
319     }
320 
321 }