Skip to content

Commit

Permalink
Allow JUnit5 runner to be extended
Browse files Browse the repository at this point in the history
  • Loading branch information
brian-mcnamara committed Aug 8, 2024
1 parent ca23db3 commit 8e3166c
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
import java.util.stream.Collectors;
import org.junit.jupiter.engine.Constants;
import org.junit.platform.engine.DiscoverySelector;
import org.junit.platform.engine.Filter;
import org.junit.platform.engine.discovery.DiscoverySelectors;
import org.junit.platform.launcher.Launcher;
import org.junit.platform.launcher.LauncherConstants;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.TagFilter;
import org.junit.platform.launcher.core.LauncherConfig;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
Expand Down Expand Up @@ -60,65 +62,12 @@ public boolean run(String testClassName) {
.addPostDiscoveryFilters(TestSharding.makeShardFilter())
.build();

final Class<?> testClass;
try {
testClass = Class.forName(testClassName, false, getClass().getClassLoader());
} catch (ClassNotFoundException e) {
throw new RuntimeException("Failed to find testClass", e);
}

// We only allow for one level of nesting at the moment
boolean enclosed = isRunWithEnclosed(testClass);
List<DiscoverySelector> classSelectors =
enclosed
? new ArrayList<>()
: Arrays.stream(testClass.getDeclaredClasses())
.filter(clazz -> Modifier.isStatic(clazz.getModifiers()))
.map(DiscoverySelectors::selectClass)
.collect(Collectors.toList());

classSelectors.add(DiscoverySelectors.selectClass(testClassName));

LauncherDiscoveryRequestBuilder request =
LauncherDiscoveryRequestBuilder.request()
.selectors(classSelectors)
.configurationParameter(LauncherConstants.CAPTURE_STDERR_PROPERTY_NAME, "true")
.configurationParameter(LauncherConstants.CAPTURE_STDOUT_PROPERTY_NAME, "true")
.configurationParameter(
Constants.EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME, "true");

String filter = System.getenv("TESTBRIDGE_TEST_ONLY");
request.filters(new PatternFilter(filter));

String includeTags = System.getProperty("JUNIT5_INCLUDE_TAGS");
if (includeTags != null && !includeTags.isEmpty()) {
request.filters(TagFilter.includeTags(includeTags.split(",")));
}

String excludeTags = System.getProperty("JUNIT5_EXCLUDE_TAGS");
if (excludeTags != null && !excludeTags.isEmpty()) {
request.filters(TagFilter.excludeTags(excludeTags.split(",")));
}

List<String> includeEngines =
System.getProperty("JUNIT5_INCLUDE_ENGINES") == null
? null
: Arrays.asList(System.getProperty("JUNIT5_INCLUDE_ENGINES").split(","));
List<String> excludeEngines =
System.getProperty("JUNIT5_EXCLUDE_ENGINES") == null
? null
: Arrays.asList(System.getProperty("JUNIT5_EXCLUDE_ENGINES").split(","));
if (includeEngines != null) {
request.filters(includeEngines(includeEngines));
}
if (excludeEngines != null) {
request.filters(excludeEngines(excludeEngines));
}
LauncherDiscoveryRequest request = getRequest(testClassName);

File exitFile = getExitFile();

Launcher launcher = LauncherFactory.create(config);
launcher.execute(request.build());
launcher.execute(request);

deleteExitFile(exitFile);

Expand All @@ -130,6 +79,72 @@ public boolean run(String testClassName) {
}
}

protected LauncherDiscoveryRequest getRequest(String testClassName) {
final Class<?> testClass;
try {
testClass = Class.forName(testClassName, false, getClass().getClassLoader());
} catch (ClassNotFoundException e) {
throw new RuntimeException("Failed to find testClass", e);
}

// We only allow for one level of nesting at the moment
boolean enclosed = isRunWithEnclosed(testClass);
List<DiscoverySelector> classSelectors =
enclosed
? new ArrayList<>()
: Arrays.stream(testClass.getDeclaredClasses())
.filter(clazz -> Modifier.isStatic(clazz.getModifiers()))
.map(DiscoverySelectors::selectClass)
.collect(Collectors.toList());

classSelectors.add(DiscoverySelectors.selectClass(testClassName));

LauncherDiscoveryRequestBuilder request =
LauncherDiscoveryRequestBuilder.request()
.selectors(classSelectors)
.configurationParameter(LauncherConstants.CAPTURE_STDERR_PROPERTY_NAME, "true")
.configurationParameter(LauncherConstants.CAPTURE_STDOUT_PROPERTY_NAME, "true")
.configurationParameter(
Constants.EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME, "true")
.filters(getFilters().toArray(new Filter[0]));

return request.build();
}

protected List<Filter<?>> getFilters() {
List<Filter<?>> filters = new ArrayList<>();

String filter = System.getenv("TESTBRIDGE_TEST_ONLY");
filters.add(new PatternFilter(filter));

String includeTags = System.getProperty("JUNIT5_INCLUDE_TAGS");
if (includeTags != null && !includeTags.isEmpty()) {
filters.add(TagFilter.includeTags(includeTags.split(",")));
}

String excludeTags = System.getProperty("JUNIT5_EXCLUDE_TAGS");
if (excludeTags != null && !excludeTags.isEmpty()) {
filters.add(TagFilter.excludeTags(excludeTags.split(",")));
}

List<String> includeEngines =
System.getProperty("JUNIT5_INCLUDE_ENGINES") == null
? null
: Arrays.asList(System.getProperty("JUNIT5_INCLUDE_ENGINES").split(","));
List<String> excludeEngines =
System.getProperty("JUNIT5_EXCLUDE_ENGINES") == null
? null
: Arrays.asList(System.getProperty("JUNIT5_EXCLUDE_ENGINES").split(","));
if (includeEngines != null) {
filters.add(includeEngines(includeEngines));
}
if (excludeEngines != null) {
filters.add(excludeEngines(excludeEngines));
}

return filters;
}

/**
* Checks if the test class is annotation with `@RunWith(Enclosed.class)`. We deliberately avoid
* using types here to avoid polluting the classpath with junit4 deps.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ public class JUnit5Runner {
"com.github.bazel_contrib.contrib_rules_jvm.junit5.Java17SystemExitToggle";

public static void main(String[] args) {
new JUnit5Runner().run();
}

public void run() {
String testSuite = System.getProperty("bazel.test_suite");

SystemExitToggle systemExitToggle = getSystemExitToggle();
Expand All @@ -33,9 +37,7 @@ public static void main(String[] args) {
systemExitToggle.prevent();

try {
Constructor<? extends RunsTest> constructor =
Class.forName(JUNIT5_RUNNER_CLASS).asSubclass(RunsTest.class).getConstructor();
RunsTest runsTest = constructor.newInstance();
RunsTest runsTest = getRunner();
if (!runsTest.run(testSuite)) {
exit(systemExitToggle, 2);
}
Expand All @@ -50,7 +52,13 @@ public static void main(String[] args) {
exit(systemExitToggle, 0);
}

private static SystemExitToggle getSystemExitToggle() {
protected RunsTest getRunner() throws ReflectiveOperationException {
Constructor<? extends RunsTest> constructor =
Class.forName(JUNIT5_RUNNER_CLASS).asSubclass(RunsTest.class).getConstructor();
return constructor.newInstance();
}

protected SystemExitToggle getSystemExitToggle() {
// In Java 8 and lower, the first part of the version is a 1.
// In Java 9 and higher, the first part of the version is the feature version.
// Major versions of early Access builds have an "-ea" suffix.
Expand Down

0 comments on commit 8e3166c

Please sign in to comment.