-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
I've uploaded a minimal reproduction to this repository: https://github.com/fapdash/junit-classselection-reproduction.
I'll reproduce the main method here:
package reproduction;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import org.junit.platform.engine.discovery.DiscoverySelectors;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.launcher.core.LauncherFactory;
public class Main {
public static void main(String[] args) throws IOException {
var className = "ExampleJUnit4Test";
compileAndSelect(className);
className = "ExampleJUnit5Test";
compileAndSelect(className);
}
private static void compileAndSelect(String className) throws IOException {
System.out.format("Testing class: %s\n", className);
var compiler = ToolProvider.getSystemJavaCompiler();
var diagnosticCollector = new DiagnosticCollector<>();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnosticCollector, null, null);
Path tempDirectory = Files.createTempDirectory(String.format("junit-reproduction-"));
System.out.format("Compiling to %s\n", tempDirectory);
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, List.of(tempDirectory.toFile()));
Iterable<? extends JavaFileObject> sources = fileManager
.getJavaFileObjectsFromPaths(List.of(Path.of(className + ".java")));
var task = compiler.getTask(null, fileManager, diagnosticCollector, null, null, sources);
if (!task.call()) {
System.out.println("Failed compilation!");
return;
}
ClassLoader classLoader = fileManager.getClassLoader(StandardLocation.CLASS_OUTPUT);
Iterable<? extends Path> classpathRootsIterable = fileManager.getLocationAsPaths(StandardLocation.CLASS_OUTPUT);
Set<Path> classpathRoots = new HashSet<>();
classpathRootsIterable.forEach(classpathRoots::add);
var originalClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(classLoader);
var request = LauncherDiscoveryRequestBuilder.request()
.selectors(DiscoverySelectors.selectClass(classLoader, className)).build();
var launcher = LauncherFactory.create();
var testPlan = launcher.discover(request);
System.out.format("TestPlan contains tests: %s\n", testPlan.containsTests());
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
When I run the example from inside of Eclipse I get the expected output, but when I run the example via the shadow jar JUnit doesn't select the JUnit 4 test class.
JUnit definitely finds the class, otherwise there would be a PreconditionViolationException
, caused by a ClassNotFoundException
. But for some reason JUnit doesn't select the class as a test class.
In the example repo I've used JUnit version 6.0.0-RC2
, but I observe the same behavior with 5.13.4
.
Steps to reproduce
Compile the project to a shadow jar and then run the example:
./gradlew clean build
java -jar build/libs/junit-classselection-reproduction-1.0-SNAPSHOT-all.jar
Expected output would be
Testing class: ExampleJUnit4Test
Compiling to /tmp/junit-reproduction-abc
TestPlan contains tests: true
Testing class: ExampleJUnit5Test
Compiling to /tmp/junit-reproduction-xyz
TestPlan contains tests: true
Actual output:
Testing class: ExampleJUnit4Test
Compiling to /tmp/junit-reproduction-asd
TestPlan contains tests: false
Testing class: ExampleJUnit5Test
Compiling to /tmp/junit-reproduction-fgh
TestPlan contains tests: true
Context
- Used versions (Jupiter/Vintage/Platform): Vintage
- Build Tool/IDE: Gradle / Eclipse
I hope my reproduction is useful.
Let me know if you need any additional information!