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



这个问题建议使用@Test注释的超时参数,让 JUnit 在该超时期限后强制停止测试。

但是到目前为止,我们有大约 5000 个单元测试,我们希望建立一个策略,要求开发人员永远不要发布需要超过 10 秒才能完成的测试。该策略可能会说"瞄准 10 秒<",但我们希望确保在 30 秒后停止任何测试。(数字只是示例,这个想法是为大多数用例定义一些"足够好"的东西,但这也确保事情不会"永远"运行)

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

现有的问题也无济于事:我正在寻找一个更改来实现这一点,而不是每个测试类解决方案的一个更改。一个集中式全局交换机。不是每个文件或方法一个。

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

唯一的问题是超时扩展当前无法抢先中止测试执行。换句话说,JUnit Jupiter 中的超时扩展目前只能对测试的执行进行计时,然后在执行时间过长时(即,在等待测试结束之后,如果测试挂起,这可能永远不会发生)引发异常。

无论如何,如果你想实现一个非抢占式全局超时扩展来与JUnit Jupiter一起使用,你需要这样做。

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

测试愉快!

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

此库使用 Byte Buddy 字节代码生成库在 JUnit 4 测试执行流中的战略点安装事件钩子。当 JUnit 创建测试类实例以运行"原子"测试时,将应用全局超时。

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

安装和激活全局超时支持所需的所有更新都在项目文件 (POM/build.gradle) 和可选属性文件中。可以通过 System 属性重写超时间隔,该属性允许从命令行或以编程方式进行调整。对于超时失败是由暂时性条件引起的场景,您可能需要将全局超时功能与自动重试功能配对。

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

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

定义一个抽象的父类,如具有以下@Rule字段的BaseIntegrationTest

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

然后,使其成为范围内每个测试类的父类。例如:

public class BaseEntityTest extends BaseIntegrationTest {
@Before
public void init() {
// init
}
@Test
public void twoPlusTwoTest() throws Exception {
assert 2 + 2 == 4;        
}
}

就是这样。

目前,也许你不能,因为 Junit 5 删除了Rule并替换为Extension. 上面的示例不起作用,因为示例代码实现了测试方法完成后将调用的AfterTestExecutionCallback,因此超时没有用。

最新更新