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.reflect.Constructor;
23 import java.lang.reflect.InvocationTargetException;
24 import java.util.Collection;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.maven.surefire.api.booter.Command;
29 import org.apache.maven.surefire.api.cli.CommandLineOption;
30 import org.apache.maven.surefire.api.provider.AbstractProvider;
31 import org.apache.maven.surefire.api.provider.CommandChainReader;
32 import org.apache.maven.surefire.api.provider.CommandListener;
33 import org.apache.maven.surefire.api.provider.ProviderParameters;
34 import org.apache.maven.surefire.api.report.ReporterConfiguration;
35 import org.apache.maven.surefire.api.report.ReporterFactory;
36 import org.apache.maven.surefire.api.report.TestOutputReportEntry;
37 import org.apache.maven.surefire.api.report.TestReportListener;
38 import org.apache.maven.surefire.api.suite.RunResult;
39 import org.apache.maven.surefire.api.testset.TestListResolver;
40 import org.apache.maven.surefire.api.testset.TestRequest;
41 import org.apache.maven.surefire.api.testset.TestSetFailedException;
42 import org.apache.maven.surefire.api.util.RunOrderCalculator;
43 import org.apache.maven.surefire.api.util.ScanResult;
44 import org.apache.maven.surefire.api.util.TestsToRun;
45 import org.apache.maven.surefire.testng.utils.FailFastEventsSingleton;
46
47 import static org.apache.maven.surefire.api.report.ConsoleOutputCapture.startCapture;
48 import static org.apache.maven.surefire.api.report.RunMode.NORMAL_RUN;
49 import static org.apache.maven.surefire.api.testset.TestListResolver.getEmptyTestListResolver;
50 import static org.apache.maven.surefire.api.testset.TestListResolver.optionallyWildcardFilter;
51 import static org.apache.maven.surefire.api.util.TestsToRun.fromClass;
52
53
54
55
56 public class TestNGProvider extends AbstractProvider {
57 private final Map<String, String> providerProperties;
58
59 private final ReporterConfiguration reporterConfiguration;
60
61 private final ClassLoader testClassLoader;
62
63 private final ScanResult scanResult;
64
65 private final TestRequest testRequest;
66
67 private final ProviderParameters providerParameters;
68
69 private final RunOrderCalculator runOrderCalculator;
70
71 private final List<CommandLineOption> mainCliOptions;
72
73 private final CommandChainReader commandsReader;
74
75 public TestNGProvider(ProviderParameters bootParams) {
76
77 commandsReader = bootParams.isInsideFork() ? bootParams.getCommandReader() : null;
78 providerParameters = bootParams;
79 testClassLoader = bootParams.getTestClassLoader();
80 runOrderCalculator = bootParams.getRunOrderCalculator();
81 providerProperties = bootParams.getProviderProperties();
82 testRequest = bootParams.getTestRequest();
83 reporterConfiguration = bootParams.getReporterConfiguration();
84 scanResult = bootParams.getScanResult();
85 mainCliOptions = bootParams.getMainCliOptions();
86 }
87
88 @Override
89 public RunResult invoke(Object forkTestSet) throws TestSetFailedException {
90 if (isFailFast() && commandsReader != null) {
91 registerPleaseStopListener();
92 }
93
94 ReporterFactory reporterFactory = providerParameters.getReporterFactory();
95 TestReportListener<TestOutputReportEntry> reporter = reporterFactory.createTestReportListener();
96
97 RunResult runResult;
98 try {
99 if (isTestNGXmlTestSuite(testRequest)) {
100 TestNGReporter testNGReporter = createTestNGReporter(reporter);
101 testNGReporter.setRunMode(NORMAL_RUN);
102
103
104
105
106 startCapture(testNGReporter);
107
108 if (commandsReader != null) {
109 commandsReader.awaitStarted();
110 }
111 TestNGXmlTestSuite testNGXmlTestSuite = newXmlSuite();
112 testNGXmlTestSuite.locateTestSets();
113 testNGXmlTestSuite.execute(testNGReporter);
114 } else {
115 TestNGReporter testNGReporter = createTestNGReporter(reporter);
116 testNGReporter.setRunMode(NORMAL_RUN);
117
118
119
120
121 startCapture(testNGReporter);
122
123 final TestsToRun testsToRun;
124 if (forkTestSet instanceof TestsToRun) {
125 testsToRun = (TestsToRun) forkTestSet;
126 } else if (forkTestSet instanceof Class) {
127 testsToRun = fromClass((Class<?>) forkTestSet);
128 } else {
129 testsToRun = scanClassPath();
130 }
131
132 if (commandsReader != null) {
133 registerShutdownListener(testsToRun);
134 commandsReader.awaitStarted();
135 }
136 TestNGDirectoryTestSuite suite = newDirectorySuite();
137 suite.execute(testsToRun, testNGReporter);
138 }
139 } finally {
140 runResult = reporterFactory.close();
141 }
142 return runResult;
143 }
144
145 boolean isTestNGXmlTestSuite(TestRequest testSuiteDefinition) {
146 Collection<File> suiteXmlFiles = testSuiteDefinition.getSuiteXmlFiles();
147 return !suiteXmlFiles.isEmpty() && !hasSpecificTests();
148 }
149
150 private boolean isFailFast() {
151 return providerParameters.getSkipAfterFailureCount() > 0;
152 }
153
154 private int getSkipAfterFailureCount() {
155 return isFailFast() ? providerParameters.getSkipAfterFailureCount() : 0;
156 }
157
158 private void registerShutdownListener(final TestsToRun testsToRun) {
159 commandsReader.addShutdownListener(new CommandListener() {
160 @Override
161 public void update(Command command) {
162 testsToRun.markTestSetFinished();
163 }
164 });
165 }
166
167 private void registerPleaseStopListener() {
168 commandsReader.addSkipNextTestsListener(new CommandListener() {
169 @Override
170 public void update(Command command) {
171 FailFastEventsSingleton.getInstance().setSkipOnNextTest();
172 }
173 });
174 }
175
176 private TestNGDirectoryTestSuite newDirectorySuite() {
177 return new TestNGDirectoryTestSuite(
178 testRequest.getTestSourceDirectory().toString(),
179 providerProperties,
180 reporterConfiguration.getReportsDirectory(),
181 getTestFilter(),
182 mainCliOptions,
183 getSkipAfterFailureCount());
184 }
185
186 private TestNGXmlTestSuite newXmlSuite() {
187 return new TestNGXmlTestSuite(
188 testRequest.getSuiteXmlFiles(),
189 testRequest.getTestSourceDirectory().toString(),
190 providerProperties,
191 reporterConfiguration.getReportsDirectory(),
192 getSkipAfterFailureCount());
193 }
194
195 @Override
196 @SuppressWarnings("unchecked")
197 public Iterable<Class<?>> getSuites() {
198 if (isTestNGXmlTestSuite(testRequest)) {
199 try {
200 return newXmlSuite().locateTestSets();
201 } catch (TestSetFailedException e) {
202 throw new RuntimeException(e);
203 }
204 } else {
205 return scanClassPath();
206 }
207 }
208
209 private TestsToRun scanClassPath() {
210 final TestsToRun scanned = scanResult.applyFilter(null, testClassLoader);
211 return runOrderCalculator.orderTestClasses(scanned);
212 }
213
214 private boolean hasSpecificTests() {
215 TestListResolver specificTestPatterns = testRequest.getTestListResolver();
216 return !specificTestPatterns.isEmpty() && !specificTestPatterns.isWildcard();
217 }
218
219 private TestListResolver getTestFilter() {
220 TestListResolver filter = optionallyWildcardFilter(testRequest.getTestListResolver());
221 return filter.isWildcard() ? getEmptyTestListResolver() : filter;
222 }
223
224
225
226 private static TestNGReporter createTestNGReporter(TestReportListener<TestOutputReportEntry> reportManager) {
227 try {
228 Class.forName("org.testng.internal.IResultListener");
229 Class<?> c = Class.forName("org.apache.maven.surefire.testng.ConfigurationAwareTestNGReporter");
230 Constructor<?> ctor = c.getConstructor(TestReportListener.class);
231 return (TestNGReporter) ctor.newInstance(reportManager);
232 } catch (InvocationTargetException e) {
233 throw new RuntimeException("Bug in ConfigurationAwareTestNGReporter", e.getCause());
234 } catch (ClassNotFoundException e) {
235 return new TestNGReporter(reportManager);
236 } catch (Exception e) {
237 throw new RuntimeException("Bug in ConfigurationAwareTestNGReporter", e);
238 }
239 }
240 }