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
31 import org.apache.maven.surefire.cli.CommandLineOption;
32 import org.apache.maven.surefire.report.RunListener;
33 import org.apache.maven.surefire.testset.TestListResolver;
34 import org.apache.maven.surefire.testset.TestSetFailedException;
35 import org.apache.maven.surefire.util.TestsToRun;
36
37 import static org.apache.maven.surefire.testng.TestNGExecutor.run;
38 import static org.apache.maven.surefire.util.internal.StringUtils.isBlank;
39
40
41
42
43
44
45
46 final class TestNGDirectoryTestSuite
47 extends TestSuite
48 {
49 private final Map<String, String> options;
50
51 private final Map<String, String> junitOptions;
52
53 private final String testSourceDirectory;
54
55 private final File reportsDirectory;
56
57 private final TestListResolver methodFilter;
58
59 private final Class<?> junitTestClass;
60
61 private final Class<? extends Annotation> junitRunWithAnnotation;
62
63 private final Class<? extends Annotation> junitTestAnnotation;
64
65 private final List<CommandLineOption> mainCliOptions;
66
67 private final int skipAfterFailureCount;
68
69 TestNGDirectoryTestSuite( String testSourceDirectory, Map<String, String> confOptions, File reportsDirectory,
70 TestListResolver methodFilter, List<CommandLineOption> mainCliOptions,
71 int skipAfterFailureCount )
72 {
73 this.options = confOptions;
74 this.testSourceDirectory = testSourceDirectory;
75 this.reportsDirectory = reportsDirectory;
76 this.methodFilter = methodFilter;
77 this.junitTestClass = findJUnitTestClass();
78 this.junitRunWithAnnotation = findJUnitRunWithAnnotation();
79 this.junitTestAnnotation = findJUnitTestAnnotation();
80 this.junitOptions = createJUnitOptions();
81 this.mainCliOptions = mainCliOptions;
82 this.skipAfterFailureCount = skipAfterFailureCount;
83 }
84
85 void execute( TestsToRun testsToRun, RunListener reporterManager )
86 throws TestSetFailedException
87 {
88 if ( !testsToRun.allowEagerReading() )
89 {
90 executeLazy( testsToRun, reporterManager );
91 }
92 else if ( testsToRun.containsAtLeast( 2 ) )
93 {
94 executeMulti( testsToRun, reporterManager );
95 }
96 else if ( testsToRun.containsAtLeast( 1 ) )
97 {
98 Class<?> testClass = testsToRun.iterator().next();
99 executeSingleClass( reporterManager, testClass );
100 }
101 }
102
103 private void executeSingleClass( RunListener reporter, Class<?> testClass )
104 throws TestSetFailedException
105 {
106 options.put( "suitename", testClass.getName() );
107
108 startTestSuite( reporter );
109
110 Map<String, String> optionsToUse = isJUnitTest( testClass ) ? junitOptions : options;
111
112 run( Collections.<Class<?>>singleton( testClass ), testSourceDirectory, optionsToUse, reporter,
113 reportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount );
114
115 finishTestSuite( reporter );
116 }
117
118 private void executeLazy( TestsToRun testsToRun, RunListener reporterManager )
119 throws TestSetFailedException
120 {
121 for ( Class<?> testToRun : testsToRun )
122 {
123 executeSingleClass( reporterManager, testToRun );
124 }
125 }
126
127 private static Class<?> findJUnitTestClass()
128 {
129 return lookupClass( "junit.framework.Test" );
130 }
131
132 private static Class<Annotation> findJUnitRunWithAnnotation()
133 {
134 return lookupAnnotation( "org.junit.runner.RunWith" );
135 }
136
137 private static Class<Annotation> findJUnitTestAnnotation()
138 {
139 return lookupAnnotation( "org.junit.Test" );
140 }
141
142 @SuppressWarnings( "unchecked" )
143 private static Class<Annotation> lookupAnnotation( String className )
144 {
145 try
146 {
147 return (Class<Annotation>) Class.forName( className );
148 }
149 catch ( ClassNotFoundException e )
150 {
151 return null;
152 }
153 }
154
155 private static Class<?> lookupClass( String className )
156 {
157 try
158 {
159 return Class.forName( className );
160 }
161 catch ( ClassNotFoundException e )
162 {
163 return null;
164 }
165 }
166
167 private void executeMulti( TestsToRun testsToRun, RunListener reporterManager )
168 throws TestSetFailedException
169 {
170 List<Class<?>> testNgTestClasses = new ArrayList<Class<?>>();
171 List<Class<?>> junitTestClasses = new ArrayList<Class<?>>();
172 for ( Class<?> testToRun : testsToRun )
173 {
174 if ( isJUnitTest( testToRun ) )
175 {
176 junitTestClasses.add( testToRun );
177 }
178 else
179 {
180 testNgTestClasses.add( testToRun );
181 }
182 }
183
184 File testNgReportsDirectory = reportsDirectory, junitReportsDirectory = reportsDirectory;
185
186 if ( !junitTestClasses.isEmpty() && !testNgTestClasses.isEmpty() )
187 {
188 testNgReportsDirectory = new File( reportsDirectory, "testng-native-results" );
189 junitReportsDirectory = new File( reportsDirectory, "testng-junit-results" );
190 }
191 startTestSuite( reporterManager );
192
193 run( testNgTestClasses, testSourceDirectory, options, reporterManager,
194 testNgReportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount );
195
196 if ( !junitTestClasses.isEmpty() )
197 {
198 run( junitTestClasses, testSourceDirectory, junitOptions, reporterManager,
199 junitReportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount );
200 }
201
202 finishTestSuite( reporterManager );
203 }
204
205 private boolean isJUnitTest( Class<?> c )
206 {
207 return isJunit3Test( c ) || isJunit4Test( c );
208 }
209
210 private boolean isJunit4Test( Class<?> c )
211 {
212 return hasJunit4RunWithAnnotation( c ) || hasJunit4TestAnnotation( c );
213 }
214
215 private boolean hasJunit4RunWithAnnotation( Class<?> c )
216 {
217 return junitRunWithAnnotation != null && c.getAnnotation( junitRunWithAnnotation ) != null;
218 }
219
220 private boolean hasJunit4TestAnnotation( Class<?> c )
221 {
222 if ( junitTestAnnotation != null )
223 {
224 for ( Method m : c.getMethods() )
225 {
226 if ( m.getAnnotation( junitTestAnnotation ) != null )
227 {
228 return true;
229 }
230 }
231 }
232
233 return false;
234 }
235
236 private boolean isJunit3Test( Class<?> c )
237 {
238 return junitTestClass != null && junitTestClass.isAssignableFrom( c );
239 }
240
241 private Map<String, String> createJUnitOptions()
242 {
243 Map<String, String> junitOptions = new HashMap<String, String>( options );
244 String onlyJUnit = options.get( "junit" );
245 if ( isBlank( onlyJUnit ) )
246 {
247 onlyJUnit = "true";
248 }
249 junitOptions.put( "junit", onlyJUnit );
250 return junitOptions;
251 }
252
253 @Override
254 Map<String, String> getOptions()
255 {
256 return options;
257 }
258 }