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.Annotation;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.Comparator;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Set;
25
26 import org.htmlunit.BrowserVersion;
27 import org.htmlunit.WebTestCase;
28 import org.htmlunit.junit.BrowserParameterizedRunner.Default;
29 import org.junit.runner.Description;
30 import org.junit.runner.notification.RunNotifier;
31 import org.junit.runners.Parameterized.Parameter;
32 import org.junit.runners.model.FrameworkField;
33 import org.junit.runners.model.FrameworkMethod;
34 import org.junit.runners.model.InitializationError;
35 import org.junit.runners.model.Statement;
36 import org.junit.runners.parameterized.TestWithParameters;
37
38
39
40
41
42
43 public class BrowserVersionClassRunnerWithParameters extends BrowserVersionClassRunner {
44
45 private final List<TestWithParameters> tests_;
46
47 private List<FrameworkMethod> testMethods_;
48
49
50
51
52
53
54
55
56
57 public BrowserVersionClassRunnerWithParameters(final Class<WebTestCase> klass,
58 final BrowserVersion browserVersion, final boolean realBrowser,
59 final List<TestWithParameters> tests)
60 throws InitializationError {
61 super(klass, browserVersion, realBrowser);
62 tests_ = tests;
63 }
64
65
66
67
68 @Override
69 protected List<FrameworkMethod> computeTestMethods() {
70 if (testMethods_ != null) {
71 return testMethods_;
72 }
73 final List<FrameworkMethod> originalMethod = super.computeTestMethods();
74 if (tests_ == null) {
75 return originalMethod;
76 }
77 final Set<String> nativeMethodNames = new HashSet<>();
78 final List<FrameworkMethod> methods = new ArrayList<>();
79 FrameworkMethod defualtMethod = null;
80 for (final FrameworkMethod m : originalMethod) {
81 final List<Object> parameters;
82 if (m.getAnnotation(Default.class) != null) {
83 defualtMethod = m;
84 parameters = tests_.get(0).getParameters();
85 }
86 else {
87 parameters = Collections.emptyList();
88 nativeMethodNames.add(m.getName());
89 }
90 final FrameworkMethodWithParameters newMethod = new FrameworkMethodWithParameters(
91 getTestClass(), m.getMethod(), parameters);
92 methods.add(newMethod);
93 }
94
95 if (defualtMethod != null) {
96 for (int i = 0; i < tests_.size() - 1; i++) {
97 final FrameworkMethodWithParameters method = new FrameworkMethodWithParameters(
98 getTestClass(), defualtMethod.getMethod(), tests_.get(i + 1).getParameters());
99 methods.add(method);
100 }
101 }
102
103 for (final Iterator<FrameworkMethod> it = methods.iterator(); it.hasNext();) {
104 final FrameworkMethod method = it.next();
105 if (method.getAnnotation(Default.class) != null && nativeMethodNames.contains(method.getName())) {
106 it.remove();
107 }
108 }
109
110 final Comparator<FrameworkMethod> comparator = new Comparator<FrameworkMethod>() {
111 @Override
112 public int compare(final FrameworkMethod fm1, final FrameworkMethod fm2) {
113 return fm1.getName().compareTo(fm2.getName());
114 }
115 };
116 Collections.sort(methods, comparator);
117 testMethods_ = methods;
118 return testMethods_;
119 }
120
121
122
123
124 @Override
125 protected String testName(final FrameworkMethod method) {
126 String prefix = "";
127 if (isNotYetImplemented(method) && !isRealBrowser()) {
128 prefix = "(NYI) ";
129 }
130
131 String browserString = getBrowserVersion().getNickname();
132 if (isRealBrowser()) {
133 browserString = "Real " + browserString;
134 }
135
136 final String methodName = method.getName();
137
138 if (!MAVEN) {
139 return String.format("%s [%s]", methodName, browserString);
140 }
141 String className = method.getMethod().getDeclaringClass().getName();
142 className = className.substring(className.lastIndexOf('.') + 1);
143 return String.format("%s%s [%s]", prefix, className + '.' + methodName, browserString);
144 }
145
146
147
148
149 @Override
150 protected void validateConstructor(final List<Throwable> errors) {
151 validateOnlyOneConstructor(errors);
152 if (fieldsAreAnnotated()) {
153 validateZeroArgConstructor(errors);
154 }
155 }
156
157
158
159
160 @Override
161 protected void validateFields(final List<Throwable> errors) {
162 super.validateFields(errors);
163 if (fieldsAreAnnotated()) {
164 final List<FrameworkField> annotatedFieldsByParameter = getAnnotatedFieldsByParameter();
165 final int[] usedIndices = new int[annotatedFieldsByParameter.size()];
166 for (final FrameworkField each : annotatedFieldsByParameter) {
167 final int index = each.getField().getAnnotation(Parameter.class)
168 .value();
169 if (index < 0 || index > annotatedFieldsByParameter.size() - 1) {
170 errors.add(new Exception("Invalid @Parameter value: "
171 + index + ". @Parameter fields counted: "
172 + annotatedFieldsByParameter.size()
173 + ". Please use an index between 0 and "
174 + (annotatedFieldsByParameter.size() - 1) + "."));
175 }
176 else {
177 usedIndices[index]++;
178 }
179 }
180 for (int index = 0; index < usedIndices.length; index++) {
181 final int numberOfUse = usedIndices[index];
182 if (numberOfUse == 0) {
183 errors.add(new Exception("@Parameter(" + index
184 + ") is never used."));
185 }
186 else if (numberOfUse > 1) {
187 errors.add(new Exception("@Parameter(" + index
188 + ") is used more than once (" + numberOfUse + ")."));
189 }
190 }
191 }
192 }
193
194
195
196
197 @Override
198 protected Statement classBlock(final RunNotifier notifier) {
199 return childrenInvoker(notifier);
200 }
201
202
203
204
205 @Override
206 protected Annotation[] getRunnerAnnotations() {
207 return new Annotation[0];
208 }
209
210 private List<FrameworkField> getAnnotatedFieldsByParameter() {
211 return getTestClass().getAnnotatedFields(Parameter.class);
212 }
213
214 private boolean fieldsAreAnnotated() {
215 return !getAnnotatedFieldsByParameter().isEmpty();
216 }
217
218
219
220
221 @Override
222 protected Description describeChild(final FrameworkMethod method) {
223 if (method.getAnnotation(Default.class) != null) {
224 return Description.createTestDescription(getTestClass().getJavaClass(),
225 testName(method), method.getAnnotations());
226 }
227 return super.describeChild(method);
228 }
229 }