当前位置: 首页 > 知识库问答 >
问题:

如何使用Junit5平台启动器api从队列中发现测试?

陈项禹
2023-03-14

我希望将测试分发到junit5独立控制台的多个实例,每个实例从队列中读取数据。runner的每个实例将使用相同的测试。jar在类路径上,所以我不想在这里分发实际测试的字节码,只想分发测试/过滤器模式字符串的名称。

在JUnit5高级主题文档中,我认为扩展JUnit5的合适地方是使用平台启动器api。我将这段代码大致与指南中的示例代码拼凑在一起。我认为这是我需要写的,但我担心我过于简化了这里所涉及的工作:

// keep pulling test classes off the queue until its empty
while(myTestQueue.isNotEmpty()) {
    String classFromQueue = myTestQueue.next(); //returns "org.myorg.foo.fooTests"
    LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
        .selectors(selectClass(classFromQueue)).build();
        
    SummaryGeneratingListener listener = new SummaryGeneratingListener();
    try (LauncherSession session = LauncherFactory.openSession()) {
        Launcher launcher = session.getLauncher();
        launcher.registerTestExecutionListeners(listener);
        TestPlan testPlan = launcher.discover(request);
        launcher.execute(testPlan);
    }   
    TestExecutionSummary summary = listener.getSummary();
    addSummary(summary);
}

问题:

  1. 在while循环中重复发现和执行是否会违反正常的测试生命周期?我有点不清楚,在所有处决之前,发现是否应该是一次性的
  2. 如果我假设重复发现然后执行是可以的,我认为HierarchicalTestEngine可能是从队列中读取数据的更好地方,因为它似乎用于实现并行执行。这更适合我的用例吗?除了可能不需要处理累积的测试摘要之外,实现是否与上面的基本相同

我不想采用的方法:我不打算使用junit 5的新特性来在同一个jvm中并行执行测试。我也不打算提前划分考试或课程;用预先确定的测试子集启动每个控制台运行程序实例。

共有1个答案

夏侯阳
2023-03-14

问题中发布的代码(粗略地)说明了一种有效的方法。不需要创建自定义引擎。利用platform launcher api来重复发现和执行测试确实有效。我认为值得强调的是,你不必扩展junit5,这不是通过一个你需要注册的扩展来执行的,正如我最初假设的那样。您只是简单地利用平台启动器api来发现和执行测试。

这是一些示例代码,其中包含存在于类路径上的测试类名的简单队列。虽然队列不是空的,但testNode类的实例将发现并执行三个测试类中的每一个,并编写LegacyXmlReport。

package org.sample.node;
import org.junit.platform.launcher.Launcher;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.LauncherSession;
import org.junit.platform.launcher.TestPlan;
import org.junit.platform.launcher.core.LauncherConfig;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.launcher.core.LauncherFactory;
import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
import org.junit.platform.reporting.legacy.xml.LegacyXmlReportGeneratingListener;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.Queue;

import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
public class TestNode {

    public void run() throws FileNotFoundException {

        // keep pulling test classes off the queue until its empty
        Queue<String> queue = getQueue();
        while(!queue.isEmpty()) {
            String testClass = queue.poll();
            LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
                    .selectors(selectClass(testClass)).build();


            LauncherConfig launcherConfig = LauncherConfig.builder()
                    .addTestExecutionListeners(new LegacyXmlReportGeneratingListener(Paths.get("target"), new PrintWriter(new FileOutputStream("log.txt"))))
                    .build();

            SummaryGeneratingListener listener = new SummaryGeneratingListener();
            try (LauncherSession session = LauncherFactory.openSession(launcherConfig)) {
                Launcher launcher = session.getLauncher();
                launcher.registerTestExecutionListeners(listener);
                TestPlan testPlan = launcher.discover(request);
                launcher.execute(testPlan);
            }
        }
    }

    private Queue<String> getQueue(){
        Queue<String> queue = new LinkedList<>();
        queue.add("org.sample.tests.Class1");
        queue.add("org.sample.tests.Class2");
        queue.add("org.sample.tests.Class3");
        return queue;
    }

    public static void main(String[] args) throws FileNotFoundException {
        TestNode node = new TestNode();
        node.run();
    }
}

我只显示了三个测试类中的一个,因为它们都是相同的东西,只是类名不同。它们位于src/main/java中,而不是src/test/java中。在maven中,将测试打包到一个大罐子中,这是一种公认的怪异但常见的模式。

package org.sample.tests;

import org.junit.jupiter.api.Test;

public class Class1 {
    @Test
    void test1() {
        System.out.println("Class1 Test 1");
    }

    @Test
    void test2() {
        System.out.println("Class1 Test 2");
    }

    @Test
    void test3() {
        System.out.println("Class1 Test 3");
    }
}
 类似资料:
  • 我编译了测试,并尝试执行以下操作来运行它们: 这引发了一个巨大的异常,开始是这样的: 但基本上说它找不到JUnitExc的类。如果我让控制台启动器查找测试,它找不到任何测试: 我不知道如何在没有IDE的情况下从命令行运行JUnit5测试。 更新: 使用 Maven 运行测试(使用 Surefire 插件)会给我同样的错误。我什至删除了所有测试,但仅导入 junit5 依赖项的测试除外,但我仍然收到

  • 我正在为我的Spring启动应用程序执行单元测试。测试工作正常,并在从intellij运行时给出预期的输出。我正在尝试使用Junit5控制台启动器从终端运行相同的测试。这是我使用的命令:- 我从包含测试类的< code > out/tests/package 文件夹中运行上面的命令。 我可以在我的外部jars文件夹中看到所需的jar和依赖项。但是当我从终端运行它时,我得到了下面的错误。 整个堆栈跟

  • 我试图用JUnit5控制台启动器运行一个简单的测试。我试了几个选择,但都不起作用。谁能告诉我哪里出了问题吗? .+--JUnit Jupiter[OK] '--JUnit Vintage[OK] 测试运行在11毫秒后完成[2个容器] [0个容器跳过][2个容器启动] [0个容器中止][2个容器成功] [0个容器失败][0个测试找到] [0个测试跳过][0个测试启动] [0个测试中止][0个测试成功

  • 问题内容: 我正在尝试使用JUnit5控制台启动器运行一个简单的测试。我尝试了几种选择,但是没有用。有人可以告诉我哪里出了问题吗? 给我警告 我试图在目录中运行所有测试,但这似乎找不到测试: 结果是这样的: 。+-JUnit Jupiter [确定] ‘-JUnit Vintage [确定] 11毫秒后测试运行完成[找到2个容器] [跳过0个容器] [0个容器中止] [2个容器成功] [0个容器失

  • JUnit5是模块化的。 我理解一切都是基于平台模块(): Jupiter模块(API+引擎部件:+)和 Vitage模块(API+引擎部分:+和)都使用平台模块作为基础模块。 但是什么是平台发射器,什么时候需要它? 什么时候、为什么需要它,以及如何将它添加到?

  • 我需要测试使用@ConfigurationProperties bean的自动配置类。我正在使用中记录的ApplicationContextRunnerhttps://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-具有测试自动配置功能,可以加快测试速度,避免在每个变体之间启