You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让JUnit统计含@BeforeAll的测试类完整执行时长?

如何让JUnit统计测试类完整生命周期时长(包含@BeforeAll/@AfterAll)

方法一:自定义JUnit 5扩展

JUnit 5的扩展机制能直接拦截测试类的生命周期,手动统计时长:

  • 写个扩展类实现BeforeAllCallback和AfterAllCallback接口,在beforeAll方法里记录测试类启动的时间戳,afterAll里计算总耗时并输出
  • 示例代码:
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;

public class ClassLifecycleTimingExtension implements BeforeAllCallback, AfterAllCallback {
    private static final String START_TIME_KEY = "classStartTime";

    @Override
    public void beforeAll(ExtensionContext context) {
        long startTime = System.currentTimeMillis();
        context.getStore(ExtensionContext.Namespace.GLOBAL).put(START_TIME_KEY, startTime);
    }

    @Override
    public void afterAll(ExtensionContext context) {
        long startTime = context.getStore(ExtensionContext.Namespace.GLOBAL).get(START_TIME_KEY, Long.class);
        long totalTime = System.currentTimeMillis() - startTime;
        System.out.printf("测试类[%s]完整生命周期耗时:%d ms%n", 
                          context.getRequiredTestClass().getName(), totalTime);
    }
}
  • 使用时,要么在测试类上加@ExtendWith(ClassLifecycleTimingExtension.class),要么在src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension里写扩展类的全限定名,让所有测试类自动生效

方法二:通过Gradle测试配置统计

直接在Gradle的build.gradle里加监听逻辑,捕捉测试类的启动和结束事件:

test {
    def classStartTimes = [:]

    beforeTest { descriptor ->
        // 只有测试类的descriptor没有父节点
        if (descriptor.parent == null) {
            classStartTimes[descriptor.className] = System.currentTimeMillis()
        }
    }

    afterTest { descriptor, result ->
        if (descriptor.parent == null) {
            long totalTime = System.currentTimeMillis() - classStartTimes[descriptor.className]
            println "测试类 ${descriptor.className} 总耗时:${totalTime} ms"
            // 要是想存到文件里,直接写文件操作就行
        }
    }
}

执行gradle test的时候,控制台就会打印每个测试类的完整耗时,包括@BeforeAll和@AfterAll的时间

方法三:用JUnit 5的TestExecutionListener

注册全局监听类,监听测试类的启动和结束事件:

  • 实现TestExecutionListener接口,重写testClassStarted和testClassFinished方法:
import org.junit.platform.launcher.TestExecutionListener;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestExecutionResult;
import java.util.HashMap;
import java.util.Map;

public class ClassTimingListener implements TestExecutionListener {
    private final Map<String, Long> classStartTimes = new HashMap<>();

    @Override
    public void testClassStarted(TestIdentifier testIdentifier) {
        if (testIdentifier.isTestClass()) {
            classStartTimes.put(testIdentifier.getUniqueId(), System.currentTimeMillis());
        }
    }

    @Override
    public void testClassFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
        if (testIdentifier.isTestClass()) {
            long startTime = classStartTimes.get(testIdentifier.getUniqueId());
            long totalTime = System.currentTimeMillis() - startTime;
            System.out.printf("测试类 %s 完整耗时:%d ms%n", testIdentifier.getDisplayName(), totalTime);
        }
    }
}
  • 注册方式:要么在src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener里写监听类全限定名,要么在Gradle配置里加:
test {
    junitPlatform {
        listeners {
            add 'com.example.ClassTimingListener'
        }
    }
}

如果想把这些时长整合到Gradle默认的HTML报告里,得自定义报告模板或者扩展现有报告,这个相对麻烦,上面的方法先解决统计问题没问题。

内容的提问来源于stack exchange,提问作者bsohdam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 21:06:15