1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.surefire.junit;
20
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23 import java.lang.reflect.Modifier;
24 import java.util.ArrayList;
25 import java.util.Collection;
26
27 import org.apache.maven.surefire.api.report.LegacyPojoStackTraceWriter;
28 import org.apache.maven.surefire.api.report.SimpleReportEntry;
29 import org.apache.maven.surefire.api.report.StackTraceWriter;
30 import org.apache.maven.surefire.api.testset.TestSetFailedException;
31 import org.apache.maven.surefire.report.ClassMethodIndexer;
32
33 import static java.util.Objects.requireNonNull;
34 import static org.apache.maven.surefire.api.report.RunMode.NORMAL_RUN;
35 import static org.apache.maven.surefire.api.report.SimpleReportEntry.withException;
36
37
38
39
40
41 public class PojoTestSetExecutor implements SurefireTestSetExecutor {
42 private static final String TEST_METHOD_PREFIX = "test";
43
44 private static final String SETUP_METHOD_NAME = "setUp";
45
46 private static final String TEARDOWN_METHOD_NAME = "tearDown";
47
48 private static final Object[] EMPTY_OBJECT_ARRAY = {};
49
50 private final JUnit3Reporter reporter;
51
52 public PojoTestSetExecutor(JUnit3Reporter reporter) {
53 this.reporter = requireNonNull(reporter, "reportManager is null");
54 }
55
56 @Override
57 public void execute(Class<?> testClass, ClassLoader loader) throws TestSetFailedException {
58 DiscoveredTestMethods discoveredTestMethods = discoverTestMethods(requireNonNull(testClass));
59
60 for (Method testMethod : discoveredTestMethods.testMethods) {
61 ClassMethodIndexer indexer = reporter.getClassMethodIndexer();
62 long testRunId = indexer.indexClassMethod(testClass.getName(), testMethod.getName());
63 boolean abort = executeTestMethod(testClass, testMethod, testRunId, discoveredTestMethods);
64 if (abort) {
65 break;
66 }
67 }
68 }
69
70 private boolean executeTestMethod(Class<?> testClass, Method method, long testRunId, DiscoveredTestMethods methods)
71 throws TestSetFailedException {
72 final Object testObject;
73
74 try {
75 testObject = testClass.getDeclaredConstructor().newInstance();
76 } catch (ReflectiveOperationException e) {
77 throw new TestSetFailedException("Unable to instantiate POJO '" + testClass + "'.", e);
78 }
79
80 final String testClassName = testClass.getName();
81 final String methodName = method.getName();
82 final String userFriendlyMethodName = methodName + "()";
83 final String testName = getTestName(testClassName, userFriendlyMethodName);
84
85 reporter.testStarting(new SimpleReportEntry(NORMAL_RUN, testRunId, testClassName, null, testName, null));
86
87 try {
88 setUpFixture(testObject, methods);
89 } catch (Throwable e) {
90 StackTraceWriter stackTraceWriter = new LegacyPojoStackTraceWriter(testClassName, methodName, e);
91 reporter.testFailed(
92 withException(NORMAL_RUN, testRunId, testClassName, null, testName, null, stackTraceWriter));
93
94
95
96
97
98
99 return true;
100 }
101
102
103 try {
104 method.invoke(testObject, EMPTY_OBJECT_ARRAY);
105 reporter.testSucceeded(new SimpleReportEntry(NORMAL_RUN, testRunId, testClassName, null, testName, null));
106 } catch (InvocationTargetException e) {
107 Throwable t = e.getTargetException();
108 StackTraceWriter stackTraceWriter = new LegacyPojoStackTraceWriter(testClassName, methodName, t);
109 reporter.testFailed(
110 withException(NORMAL_RUN, testRunId, testClassName, null, testName, null, stackTraceWriter));
111
112
113 } catch (Throwable t) {
114 StackTraceWriter stackTraceWriter = new LegacyPojoStackTraceWriter(testClassName, methodName, t);
115 reporter.testFailed(
116 withException(NORMAL_RUN, testRunId, testClassName, null, testName, null, stackTraceWriter));
117
118
119 }
120
121 try {
122 tearDownFixture(testObject, methods);
123 } catch (Throwable t) {
124 StackTraceWriter stackTraceWriter = new LegacyPojoStackTraceWriter(testClassName, methodName, t);
125
126 reporter.testFailed(
127 withException(NORMAL_RUN, testRunId, testClassName, null, testName, null, stackTraceWriter));
128
129
130
131
132
133
134 return true;
135 }
136
137
138
139
140
141
142 return false;
143 }
144
145 private String getTestName(String testClassName, String testMethodName) {
146 return testClassName + "." + requireNonNull(testMethodName, "testMethodName is null");
147 }
148
149 private void setUpFixture(Object testObject, DiscoveredTestMethods methods) throws Throwable {
150 if (methods.setUpMethod != null) {
151 methods.setUpMethod.invoke(testObject);
152 }
153 }
154
155 private void tearDownFixture(Object testObject, DiscoveredTestMethods methods) throws Throwable {
156 if (methods.tearDownMethod != null) {
157 methods.tearDownMethod.invoke(testObject);
158 }
159 }
160
161 private DiscoveredTestMethods discoverTestMethods(Class<?> testClass) {
162 DiscoveredTestMethods methods = new DiscoveredTestMethods();
163 for (Method m : testClass.getMethods()) {
164 if (isNoArgsInstanceMethod(m)) {
165 if (isValidTestMethod(m)) {
166 methods.testMethods.add(m);
167 } else if (SETUP_METHOD_NAME.equals(m.getName())) {
168 methods.setUpMethod = m;
169 } else if (TEARDOWN_METHOD_NAME.equals(m.getName())) {
170 methods.tearDownMethod = m;
171 }
172 }
173 }
174 return methods;
175 }
176
177 private static boolean isNoArgsInstanceMethod(Method m) {
178 boolean isInstanceMethod = !Modifier.isStatic(m.getModifiers());
179 boolean returnsVoid = m.getReturnType().equals(void.class);
180 boolean hasNoParams = m.getParameterTypes().length == 0;
181 return isInstanceMethod && returnsVoid && hasNoParams;
182 }
183
184 private static boolean isValidTestMethod(Method m) {
185 return m.getName().startsWith(TEST_METHOD_PREFIX);
186 }
187
188 private static class DiscoveredTestMethods {
189 final Collection<Method> testMethods = new ArrayList<>();
190 Method setUpMethod;
191 Method tearDownMethod;
192 }
193 }