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