通过 LauncherDiscoveryRequest 在提供的类路径上发现测试

Discovering tests on provided classpath via LauncherDiscoveryRequest

我正尝试在 LauncherDiscoveryRequest 作为 described in the user guide 的帮助下发现 JUnit 5 测试。我使用的代码如下所示:

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());
    }
}

是否 LauncherDiscoveryRequestBuilder 仅自动发现 JVM class 路径上的测试 运行 此代码?我尝试使用方法 DiscoverySelectors.selectClasspathRootsDiscoverySelectors.selectClasspathResource 作为选择器来提供要搜索测试 classes 的根目录。但是,我无法发现任何测试。 selectClasspathRootsselectClasspathResource 的参数是否必须指向包含按包组织的 class 文件的根目录,或者您是否提供每个测试 class 文件的完整路径?

我尝试了以下 /some/dir 代表包含测试 class 文件的根目录:

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

我查看了 LauncherDiscoveryRequestBuilderTests.java,但它对弄清楚为什么我的示例代码不起作用没有多大用处。如何最好地诊断问题?

我正在使用以下依赖项:

LauncherDiscoveryRequestBuilder 是否仅在 classJVM 的路径运行这段代码?

不,它可以扫描 jvm 中的每个 class。您必须至少提供一个选择器,但发现是通过 class 路径上有组织的文件夹/包结构完成的。

添加过滤器以控制 class 要扫描的内容。

这是来自文档。

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

所有的发现选择器都是通过各种方式到达测试classes.

可能没有更多的上下文,但这就是我根据文档和 running/debugging 下面的测试所能弄清楚的。

ClasspathScannerTests

输出

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]

样本测试Class

package discover.suite;

import org.junit.jupiter.api.Test;

public class Junit5TestCase {

    @Test
    public void junitMethod() {
    }

}

下面是几个使用不同选择器的例子。

    //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();

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

简短回答:是的,Launcher 只会在 JVM 运行 代码的 class 路径上自动发现测试。

通常,TestEngine 实现负责解析选择器,例如您通过 selectClasspathRoots() 创建的 ClasspathRootSelector。 Jupiter 和 Vintage 引擎将扫描提供的目录以查找 .class 文件,然后尝试使用当前线程的上下文 ClassLoader 加载它们。如果后一步失败,class 将被忽略。

如果您想发现尚未在 class 路径上的测试,您需要创建一个新的 ClassLoader 并使其成为当前线程的上下文 ClassLoader。 JUnit 平台 ConsoleLauncher 也这样做:

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