1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.junit;
16
17 import java.lang.annotation.ElementType;
18 import java.lang.annotation.Retention;
19 import java.lang.annotation.RetentionPolicy;
20 import java.lang.annotation.Target;
21 import java.text.MessageFormat;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Set;
27
28 import org.htmlunit.BrowserVersion;
29 import org.htmlunit.WebDriverTestCase;
30 import org.htmlunit.WebTestCase;
31 import org.junit.runner.Runner;
32 import org.junit.runner.manipulation.Filter;
33 import org.junit.runner.manipulation.Filterable;
34 import org.junit.runner.manipulation.NoTestsRemainException;
35 import org.junit.runners.Parameterized.Parameters;
36 import org.junit.runners.Suite;
37 import org.junit.runners.model.FrameworkMethod;
38 import org.junit.runners.model.TestClass;
39 import org.junit.runners.parameterized.TestWithParameters;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 public class BrowserParameterizedRunner extends Suite {
103
104
105
106
107 @Retention(RetentionPolicy.RUNTIME)
108 @Target(ElementType.METHOD)
109 public @interface Default {
110 }
111
112 private final ArrayList<Runner> runners_ = new ArrayList<>();
113
114
115
116
117
118
119 public BrowserParameterizedRunner(final Class<WebTestCase> klass) throws Throwable {
120 super(klass, Collections.<Runner>emptyList());
121
122 verifyDefaultMEthod();
123
124 final Parameters parameters = getParametersMethod().getAnnotation(Parameters.class);
125
126 final List<TestWithParameters> tests = createTestsForParameters(
127 allParameters(), parameters.name());
128
129 if (BrowserVersionClassRunner.containsTestMethods(klass)) {
130 final Set<String> browsers = WebDriverTestCase.getBrowsersProperties();
131 if (WebDriverTestCase.class.isAssignableFrom(klass)) {
132 if (browsers.contains(BrowserRunner.REAL_CHROME)) {
133 runners_.add(new BrowserVersionClassRunnerWithParameters(
134 klass, BrowserVersion.CHROME, true, tests));
135 }
136 if (browsers.contains(BrowserRunner.REAL_FIREFOX_ESR)) {
137 runners_.add(new BrowserVersionClassRunnerWithParameters(
138 klass, BrowserVersion.FIREFOX_ESR, true, tests));
139 }
140 if (browsers.contains(BrowserRunner.REAL_FIREFOX)) {
141 runners_.add(new BrowserVersionClassRunnerWithParameters(
142 klass, BrowserVersion.FIREFOX, true, tests));
143 }
144 if (browsers.contains(BrowserRunner.REAL_EDGE)) {
145 runners_.add(new BrowserVersionClassRunnerWithParameters(
146 klass, BrowserVersion.EDGE, true, tests));
147 }
148 }
149
150 if (browsers.contains(BrowserRunner.HTMLUNIT_CHROME)) {
151 runners_.add(new BrowserVersionClassRunnerWithParameters(
152 klass, BrowserVersion.CHROME, false, tests));
153 }
154 if (browsers.contains(BrowserRunner.HTMLUNIT_FIREFOX_ESR)) {
155 runners_.add(new BrowserVersionClassRunnerWithParameters(
156 klass, BrowserVersion.FIREFOX_ESR, false, tests));
157 }
158 if (browsers.contains(BrowserRunner.HTMLUNIT_FIREFOX)) {
159 runners_.add(new BrowserVersionClassRunnerWithParameters(
160 klass, BrowserVersion.FIREFOX, false, tests));
161 }
162 if (browsers.contains(BrowserRunner.HTMLUNIT_EDGE)) {
163 runners_.add(new BrowserVersionClassRunnerWithParameters(
164 klass, BrowserVersion.EDGE, false, tests));
165 }
166 }
167 else {
168 throw new IllegalStateException("No @Test method found");
169 }
170 }
171
172
173
174
175 @Override
176 protected List<Runner> getChildren() {
177 return runners_;
178 }
179
180 private TestWithParameters createTestWithNotNormalizedParameters(
181 final String pattern, final int index, final Object parametersOrSingleParameter) {
182 final Object[] parameters = (parametersOrSingleParameter instanceof Object[])
183 ? (Object[]) parametersOrSingleParameter
184 : new Object[] {parametersOrSingleParameter};
185 return createTestWithParameters(getTestClass(), pattern, index,
186 parameters);
187 }
188
189 @SuppressWarnings("unchecked")
190 private Iterable<Object> allParameters() throws Throwable {
191 final Object parameters = getParametersMethod().invokeExplosively(null);
192 if (parameters instanceof Iterable) {
193 return (Iterable<Object>) parameters;
194 }
195 else if (parameters instanceof Object[]) {
196 return Arrays.asList((Object[]) parameters);
197 }
198 else {
199 throw parametersMethodReturnedWrongType();
200 }
201 }
202
203 private FrameworkMethod getParametersMethod() throws Exception {
204 final List<FrameworkMethod> methods = getTestClass().getAnnotatedMethods(
205 Parameters.class);
206 for (final FrameworkMethod each : methods) {
207 if (each.isStatic() && each.isPublic()) {
208 return each;
209 }
210 }
211
212 throw new Exception("No public static parameters method on class "
213 + getTestClass().getName());
214 }
215
216 private List<TestWithParameters> createTestsForParameters(
217 final Iterable<Object> allParameters, final String namePattern) {
218 int i = 0;
219 final List<TestWithParameters> children = new ArrayList<>();
220 for (final Object parametersOfSingleTest : allParameters) {
221 children.add(createTestWithNotNormalizedParameters(namePattern,
222 i++, parametersOfSingleTest));
223 }
224 return children;
225 }
226
227 private Exception parametersMethodReturnedWrongType() throws Exception {
228 final String className = getTestClass().getName();
229 final String methodName = getParametersMethod().getName();
230 final String message = MessageFormat.format(
231 "{0}.{1}() must return an Iterable of arrays.",
232 className, methodName);
233 return new Exception(message);
234 }
235
236 private static TestWithParameters createTestWithParameters(
237 final TestClass testClass, final String pattern, final int index, final Object[] parameters) {
238 final String finalPattern = pattern.replaceAll("\\{index\\}",
239 Integer.toString(index));
240 final String name = MessageFormat.format(finalPattern, parameters);
241 return new TestWithParameters("[" + name + "]", testClass,
242 Arrays.asList(parameters));
243 }
244
245 private void verifyDefaultMEthod() throws Exception {
246 final List<FrameworkMethod> methods = getTestClass().getAnnotatedMethods(Default.class);
247 if (methods.size() != 1) {
248 throw new Exception("A single method with @Default must exist in class "
249 + getTestClass().getName());
250 }
251 }
252
253
254
255
256 @Override
257 public void filter(final Filter filter) throws NoTestsRemainException {
258 boolean atLeastOne = false;
259 for (final Runner runner : getChildren()) {
260 try {
261 if (runner instanceof Filterable) {
262 ((Filterable) runner).filter(filter);
263 atLeastOne = true;
264 }
265 }
266 catch (final NoTestsRemainException e) {
267
268 }
269 }
270
271 if (!atLeastOne) {
272 throw new NoTestsRemainException();
273 }
274 }
275 }