基于 junit5 实现 junitperf 源码分析
前言
上一节介绍了基于 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 源码分析的更多相关文章
- Django——基于类的视图源码分析 二
源码分析 抽象类和常用视图(base.py) 这个文件包含视图的顶级抽象类(View),基于模板的工具类(TemplateResponseMixin),模板视图(TemplateView)和重定向视图 ...
- SPI机制剖析——基于DriverManager+ServiceLoader的源码分析
我的上一篇博客类加载器与双亲委派中提到,SPI机制是一种上级类加载器调用下级类加载器的情形,因此会打破类加载的双亲委派模型.为了深入理解其中的细节,本博客详细剖析一下SPI机制,并以JDBC为例,基于 ...
- Django——基于类的视图源码分析 一
基于类的视图(Class-based view)是Django 1.3引入的新的视图编写方式,用于取代以前基于函数(Function-based)方式. 借助于OO和Python中方便的多重继承特性, ...
- Django——基于类的视图源码分析 三
列表类通用视图(list.py) 此文件包含用于显示数据列表常用的类和工具类.不仅可以方便的用于显示基于模型(Model)的数据列表,也可以用于显示自定义数据列表. 此图中绿色部分属于base.py, ...
- documentsUI源码分析
documentsUI源码分析 本文基于Android 6.0的源码,来分析documentsUI模块. 原本基于7.1源码看了两天,但是Android 7.1与6.0中documentsUI模块差异 ...
- Spark大师之路:广播变量(Broadcast)源码分析
概述 最近工作上忙死了……广播变量这一块其实早就看过了,一直没有贴出来. 本文基于Spark 1.0源码分析,主要探讨广播变量的初始化.创建.读取以及清除. 类关系 BroadcastManager类 ...
- 第八篇:Spark SQL Catalyst源码分析之UDF
/** Spark SQL源码分析系列文章*/ 在SQL的世界里,除了官方提供的常用的处理函数之外,一般都会提供可扩展的对外自定义函数接口,这已经成为一种事实的标准. 在前面Spark SQL源码分析 ...
- HashMap源码分析(一)
基于JDK1.7 HashMap源码分析 概述 HashMap是存放键值对的集合,数据结构如下: table被称为桶,大小(capacity)始终为2的幂,当发生扩容时,map容量扩大为两倍 Hash ...
- java集合源码分析(六):HashMap
概述 HashMap 是 Map 接口下一个线程不安全的,基于哈希表的实现类.由于他解决哈希冲突的方式是分离链表法,也就是拉链法,因此他的数据结构是数组+链表,在 JDK8 以后,当哈希冲突严重时,H ...
- docker 源码分析 一(基于1.8.2版本),docker daemon启动过程;
最近在研究golang,也学习一下比较火的开源项目docker的源代码,国内比较出名的docker源码分析是孙宏亮大牛写的一系列文章,但是基于的docker版本有点老:索性自己就git 了一下最新的代 ...
随机推荐
- Angular系列教程之生命周期钩子
.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...
- [转帖]【sql server安全】sql server连接加密,sql server SSL加密连接
https://www.cnblogs.com/gered/p/13595098.html#_label1_0 MSSQL - 最佳实践 - 使用SSL加密连接 回到顶部 author: 风移 回到顶 ...
- Grub2 内核启动参数总结
Grub2 内核启动参数总结 部分参数 biosdevname=0 net.ifnames=0 # 注意这个配置会修改网卡的名字, 比如之前是ens192 # 添加如上两个内容后就会变成 eth0 类 ...
- [转帖]关于虚拟化中cpu的指令集SSE 4.2的不支持
背景: 局域网中有两台服务器proxmox进行了虚拟化,跑一些测试应用.今天正好想要安装一下clickhouse跑一下.安装前准备: 测试服务器是否支持sse 4.2指令集-如下 [root@slav ...
- HotSpare 9361Raid卡热备盘的设置过程
HotSpare 9361Raid卡热备盘的设置过程 摘要 公司最近一批服务器到位(去年生产) 插满24盘位的 960G 的SSD 的超融合服务器. (硬盘是镁光的 !-_-!) 想着Raid6虽然数 ...
- buildkit ctr 与 k3s的简单学习
摘要 前面一部分学习了 buildkit的简单搭建 也学习会了如果build images的简单处理 但是搭建镜像只是万里长征第一步. 如何进行微服务部署,才是关键的第二步. 公司最近使用基于K3S的 ...
- 热更新适配ibatis原理浅析
一.热更新解决了什么问题? 在研发过程中,每个研发同学在联调.自测阶段中总会频繁的去执行编译.构建.打包的动作,遇到比较大的项目,执行一套流程下来,往往需要3-10分钟左右,极大的降低了研发的速度,基 ...
- 【代码分享】使用 avx512 + 查表法,优化凯撒加密
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 关于凯撒加密,具体请看:https://en.wikipe ...
- [P9253 [PA 2022] Ornitolog 2] 题解
题目 P9253 [PA 2022] Ornitolog 2 题目描述 给你一个长度为 \(n\) 的数列,求至少要修改多少个数才能让数列成为交替鹡鸰鸟鸣的音高序列. 思路 这道题有两种情况. 第一种 ...
- SqlSugar删除数据
1.根据实体删除 1.1 强类型实体 需要配置主键 ,根据主键删除需要给实体配置主键,参考文档实体配置 //单个实体 db.Deleteable<Student>(new Student( ...