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