当前位置: 代码迷 >> 综合 >> 基于 junit5 实现 junitperf 源码分析
  详细解决方案

基于 junit5 实现 junitperf 源码分析

热度:65   发布时间:2024-01-06 10:15:54.0

前言

上一节介绍了基于 junit4 实现 junitperf,但是可以发现定义变量的方式依然不够优雅。

那可以让用户使用起来更加自然一些吗?

有的,junit5 为我们带来了更加强大的功能。

拓展阅读:

浅谈性能测试

基于 junit4 分析 junitperf 源码,junit4 99% 的人都不知道的秘密!

junit5

没有对比,就没有伤害

我们首先回顾一下 junit4 的写法:

public class HelloWorldTest {
    @Rulepublic JunitPerfRule junitPerfRule = new JunitPerfRule();/*** 单一线程,执行 1000ms,默认以 html 输出测试结果* @throws InterruptedException if any*/@Test@JunitPerfConfig(duration = 1000)public void helloWorldTest() throws InterruptedException {
    System.out.println("hello world");Thread.sleep(20);}}

再看一下 junit5 的写法:

public class HelloWorldTest {
    @JunitPerfConfig(duration = 1000)public void helloTest() throws InterruptedException {
    Thread.sleep(100);System.out.println("Hello Junit5");}}

JunitPerfRule 竟然神奇的消失了?这一切是怎么做到的呢?

让我们一起揭开 junit5 神秘的面纱。

Junit5 更加强大的特性

@JunitPerfConfig

我们只是指定了一个简单的 @JunitPerfConfig 注解,那么问题一定就出在这个注解里。

定义如下:

import java.lang.annotation.*;/*** 执行接口* 对于每一个测试方法的条件配置* @author bbhou* @version 1.0.0* @since 1.0.0*/
@Retention(RetentionPolicy.RUNTIME)
@Target({
    ElementType.ANNOTATION_TYPE, ElementType.METHOD})@ExtendWith(PerfConfigProvider.class)
@TestTemplate
public @interface JunitPerfConfig {
    // 属性省略}

@Retention@Target 属于 java 中的常规注解,此处不做赘述。

我们重点看一下剩余的两个注解。

@TestTemplate

我们以前在写单元测试的时候,都会写一个 @Test 注解,你会发现 junit5 中连这个注解都省略了。

那么,他去哪里了呢?

答案就是 @TestTemplate 声明的注解,就是用来标识这个方法是单元测试的方法,idea 也会认的,这一点非常的灵活强大。

@ExtendWith

这个注解,给我们的注解进行了赋能。

看名字,就是一个拓展,拓展的实现,就是我们指定的类 PerfConfigProvider

PerfConfigProvider

我们来看一下 PerfConfigProvider 的实现。

public class PerfConfigProvider implements TestTemplateInvocationContextProvider {
    @Overridepublic boolean supportsTestTemplate(ExtensionContext context) {
    return context.getTestMethod().filter(m -> AnnotationSupport.isAnnotated(m, JunitPerfConfig.class)).isPresent();}@Overridepublic Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext context) {
    return Stream.of(new PerfConfigContext(context));}}

实现非常简单,首先是一个过滤。

只有定义了 @JunitPerfConfig 注解的方法,才会生效。

下面就是我们自定义实现的上下文 PerfConfigContext。

PerfConfigContext

PerfConfigContext 实现了 TestTemplateInvocationContext,并且对原生的 ExtensionContext 进行了简单的封装。

public class PerfConfigContext implements TestTemplateInvocationContext {
    // 省略内部属性@Overridepublic List<Extension> getAdditionalExtensions() {
    return Collections.singletonList((TestInstancePostProcessor) (testInstance, context) -> {
    final Class clazz = testInstance.getClass();// Group test contexts by test classACTIVE_CONTEXTS.putIfAbsent(clazz, new ArrayList<>());EvaluationContext evaluationContext = new EvaluationContext(testInstance,method,DateUtil.getCurrentDateTimeStr());evaluationContext.loadConfig(perfConfig);evaluationContext.loadRequire(perfRequire);StatisticsCalculator statisticsCalculator = perfConfig.statistics().newInstance();Set<Reporter> reporterSet = getReporterSet();ACTIVE_CONTEXTS.get(clazz).add(evaluationContext);try {
    new PerformanceEvaluationStatement(evaluationContext,statisticsCalculator,reporterSet,ACTIVE_CONTEXTS.get(clazz),clazz).evaluate();} catch (Throwable throwable) {
    throw new JunitPerfRuntimeException(throwable);}});}
}

写到这里,我们就会发现又回到了和 junit4 相似的地方。

不明白的小伙伴可以去看一下原来的实现,这里不做赘述。

剩下的部分,和原来 junit4 的实现都是一致的。

小结

可以发现 junit5 为我们提供的拓展能力更加强大灵活,他可以让我们定义属于自己的注解。

这个注解用起来让用户和使用原有的 junit5 注解没有什么区别。

不得不感慨一句,长江后浪推前浪,前浪死在沙滩上。

参考资料

https://github.com/houbb/junitperf

https://github.com/junit-team/junit4/wiki/Rules

  相关解决方案