14
14
import org .junit .runners .model .FrameworkMethod ;
15
15
import org .junit .runners .model .InitializationError ;
16
16
import org .junit .runners .model .TestClass ;
17
- import org .junit .runners .parameterized .BlockJUnit4ClassRunnerWithParameters ;
17
+ import org .junit .runners .parameterized .BlockJUnit4ClassRunnerWithParametersFactory ;
18
+ import org .junit .runners .parameterized .ParametersRunnerFactory ;
18
19
import org .junit .runners .parameterized .TestWithParameters ;
19
20
20
21
/**
128
129
* }
129
130
* </pre>
130
131
*
132
+ * <h3>Create different runners</h3>
133
+ * <p>
134
+ * By default the {@code Parameterized} runner creates a slightly modified
135
+ * {@link BlockJUnit4ClassRunner} for each set of parameters. You can build an
136
+ * own {@code Parameterized} runner that creates another runner for each set of
137
+ * parameters. Therefore you have to build a {@link ParametersRunnerFactory}
138
+ * that creates a runner for each {@link TestWithParameters}. (
139
+ * {@code TestWithParameters} are bundling the parameters and the test name.)
140
+ * The factory must have a public zero-arg constructor.
141
+ *
142
+ * <pre>
143
+ * public class YourRunnerFactory implements ParameterizedRunnerFactory {
144
+ * public Runner createRunnerForTestWithParameters(TestWithParameters test)
145
+ * throws InitializationError {
146
+ * return YourRunner(test);
147
+ * }
148
+ * }
149
+ * </pre>
150
+ * <p>
151
+ * Use the {@link UseParametersRunnerFactory} to tell the {@code Parameterized}
152
+ * runner that it should use your factory.
153
+ *
154
+ * <pre>
155
+ * @RunWith(Parameterized.class)
156
+ * @UseParametersRunnerFactory(YourRunnerFactory.class)
157
+ * public class YourTest {
158
+ * ...
159
+ * }
160
+ * </pre>
161
+ *
131
162
* @since 4.0
132
163
*/
133
164
public class Parameterized extends Suite {
@@ -181,6 +212,24 @@ public class Parameterized extends Suite {
181
212
int value () default 0 ;
182
213
}
183
214
215
+ /**
216
+ * Add this annotation to your test class if you want to generate a special
217
+ * runner. You have to specify a {@link ParametersRunnerFactory} class that
218
+ * creates such runners. The factory must have a public zero-arg
219
+ * constructor.
220
+ */
221
+ @ Retention (RetentionPolicy .RUNTIME )
222
+ @ Target (ElementType .TYPE )
223
+ public @interface UseParametersRunnerFactory {
224
+ /**
225
+ * @return a {@link ParametersRunnerFactory} class (must have a default
226
+ * constructor)
227
+ */
228
+ Class <? extends ParametersRunnerFactory > value () default BlockJUnit4ClassRunnerWithParametersFactory .class ;
229
+ }
230
+
231
+ private static final ParametersRunnerFactory DEFAULT_FACTORY = new BlockJUnit4ClassRunnerWithParametersFactory ();
232
+
184
233
private static final List <Runner > NO_RUNNERS = Collections .<Runner >emptyList ();
185
234
186
235
private final List <Runner > fRunners ;
@@ -190,29 +239,38 @@ public class Parameterized extends Suite {
190
239
*/
191
240
public Parameterized (Class <?> klass ) throws Throwable {
192
241
super (klass , NO_RUNNERS );
242
+ ParametersRunnerFactory runnerFactory = getParametersRunnerFactory (
243
+ klass );
193
244
Parameters parameters = getParametersMethod ().getAnnotation (
194
245
Parameters .class );
195
- fRunners = Collections .unmodifiableList (createRunnersForParameters (allParameters (), parameters .name ()));
246
+ fRunners = Collections .unmodifiableList (createRunnersForParameters (
247
+ allParameters (), parameters .name (), runnerFactory ));
248
+ }
249
+
250
+ private ParametersRunnerFactory getParametersRunnerFactory (Class <?> klass )
251
+ throws InstantiationException , IllegalAccessException {
252
+ UseParametersRunnerFactory annotation = klass
253
+ .getAnnotation (UseParametersRunnerFactory .class );
254
+ if (annotation == null ) {
255
+ return DEFAULT_FACTORY ;
256
+ } else {
257
+ Class <? extends ParametersRunnerFactory > factoryClass = annotation
258
+ .value ();
259
+ return factoryClass .newInstance ();
260
+ }
196
261
}
197
262
198
263
@ Override
199
264
protected List <Runner > getChildren () {
200
265
return fRunners ;
201
266
}
202
267
203
- private Runner createRunnerWithNotNormalizedParameters (String pattern ,
204
- int index , Object parametersOrSingleParameter )
205
- throws InitializationError {
268
+ private TestWithParameters createTestWithNotNormalizedParameters (
269
+ String pattern , int index , Object parametersOrSingleParameter ) {
206
270
Object [] parameters = (parametersOrSingleParameter instanceof Object []) ? (Object []) parametersOrSingleParameter
207
271
: new Object [] { parametersOrSingleParameter };
208
- TestWithParameters test = createTestWithParameters (getTestClass (),
209
- pattern , index , parameters );
210
- return createRunnerForTest (test );
211
- }
212
-
213
- protected Runner createRunnerForTest (TestWithParameters test )
214
- throws InitializationError {
215
- return new BlockJUnit4ClassRunnerWithParameters (test );
272
+ return createTestWithParameters (getTestClass (), pattern , index ,
273
+ parameters );
216
274
}
217
275
218
276
@ SuppressWarnings ("unchecked" )
@@ -240,20 +298,37 @@ private FrameworkMethod getParametersMethod() throws Exception {
240
298
+ getTestClass ().getName ());
241
299
}
242
300
243
- private List <Runner > createRunnersForParameters (Iterable <Object > allParameters , String namePattern ) throws Exception {
301
+ private List <Runner > createRunnersForParameters (
302
+ Iterable <Object > allParameters , String namePattern ,
303
+ ParametersRunnerFactory runnerFactory )
304
+ throws InitializationError ,
305
+ Exception {
244
306
try {
245
- int i = 0 ;
246
- List <Runner > children = new ArrayList <Runner >();
247
- for (Object parametersOfSingleTest : allParameters ) {
248
- children .add (createRunnerWithNotNormalizedParameters (
249
- namePattern , i ++, parametersOfSingleTest ));
307
+ List <TestWithParameters > tests = createTestsForParameters (
308
+ allParameters , namePattern );
309
+ List <Runner > runners = new ArrayList <Runner >();
310
+ for (TestWithParameters test : tests ) {
311
+ runners .add (runnerFactory
312
+ .createRunnerForTestWithParameters (test ));
250
313
}
251
- return children ;
314
+ return runners ;
252
315
} catch (ClassCastException e ) {
253
316
throw parametersMethodReturnedWrongType ();
254
317
}
255
318
}
256
319
320
+ private List <TestWithParameters > createTestsForParameters (
321
+ Iterable <Object > allParameters , String namePattern )
322
+ throws Exception {
323
+ int i = 0 ;
324
+ List <TestWithParameters > children = new ArrayList <TestWithParameters >();
325
+ for (Object parametersOfSingleTest : allParameters ) {
326
+ children .add (createTestWithNotNormalizedParameters (namePattern ,
327
+ i ++, parametersOfSingleTest ));
328
+ }
329
+ return children ;
330
+ }
331
+
257
332
private Exception parametersMethodReturnedWrongType () throws Exception {
258
333
String className = getTestClass ().getName ();
259
334
String methodName = getParametersMethod ().getName ();
0 commit comments