Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support the selection of a default Runner in ClassRequest #1423

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -31,6 +31,7 @@ public Runner runnerForClass(Class<?> testClass) throws Throwable {
annotatedBuilder(),
suiteMethodBuilder(),
junit3Builder(),
defaultBuilder(),
junit4Builder());

for (RunnerBuilder each : builders) {
Expand Down Expand Up @@ -58,6 +59,10 @@ protected IgnoredBuilder ignoredBuilder() {
return new IgnoredBuilder();
}

protected RunnerBuilder defaultBuilder() {
return new NullBuilder();
}

protected RunnerBuilder suiteMethodBuilder() {
if (canUseSuiteMethod) {
return new SuiteMethodBuilder();
Expand Down
21 changes: 1 addition & 20 deletions src/main/java/org/junit/internal/builders/AnnotatedBuilder.java
Expand Up @@ -2,7 +2,6 @@

import org.junit.runner.RunWith;
import org.junit.runner.Runner;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;

import java.lang.reflect.Modifier;
Expand Down Expand Up @@ -69,8 +68,6 @@
* @since 4.0
*/
public class AnnotatedBuilder extends RunnerBuilder {
private static final String CONSTRUCTOR_ERROR_FORMAT = "Custom runner class %s should have a public constructor with signature %s(Class testClass)";

private final RunnerBuilder suiteBuilder;

public AnnotatedBuilder(RunnerBuilder suiteBuilder) {
Expand All @@ -83,7 +80,7 @@ public Runner runnerForClass(Class<?> testClass) throws Exception {
currentTestClass = getEnclosingClassForNonStaticMemberClass(currentTestClass)) {
RunWith annotation = currentTestClass.getAnnotation(RunWith.class);
if (annotation != null) {
return buildRunner(annotation.value(), testClass);
return buildRunner(annotation.value(), testClass, suiteBuilder);
}
}

Expand All @@ -97,20 +94,4 @@ private Class<?> getEnclosingClassForNonStaticMemberClass(Class<?> currentTestCl
return null;
}
}

public Runner buildRunner(Class<? extends Runner> runnerClass,
Class<?> testClass) throws Exception {
try {
return runnerClass.getConstructor(Class.class).newInstance(testClass);
} catch (NoSuchMethodException e) {
try {
return runnerClass.getConstructor(Class.class,
RunnerBuilder.class).newInstance(testClass, suiteBuilder);
} catch (NoSuchMethodException e2) {
String simpleName = runnerClass.getSimpleName();
throw new InitializationError(String.format(
CONSTRUCTOR_ERROR_FORMAT, simpleName, simpleName));
}
}
}
}
18 changes: 18 additions & 0 deletions src/main/java/org/junit/internal/builders/DefaultBuilder.java
@@ -0,0 +1,18 @@
package org.junit.internal.builders;

import org.junit.runner.Runner;
import org.junit.runners.model.RunnerBuilder;

public class DefaultBuilder extends RunnerBuilder {
private Class<? extends Runner> defaultRunnerClass;
private RunnerBuilder suiteBuilder;

public DefaultBuilder(Class<? extends Runner> defaultRunnerClass, RunnerBuilder suiteBuilder) {
this.defaultRunnerClass = defaultRunnerClass;
this.suiteBuilder = suiteBuilder;
}

public Runner runnerForClass(Class<?> testClass) throws Throwable {
return buildRunner(defaultRunnerClass, testClass, suiteBuilder);
}
}
18 changes: 17 additions & 1 deletion src/main/java/org/junit/internal/requests/ClassRequest.java
@@ -1,6 +1,7 @@
package org.junit.internal.requests;

import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
import org.junit.internal.builders.DefaultBuilder;
import org.junit.internal.builders.SuiteMethodBuilder;
import org.junit.runner.Request;
import org.junit.runner.Runner;
Expand All @@ -17,10 +18,17 @@ public class ClassRequest extends Request {
private final Class<?> fTestClass;
private final boolean canUseSuiteMethod;
private volatile Runner runner;
private Class<? extends Runner> defaultRunnerClass;

public ClassRequest(Class<?> testClass, boolean canUseSuiteMethod) {
public ClassRequest(Class<?> testClass, boolean canUseSuiteMethod,
Class<? extends Runner> defaultRunnerClass) {
this.fTestClass = testClass;
this.canUseSuiteMethod = canUseSuiteMethod;
this.defaultRunnerClass = defaultRunnerClass;
}

public ClassRequest(Class<?> testClass, boolean canUseSuiteMethod) {
this(testClass, canUseSuiteMethod, null);
}

public ClassRequest(Class<?> testClass) {
Expand All @@ -45,6 +53,14 @@ private class CustomAllDefaultPossibilitiesBuilder extends AllDefaultPossibiliti
protected RunnerBuilder suiteMethodBuilder() {
return new CustomSuiteMethodBuilder();
}

@Override
protected RunnerBuilder defaultBuilder() {
if (defaultRunnerClass != null) {
return new DefaultBuilder(defaultRunnerClass, this);
}
return super.defaultBuilder();
}
}

/*
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/org/junit/runner/Request.java
Expand Up @@ -61,6 +61,19 @@ public static Request classWithoutSuiteMethod(Class<?> clazz) {
return new ClassRequest(clazz, false);
}

/**
* Create a <code>Request</code> that, when processed, will run all the tests
* in a class. If the class does not set the runner to use, a runner of the given
* class will be used by default.
*
* @param clazz the class containing the tests
* @param defaultRunnerClass the class of the runner to use by default
* @return a <code>Request</code> that will cause all tests in the class to be run
*/
public static Request classWithDefaultRunner(Class<?> clazz, Class<? extends Runner> defaultRunnerClass) {
return new ClassRequest(clazz, true, defaultRunnerClass);
}

/**
* Create a <code>Request</code> that, when processed, will run all the tests
* in a set of classes.
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/org/junit/runners/model/RunnerBuilder.java
Expand Up @@ -37,6 +37,8 @@
* @since 4.5
*/
public abstract class RunnerBuilder {
private static final String CONSTRUCTOR_ERROR_FORMAT = "Custom runner class %s should have a public constructor with signature %s(Class testClass)";

private final Set<Class<?>> parents = new HashSet<Class<?>>();

/**
Expand Down Expand Up @@ -80,6 +82,22 @@ void removeParent(Class<?> klass) {
parents.remove(klass);
}

public Runner buildRunner(Class<? extends Runner> runnerClass,
Class<?> testClass, RunnerBuilder suiteBuilder) throws Exception {
try {
return runnerClass.getConstructor(Class.class).newInstance(testClass);
} catch (NoSuchMethodException e) {
try {
return runnerClass.getConstructor(Class.class,
RunnerBuilder.class).newInstance(testClass, suiteBuilder);
} catch (NoSuchMethodException e2) {
String simpleName = runnerClass.getSimpleName();
throw new InitializationError(String.format(
CONSTRUCTOR_ERROR_FORMAT, simpleName, simpleName));
}
}
}

/**
* Constructs and returns a list of Runners, one for each child class in
* {@code children}. Care is taken to avoid infinite recursion:
Expand Down