1 package org.apache.maven.surefire.testng;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.lang.annotation.Annotation;
24 import java.lang.reflect.Method;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Properties;
31 import java.util.SortedMap;
32 import java.util.TreeMap;
33
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.RunOrderCalculator;
44 import org.apache.maven.surefire.util.ScanResult;
45 import org.apache.maven.surefire.util.TestsToRun;
46
47
48
49
50
51
52
53 public class TestNGDirectoryTestSuite
54 implements TestNgTestSuite
55 {
56
57 private final Map options;
58
59 private final Map junitOptions;
60
61 private final String testSourceDirectory;
62
63 private final File reportsDirectory;
64
65 private SortedMap<String, TestNGTestSet> testSets;
66
67 private final ScanResult scanResult;
68
69 private final String testMethodPattern;
70
71 private final RunOrderCalculator runOrderCalculator;
72
73 private final Class junitTestClass;
74
75 private Class<? extends Annotation> junitRunWithAnnotation;
76
77 private Class<? extends Annotation> junitTestAnnotation;
78
79 public TestNGDirectoryTestSuite( String testSourceDirectory, Properties confOptions, File reportsDirectory, String testMethodPattern,
80 RunOrderCalculator runOrderCalculator, ScanResult scanResult )
81 {
82
83 this.runOrderCalculator = runOrderCalculator;
84
85 this.options = confOptions;
86
87 this.testSourceDirectory = testSourceDirectory;
88 this.reportsDirectory = reportsDirectory;
89 this.scanResult = scanResult;
90 this.testMethodPattern = testMethodPattern;
91 this.junitTestClass = findJUnitTestClass();
92 this.junitRunWithAnnotation = findJUnitRunWithAnnotation();
93 this.junitTestAnnotation = findJUnitTestAnnotation();
94 this.junitOptions = createJUnitOptions();
95 }
96
97 public void execute( TestsToRun testsToRun, ReporterFactory reporterManagerFactory )
98 throws ReporterException, TestSetFailedException
99 {
100
101 if ( !testsToRun.allowEagerReading() )
102 {
103 executeLazy( testsToRun, reporterManagerFactory );
104 }
105 else if ( testsToRun.containsAtLeast( 2 ) )
106 {
107 executeMulti( testsToRun, reporterManagerFactory );
108 }
109 else if ( testsToRun.containsAtLeast( 1 ) )
110 {
111 Class testClass = testsToRun.iterator().next();
112 executeSingleClass( reporterManagerFactory, testClass );
113 }
114 }
115
116 private void executeSingleClass( ReporterFactory reporterManagerFactory, Class testClass )
117 throws TestSetFailedException
118 {
119 this.options.put( "suitename", testClass.getName() );
120
121 RunListener reporter = reporterManagerFactory.createReporter();
122 ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporter );
123
124 startTestSuite( reporter, this );
125
126 final Map optionsToUse = isJUnitTest( testClass ) ? junitOptions : options;
127
128 TestNGExecutor.run( new Class[]{ testClass }, testSourceDirectory, optionsToUse, reporter, this,
129 reportsDirectory, testMethodPattern );
130
131 finishTestSuite( reporter, this );
132 }
133
134 public void executeLazy( TestsToRun testsToRun, ReporterFactory reporterFactory )
135 throws ReporterException, TestSetFailedException
136 {
137
138 for ( Class c : testsToRun )
139 {
140 executeSingleClass( reporterFactory, c );
141 }
142 }
143
144 private Class findJUnitTestClass()
145 {
146 return lookupClass( "junit.framework.Test" );
147 }
148
149 private Class findJUnitRunWithAnnotation()
150 {
151 return lookupClass( "org.junit.runner.RunWith" );
152 }
153
154 private Class findJUnitTestAnnotation()
155 {
156 return lookupClass( "org.junit.Test" );
157 }
158
159 private Class lookupClass( String className )
160 {
161 Class junitClass;
162 try
163 {
164 junitClass = Class.forName( className );
165 }
166 catch ( ClassNotFoundException e )
167 {
168 junitClass = null;
169 }
170 return junitClass;
171 }
172
173 public void executeMulti( TestsToRun testsToRun, ReporterFactory reporterFactory )
174 throws ReporterException, TestSetFailedException
175 {
176 List<Class> testNgTestClasses = new ArrayList<Class>();
177 List<Class> junitTestClasses = new ArrayList<Class>();
178 for ( Class c : testsToRun )
179 {
180 if ( isJUnitTest( c ) )
181 {
182 junitTestClasses.add( c );
183 }
184 else
185 {
186 testNgTestClasses.add( c );
187 }
188 }
189
190 File testNgReportsDirectory = reportsDirectory, junitReportsDirectory = reportsDirectory;
191
192 if ( junitTestClasses.size() > 0 && testNgTestClasses.size() > 0 )
193 {
194 testNgReportsDirectory = new File( reportsDirectory, "testng-native-results" );
195 junitReportsDirectory = new File( reportsDirectory, "testng-junit-results" );
196 }
197
198 RunListener reporterManager = reporterFactory.createReporter();
199 ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporterManager );
200 startTestSuite( reporterManager, this );
201
202 Class[] testClasses = testNgTestClasses.toArray( new Class[testNgTestClasses.size()] );
203
204 TestNGExecutor.run( testClasses, this.testSourceDirectory, options, reporterManager, this,
205 testNgReportsDirectory, testMethodPattern );
206
207 if ( junitTestClasses.size() > 0 )
208 {
209 testClasses = junitTestClasses.toArray( new Class[junitTestClasses.size()] );
210
211 TestNGExecutor.run( testClasses, testSourceDirectory, junitOptions, reporterManager, this,
212 junitReportsDirectory, testMethodPattern );
213 }
214
215 finishTestSuite( reporterManager, this );
216 }
217
218 private boolean isJUnitTest( Class c )
219 {
220 return isJunit3Test( c ) || isJunit4Test( c );
221 }
222
223 private boolean isJunit4Test( Class c )
224 {
225 return hasJunit4RunWithAnnotation( c ) || hasJunit4TestAnnotation( c );
226 }
227
228 private boolean hasJunit4RunWithAnnotation( Class c )
229 {
230 return junitRunWithAnnotation != null && c.getAnnotation( junitRunWithAnnotation ) != null;
231 }
232
233 private boolean hasJunit4TestAnnotation( Class c )
234 {
235 if ( junitTestAnnotation != null )
236 {
237 for ( Method m : c.getMethods() )
238 {
239 if ( m.getAnnotation( junitTestAnnotation ) != null )
240 {
241 return true;
242 }
243 }
244 }
245
246 return false;
247 }
248
249 private boolean isJunit3Test( Class c )
250 {
251 return junitTestClass != null && junitTestClass.isAssignableFrom( c );
252 }
253
254 private Map createJUnitOptions()
255 {
256 Map junitOptions = new HashMap( this.options );
257 junitOptions.put( "junit", Boolean.TRUE );
258 return junitOptions;
259 }
260
261
262 public void execute( String testSetName, ReporterFactory reporterManagerFactory )
263 throws ReporterException, TestSetFailedException
264 {
265 if ( testSets == null )
266 {
267 throw new IllegalStateException( "You must call locateTestSets before calling execute" );
268 }
269 TestNGTestSet testSet = testSets.get( testSetName );
270
271 if ( testSet == null )
272 {
273 throw new TestSetFailedException( "Unable to find test set '" + testSetName + "' in suite" );
274 }
275
276 RunListener reporter = reporterManagerFactory.createReporter();
277 ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporter );
278
279 startTestSuite( reporter, this );
280
281 TestNGExecutor.run( new Class[]{ testSet.getTestClass() }, this.testSourceDirectory, this.options, reporter, this, reportsDirectory, testMethodPattern );
282
283 finishTestSuite( reporter, this );
284 }
285
286 public static void startTestSuite( RunListener reporter, Object suite )
287 {
288 ReportEntry report = new SimpleReportEntry( suite.getClass().getName(), getSuiteName( suite ) );
289
290 try
291 {
292 reporter.testSetStarting( report );
293 }
294 catch ( ReporterException e )
295 {
296
297 }
298 }
299
300 public static void finishTestSuite( RunListener reporterManager, Object suite )
301 throws ReporterException
302 {
303 ReportEntry report = new SimpleReportEntry( suite.getClass().getName(), getSuiteName( suite ) );
304
305 reporterManager.testSetCompleted( report );
306 }
307
308 public String getSuiteName()
309 {
310 String result = (String) options.get( "suitename" );
311 if ( result == null )
312 {
313 result = "TestSuite";
314 }
315 return result;
316 }
317
318 private static String getSuiteName( Object suite )
319 {
320 String result;
321 if ( suite instanceof TestNGDirectoryTestSuite )
322 {
323 return ( (TestNGDirectoryTestSuite) suite ).getSuiteName();
324 }
325 else if ( suite instanceof TestNGXmlTestSuite )
326 {
327 return ( (TestNGXmlTestSuite) suite ).getSuiteName();
328 }
329 else
330 {
331 result = "TestSuite";
332 }
333
334 return result;
335 }
336
337 public Map locateTestSets( ClassLoader classLoader )
338 throws TestSetFailedException
339 {
340 if ( testSets != null )
341 {
342 throw new IllegalStateException( "You can't call locateTestSets twice" );
343 }
344 testSets = new TreeMap<String, TestNGTestSet>();
345
346 final TestsToRun scanned = scanResult.applyFilter( new NonAbstractClassFilter(), classLoader );
347
348 final TestsToRun testsToRun = runOrderCalculator.orderTestClasses( scanned );
349
350 for ( Class testClass : testsToRun )
351 {
352 TestNGTestSet testSet = new TestNGTestSet( testClass );
353
354 if ( testSets.containsKey( testSet.getName() ) )
355 {
356 throw new TestSetFailedException( "Duplicate test set '" + testSet.getName() + "'" );
357 }
358 testSets.put( testSet.getName(), testSet );
359
360 }
361
362 return Collections.unmodifiableSortedMap( testSets );
363 }
364
365 }