如何为 JUnit 测试用例运行启用全局超时?

How to enable a global timeout for JUnit testcase runs?

@Test 注释的这个 question suggests to use the timeout 参数让 JUnit 在该超时期限后强制停止测试。

但是到目前为止,我们有大约 5000 个单元测试,我们想制定一项政策,要求开发人员永远不要发布需要超过 10 秒才能完成的测试。该策略可能会说 "aim for < 10 seconds",但我们希望确保 any 测试在 30 秒后停止。 (数字只是示例,想法是为大多数用例定义 "good enough" 的东西,但这也确保事情不会 运行 "forever" )

现在我想知道是否有一种方法可以启用这种行为 而无需 进入每个测试用例并添加该注释参数。

现有的 question 也无济于事:我正在寻找 一个 更改以启用此功能,而不是 每个测试一个更改 class解。一个中央全局交换机。不是每个文件或方法一个。

您可能正在寻找的内容尚未实现:https://github.com/junit-team/junit4/issues/140

不过,您可以通过简单的继承获得相同的结果。

定义一个抽象父级 class,如 BaseIntegrationTest 和以下 @Rule 字段:

public abstract class BaseIntegrationTest extends RunListener {

    private static final int TEST_GLOBAL_TIMEOUT_VALUE = 10;

    @Rule
    protected Timeout globalTimeout = Timeout.seconds(TEST_GLOBAL_TIMEOUT_VALUE);

}

然后将其作为范围内每个测试 class 的父级。例如:

public class BaseEntityTest extends BaseIntegrationTest {

    @Before
    public void init() {
        // init
    }

    @Test
    public void twoPlusTwoTest() throws Exception {
        assert 2 + 2 == 4;        
    }
}

就是这样。

尽管 JUnit Jupiter(即 JUnit 5 中引入的编程和扩展模型)还没有 内置 support for global timeouts,您仍然可以实现全局超时自己支持。

唯一的问题是超时扩展当前无法抢先中止测试执行。换句话说,JUnit Jupiter 中的超时扩展目前只能计时测试的执行时间,然后在执行时间过长时抛出异常(即,在等待测试结束后,如果测试 挂起).

无论如何,如果您想实现非抢占式全局超时扩展以与 JUnit Jupiter 一起使用,这就是您需要做的。

  1. 查看 JUnit 5 用户指南中的 TimingExtension 示例以获取灵感。您将需要与此类似的代码,但如果 duration 超过配置的 timeout,您将希望抛出异常。如何配置全局超时由您决定:对其进行硬编码,从 JVM 系统中查找值 属性,从自定义注释中查找值等
  2. 使用 Java 的 ServiceLoader 机制注册您的全局超时扩展。有关详细信息,请参阅 Automatic Extension Registration

测试愉快!

目前,您可能不能这样做,因为 Junit 5 删除了 Rule 并替换为 Extension does not work because the example code 实现了将在测试方法完成后调用的 AfterTestExecutionCallback,因此超时没有用。

查看我的 JUnit 4 扩展库 (https://github.com/Nordstrom/JUnit-Foundation)。该库提供的功能之一是能够定义全局超时值,该值将自动应用于尚未定义更长超时间隔的每个测试方法。

该库使用 Byte Buddy 字节代码生成库在 JUnit 4 测试执行流程中的关键点安装事件挂钩。当 JUnit 创建一个测试 class 实例到 运行 一个 "atomic" 测试。

为了应用全局超时,库将原始的@Test 注释替换为实现@Test 接口的对象。这种方法利用了 JUnit 的所有本机超时功能,它提供了 运行 太长的测试的先发制人终止。本机超时功能的使用消除了侵入性实施或特殊情况处理的需要,并且无需触及单个源文件即可激活此功能。

安装和激活全局超时支持所需的所有更新都在项目文件 (POM / build.gradle) 和可选属性文件中。可以通过系统 属性 覆盖超时间隔,这使得可以从命令行或以编程方式进行调整。对于由瞬态条件导致超时失败的场景,您可能希望将全局超时功能与自动重试功能配对。