Discovering tests on provided classpath via LauncherDiscoveryRequest

5.9k views Asked by At

I am trying to discover JUnit 5 tests with the help of LauncherDiscoveryRequest as described in the user guide. The code I am using looks as follows:

LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
    .filters(includeClassNamePatterns(".*"))
    .build();

TestPlan plan = LauncherFactory.create().discover(request);

for (TestIdentifier root : plan.getRoots()) {
    System.out.println("Root: " + root.toString());

    for (TestIdentifier test : plan.getChildren(root)) {
        System.out.println("Found test: " + test.toString());
    }
}

Does LauncherDiscoveryRequestBuilder only auto-discover tests on the classpath of the JVM running this code? I tried using the methods DiscoverySelectors.selectClasspathRoots and DiscoverySelectors.selectClasspathResource as selectors to provide root directories to be searched for test classes. However, I wasn't able to discover any tests. Do the parameters for selectClasspathRoots and selectClasspathResource have to point to the root directory containing the class files organized by package or do you provide the full path to each test class file?

I tried the following where /some/dir represents the root directory containing test class files:

File classesDir = new File("/some/dir");
LauncherDiscoveryRequestBuilder.request()
     .selectors(selectClasspathRoots(Collections.singleton(Paths.get(classesDir.toURI()))))
     .build();

I had a look at LauncherDiscoveryRequestBuilderTests.java but it wasn't very useful in figuring out why my example code doesn't work. How do I best diagnose the issue?

I am using the following dependencies:

  • org.junit.platform:junit-platform-engine:1.0.0-M3
  • org.junit.platform:junit-platform-launcher:1.0.0-M3
2

There are 2 answers

3
Marc Philipp On BEST ANSWER

Does LauncherDiscoveryRequestBuilder only auto-discover tests on the classpath of the JVM running this code?

Short answer: Yes, the Launcher will only auto-discover tests on the classpath of the JVM running the code.

In general, TestEngine implementations are responsible for resolving selectors such as the ClasspathRootSelector you create via selectClasspathRoots(). The Jupiter and Vintage engines will scan the supplied directories for .class files and then try to load them using the current thread's context ClassLoader. If the latter step fails, the class will be silently ignored.

If you want to discover tests not yet on the classpath, you need to create a new ClassLoader and make it the current thread's context ClassLoader. The JUnit Platform ConsoleLauncher does this, too:

  1. Create custom ClassLoader
  2. Invoke Launcher with replaced context ClassLoader
1
s7vr On

Does LauncherDiscoveryRequestBuilder only auto-discover tests on the classpath of the JVM running this code?

No, it can scan every single class in the jvm. You will have to provide at least one selector, but the discovery is done through organized folder/ package structure on the classpath.

Add filter to control what classes to be scanned.

This is from the docs.

There’s currently the possibility to search for classes, methods, all classes in a package, or even all tests in the classpath.

All the discovery selectors are various ways to reach the test classes.

May be there is little more context, but this is all I can figure out based on docs and running/debugging below tests.

ClasspathScannerTests

Output

Root: TestIdentifier [uniqueId = '[engine:junit-jupiter]', parentId = null, displayName = 'JUnit Jupiter', source = null, tags = [], test = false, container = true]
Found test: TestIdentifier [uniqueId = '[engine:junit-jupiter]/[class:discover.suite.Junit5TestCase]', parentId = '[engine:junit-jupiter]', displayName = 'Junit5TestCase', source = ClassSource [className = 'discover.suite.Junit5TestCase', filePosition = null], tags = [], test = false, container = true]

Sample Test Class

package discover.suite;

import org.junit.jupiter.api.Test;

public class Junit5TestCase {

    @Test
    public void junitMethod() {
    }

}

Below are few examples using different selectors.

    //By classpath root
    File classesDir = new File("C:\\Users\\me\\Junit5\\target\\test-classes");

    LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
            .selectors(selectClasspathRoots(Collections.singleton(Paths.get(classesDir.toURI()))))
            .filters(includeClassNamePatterns(".*"))
            .build();

    //By package
    LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
            .selectors(selectPackage("discover.suite"))
            .filters(includeClassNamePatterns(".*"))
            .build();

    //By Class
    LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
            .selectors(selectClass(Junit5TestCase.class))
            .filters(includeClassNamePatterns(".*"))
            .build();

    //By Method
    LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
            .selectors(selectMethod(Junit5TestCase.class, "junitMethod"))
            .filters(includeClassNamePatterns(".*"))
            .build();