package org.junit.runners.model;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.internal.runners.ErrorReportingRunner;
import org.junit.runner.Runner;

A RunnerBuilder is a strategy for constructing runners for classes. Only writers of custom runners should use RunnerBuilders. A custom runner class with a constructor taking a RunnerBuilder parameter will be passed the instance of RunnerBuilder used to build that runner itself. For example, imagine a custom runner that builds suites based on a list of classes in a text file:
\@RunWith(TextFileSuite.class)
\@SuiteSpecFile("mysuite.txt")
class MySuite {}
The implementation of TextFileSuite might include:
public TextFileSuite(Class testClass, RunnerBuilder builder) {
  // ...
  for (String className : readClassNames())
    addRunner(builder.runnerForClass(Class.forName(className)));
  // ...
}
See Also:
Since:4.5
/** * A RunnerBuilder is a strategy for constructing runners for classes. * * Only writers of custom runners should use <code>RunnerBuilder</code>s. A custom runner class with a constructor taking * a <code>RunnerBuilder</code> parameter will be passed the instance of <code>RunnerBuilder</code> used to build that runner itself. * For example, * imagine a custom runner that builds suites based on a list of classes in a text file: * * <pre> * \@RunWith(TextFileSuite.class) * \@SuiteSpecFile("mysuite.txt") * class MySuite {} * </pre> * * The implementation of TextFileSuite might include: * * <pre> * public TextFileSuite(Class testClass, RunnerBuilder builder) { * // ... * for (String className : readClassNames()) * addRunner(builder.runnerForClass(Class.forName(className))); * // ... * } * </pre> * * @see org.junit.runners.Suite * @since 4.5 */
public abstract class RunnerBuilder { private final Set<Class<?>> parents = new HashSet<Class<?>>();
Override to calculate the correct runner for a test class at runtime.
Params:
  • testClass – class to be run
Throws:
  • Throwable – if a runner cannot be constructed
Returns:a Runner
/** * Override to calculate the correct runner for a test class at runtime. * * @param testClass class to be run * @return a Runner * @throws Throwable if a runner cannot be constructed */
public abstract Runner runnerForClass(Class<?> testClass) throws Throwable;
Always returns a runner, even if it is just one that prints an error instead of running tests.
Params:
  • testClass – class to be run
Returns:a Runner
/** * Always returns a runner, even if it is just one that prints an error instead of running tests. * * @param testClass class to be run * @return a Runner */
public Runner safeRunnerForClass(Class<?> testClass) { try { return runnerForClass(testClass); } catch (Throwable e) { return new ErrorReportingRunner(testClass, e); } } Class<?> addParent(Class<?> parent) throws InitializationError { if (!parents.add(parent)) { throw new InitializationError(String.format("class '%s' (possibly indirectly) contains itself as a SuiteClass", parent.getName())); } return parent; } void removeParent(Class<?> klass) { parents.remove(klass); }
Constructs and returns a list of Runners, one for each child class in children. Care is taken to avoid infinite recursion: this builder will throw an exception if it is requested for another runner for parent before this call completes.
/** * Constructs and returns a list of Runners, one for each child class in * {@code children}. Care is taken to avoid infinite recursion: * this builder will throw an exception if it is requested for another * runner for {@code parent} before this call completes. */
public List<Runner> runners(Class<?> parent, Class<?>[] children) throws InitializationError { addParent(parent); try { return runners(children); } finally { removeParent(parent); } } public List<Runner> runners(Class<?> parent, List<Class<?>> children) throws InitializationError { return runners(parent, children.toArray(new Class<?>[0])); } private List<Runner> runners(Class<?>[] children) { ArrayList<Runner> runners = new ArrayList<Runner>(); for (Class<?> each : children) { Runner childRunner = safeRunnerForClass(each); if (childRunner != null) { runners.add(childRunner); } } return runners; } }