com.saucelabs.junit.ConcurrentParameterized Maven / Gradle / Ivy
package com.saucelabs.junit;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.Suite;
import org.junit.runners.model.*;
import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;
/**
* Reimplementation of {@link Parallelized} to support parameterized tests and concurrent execution of test methods.
*
* The {@link Parallelized} class follows a similar pattern, however in that class, the underlying runner scheduler
* only allows single tests to be executed. The surefire/failsafe plugins facilitate test methods to be run in parallel,
* but this doesn't seem to work with parameterized tests.
*
* @author Ross Rowe
*/
public class ConcurrentParameterized extends Suite {
/**
* Annotation for a method which provides parameters to be injected into the
* test class constructor by SauceParameterized
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Parameters {
/**
* Optional pattern to derive the test's name from the parameters. Use
* numbers in braces to refer to the parameters or the additional data
* as follows:
*
* {index} - the current parameter index
* {0} - the first parameter value
* {1} - the second parameter value
* etc...
*
* Default value is "{index}" for compatibility with previous JUnit
* versions.
*
* @return {@link java.text.MessageFormat} pattern string, except the index
* placeholder.
* @see java.text.MessageFormat
*/
String name() default "{index}";
}
/**
* Annotation for fields of the test class which will be initialized by the
* method annotated by Parameters
* By using directly this annotation, the test class constructor isn't needed.
* Index range must start at 0.
* Default value is 0.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Parameter {
/**
* Method that returns the index of the parameter in the array
* returned by the method annotated by Parameters
.
* Index range must start at 0.
* Default value is 0.
*
* @return the index of the parameter.
*/
int value() default 0;
}
private static final List NO_RUNNERS = Collections.emptyList();
private final ArrayList runners = new ArrayList();
/**
* Only called reflectively. Do not use programmatically.
* @param klass Sets up class with data provider and runners for parallel runs
* @throws Throwable Throwable propagating from {link#createRunnersForParameters}
*/
public ConcurrentParameterized(Class> klass) throws Throwable {
super(klass, NO_RUNNERS);
Parameters parameters = getParametersMethod().getAnnotation(
Parameters.class);
createRunnersForParameters(allParameters(), parameters.name());
setScheduler(new NonBlockingAsynchronousRunner());
}
@Override
protected List getChildren() {
return runners;
}
@SuppressWarnings("unchecked")
private Iterable