前言

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

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

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

拓展阅读:

浅谈性能测试

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

没有对比,就没有伤害

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

public class HelloWorldTest {

    @Rule
public 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 {

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

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

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

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

PerfConfigContext

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

public class PerfConfigContext implements TestTemplateInvocationContext {

    // 省略内部属性

    @Override
public List<Extension> getAdditionalExtensions() {
return Collections.singletonList(
(TestInstancePostProcessor) (testInstance, context) -> {
final Class clazz = testInstance.getClass();
// Group test contexts by test class
ACTIVE_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

基于 junit5 实现 junitperf 源码分析的更多相关文章

  1. Django——基于类的视图源码分析 二

    源码分析 抽象类和常用视图(base.py) 这个文件包含视图的顶级抽象类(View),基于模板的工具类(TemplateResponseMixin),模板视图(TemplateView)和重定向视图 ...

  2. SPI机制剖析——基于DriverManager+ServiceLoader的源码分析

    我的上一篇博客类加载器与双亲委派中提到,SPI机制是一种上级类加载器调用下级类加载器的情形,因此会打破类加载的双亲委派模型.为了深入理解其中的细节,本博客详细剖析一下SPI机制,并以JDBC为例,基于 ...

  3. Django——基于类的视图源码分析 一

    基于类的视图(Class-based view)是Django 1.3引入的新的视图编写方式,用于取代以前基于函数(Function-based)方式. 借助于OO和Python中方便的多重继承特性, ...

  4. Django——基于类的视图源码分析 三

    列表类通用视图(list.py) 此文件包含用于显示数据列表常用的类和工具类.不仅可以方便的用于显示基于模型(Model)的数据列表,也可以用于显示自定义数据列表. 此图中绿色部分属于base.py, ...

  5. documentsUI源码分析

    documentsUI源码分析 本文基于Android 6.0的源码,来分析documentsUI模块. 原本基于7.1源码看了两天,但是Android 7.1与6.0中documentsUI模块差异 ...

  6. Spark大师之路:广播变量(Broadcast)源码分析

    概述 最近工作上忙死了……广播变量这一块其实早就看过了,一直没有贴出来. 本文基于Spark 1.0源码分析,主要探讨广播变量的初始化.创建.读取以及清除. 类关系 BroadcastManager类 ...

  7. 第八篇:Spark SQL Catalyst源码分析之UDF

    /** Spark SQL源码分析系列文章*/ 在SQL的世界里,除了官方提供的常用的处理函数之外,一般都会提供可扩展的对外自定义函数接口,这已经成为一种事实的标准. 在前面Spark SQL源码分析 ...

  8. HashMap源码分析(一)

    基于JDK1.7 HashMap源码分析 概述 HashMap是存放键值对的集合,数据结构如下: table被称为桶,大小(capacity)始终为2的幂,当发生扩容时,map容量扩大为两倍 Hash ...

  9. java集合源码分析(六):HashMap

    概述 HashMap 是 Map 接口下一个线程不安全的,基于哈希表的实现类.由于他解决哈希冲突的方式是分离链表法,也就是拉链法,因此他的数据结构是数组+链表,在 JDK8 以后,当哈希冲突严重时,H ...

  10. docker 源码分析 一(基于1.8.2版本),docker daemon启动过程;

    最近在研究golang,也学习一下比较火的开源项目docker的源代码,国内比较出名的docker源码分析是孙宏亮大牛写的一系列文章,但是基于的docker版本有点老:索性自己就git 了一下最新的代 ...

随机推荐

  1. .NET 5 开发WPF - 美食应用登录UI设计

    Demo演示: 你的时间宝贵,不想看啰嗦的文字,可直接拉到文末下载源码! 1. 新建项目 站长开发环境: VS 2019企业版 16.70 .NET 5 Preview 5 .NET 5 WPF 项目 ...

  2. [kubernetes]安装dashboard

    前言 kubernetes官方文档中的web UI网页管理工具是kubernetes-dashboard,可提供部署应用.资源对象管理.容器日志查询.系统监控等常用的集群管理功能.为了在页面上显示系统 ...

  3. [转帖]第24/24周 数据库维护(Database Maintenance)

    https://www.cnblogs.com/woodytu/p/4795542.html 哇哦,光阴似箭!欢迎回到性能调优培训的最后一期.今天我会详细讲下SQL Server里的数据库维护,尤其是 ...

  4. [转帖]十步解析awr报告

    http://www.zhaibibei.cn/awr/1.1/ 从这期开始讲解awr报告的部分,首先讲解awr整体的部分 后续会针对不同的点进行讲解 1. 数据库细节 这部分可以看到 数据库的版本 ...

  5. [转帖]nginx 反向代理 URL替换方案

    nginx 提供反向代理服务,日常开发过程中有时候我们需要使用nginx 作为代理服务根据url的不同去访问不同的服务器或者不同端口,如下提供两种方案. 1.直接替换location  匹配部分 1. ...

  6. Springboot 使用nacos鉴权的简单步骤

    Springboot 使用nacos鉴权的简单步骤 背景 前端时间nacos爆出了漏洞. 因为他的默认token固定,容易被利用. 具体的问题为: QVD-2023-6271 漏洞描述:开源服务管理平 ...

  7. [转帖]mvcc多版本并发控制的原理

      https://baijiahao.baidu.com/s?id=1751185558149315946 MVCC多版本并发控制的原理:通过undo_log多版本链条,加上开启事务时产生的read ...

  8. windwos10任务栏居中

    如下操作 新建一个文件夹如图 然后出现这个重右往左一直拖然后拉出来就行了如图 拖不动或者没有的把这个关了-锁定任务栏 文字如何隐藏? 在这个文字旁边右击关闭标题即可 然后锁定任务栏就OK了

  9. python中可变参数与装饰器的例子

    python的可变参数 方法定义 #*args是可以传list类型的可变参数,**kwargs是可以传dict的可变参数 def wrapper(*args, **kwargs): 使用示例 def ...

  10. Vue双向数据绑定原理-中

    defineProperty方法 defineProperty除了可以动态修改/新增对象的属性以外, 还可以在修改/新增的时候给该属性添加get/set方法, 从而实现数据劫持. defineProp ...