问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

提出问题,解答问题!这才是理解代码设计的正确方法

发布网友 发布时间:2024-10-01 14:01

我来回答

1个回答

热心网友 时间:2024-12-13 18:35

上一篇我们通过调用关系,梳理出了TestRunner调用核心模型的流程。

本篇是《如何高效阅读源码》专题的第十一篇,我们来回答流程梳理中遇到的一些问题,思考为什么要这么设计。

上一篇我们提出了几个问题:

为什么使用Statement类?作用是什么?

RunNotifier如何进行监听的?

classBlock方法中,if判断里的逻辑是干什么用的呢?看方法名好像和BeforeClass、AfterClass注解有关系,它是怎么处理的呢?

为什么要用Statement封装一层来执行测试?所有的方法都在ParentRunner类里面,直接调用不就好了吗?

runChildren方法中为什么这里要构建一个Runnable来执行呢?

本节将来回答这些问题。

Statement的作用

其实,如果你熟悉设计模式,你应该能立刻认出来,Statement实现的是个命令模式。

?

首先childrenInvoker方法(见下图)直接构建了一个Statement的匿名实现类,来包装执行类里所有符合条件的测试方法。 接着通过if判定里的四个方法添加额外的执行逻辑。

?

限于篇幅,我们就只看第一个withBeforeClasses方法,看这个名字,我们应该能猜到这个方法是为了处理被BeforeClass注解的方法的。

在看它的实现之前,我们可以想想,如果是我们来实现的话?我们该怎么实现呢?或者我们可以换个问法,有没有什么方式能够保证一个方法在另一个方法之前执行?你有没有什么思路呢?(在向下看之前,最好自己先思考一下)

比如,我们可以使用一个Statement包装类,也就是使用装饰模式。在执行这个Statement之前,先执行BeforeClass;或者我们也可以使用组合模式,构造一个父Statement,BeforeClass和原来的Statement作为叶子节点,不过此处要注意顺序。

现在我们来看看JUnit里面是怎么实现的呢?

?

首先,通过TestClass对象的getAnnotatedMethods方法找到所有有BeforeClass注解的方法。如果没有对应注解的方法就直接返回原Statement,否则就构建一个RunBefores对象返回,很明显这个RunBefores也是Statement的子类。

我们来看这个RunBefores类是如何实现来保证具有BeforeClass注解的方法先于Test注解的方法执行的。

?

注意evaluate方法,首先先遍历执行了BeforeClass注解的方法,然后执行了测试方法Statement对象的evaluate方法。 显而易见,这里使用的是装饰模式。

装饰模式:动态地给一个对象添加一些额外的职责

也就是说,JUnit通过装饰模式动态的给测试方法添加了额外的职责。相信其它的方法不需要看你也能大概知道是怎么实现的了吧?

RunNotifier的作用

RunNotifier的实现就更加的显而易见了:观察者模式!

观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

使用观察者模式的作用就是解耦测试的执行与测试结果的展示。我们来看一下JUnit具体是怎么做的。

我们接着上面的childrenInvoker方法往下看,childrenInvoker里构建了一个Statement,实际调用的是ParentRunner里的runChildren方法。

?

这里为什么要用线程来执行呢?其实理由很简单,这里执行的是一个个的测试方法,每个测试方法之间是没有关系的,所以这里使用线程,可以提高测试的执行效率。

注意:虽然每个测试方法是独立的,但是结果Listener是公用的,那这里就涉及到了竞争问题。JUnit是如何保证线程安全的呢?这里留给大家去源码里查找答案。提个醒,先了解下CopyOnWriteArrayList

线程方法里执行的是runChild方法,而这是一个抽象方法,由子类实现。它有两个实现类,一个是BlockJUnit4ClassRunner类,一个是Suite类,很明显Suite是用来执行一批测试方法的。这个关系是组合模式的套路!Suite和BlockJunit4ClassRunner之间使用的肯定是组合模式。如果不信可自行验证,这里就不再梳理了。

我们这里直接看BlockJUnit4ClassRunner的runChild方法。

?

注意其中的methodBlock方法,回想一下上面的classBlock方法,能猜出来这里的逻辑吗? 最后到runLeaf方法,也就是最终执行的方法,我们来看notifier具体做了哪些工作。

?

这里相当于对statement执行的开始、结束和报错阶段进行了监听,调用了不同的方法。而这些方法,最终委托到了注册到TestNotifier的TestListener了。比如addFailure方法,最终调用的是TestListener的testFailure方法。

现在我们只要看一看哪些类继承了TestListener类,就能知道测试结果有哪些处理方式了。(后文会从此处将整个执行流程串联起来) 我们以最简单的TextListener为例。

?

可以看到,这里只是简单的将其输出到命令行。 如果你想要其它的结果处理方式,你只需要编写一个类实现TestListener类即可。 我们反过来想一下,如果不使用*模式,这里的测试执行和结果处理是否就耦合到了一起,且没有扩展性呢?

总结

在本文中,为了回答上文提出来的问题,我们对核心代码流程进行了代码级别的梳理,并理解了为什么要这么设计,如果不这么设计又会带来什么问题。

同时,你应该也体会到了,熟悉设计模式能极大的提高阅读源码的效率。假设你不了解设计模式,你就需要先理出类之间的关系,比如上面的RunNotifier和TestListener之间的关系,然后思考为什么要这么设计,同时可以到网上找资料确认这两者的关系,以学习观察者模式。当下次再看到类似结构的时候,能快速的理清逻辑。

下文我们将结合Spring来梳理JUnit的Runner,完成整个测试流程的最后一块拼图。

原文:https://juejin.cn/post/7097413454494957599

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
windows8怎么本地连接 windows8如何设置网络 诸葛亮故里诸葛亮故里纪念馆 临沂诸葛亮文化旅游节历届介绍 第四届诸葛亮文化旅游节纪念诞辰 ...请根据该表回答下面问题: (1)表中A、B、C分 ...请你分析样品A、B、C中代表血浆、原尿和尿液的样品分别是... c糖蛋白化验 江诗丹顿金属手表(江诗丹顿的手表女款) 定位最好的手表? 表带上的圈叫什么 ...考试科目代码,比如308,309之类的,是什么意思?我只是举个例子,希望... 急!哪位亲会VC,可以帮我解释下面的代码是什么意思吗?我想要具体点的(这... 格力KFR-26GW/(26556)FNDe-3其他 ...变频3KFR-35GW/(35559)FNhAb-A3(含管)顶(清爽白)有什么功能亮点... 床垫是棕垫,还是席梦思垫好, 棕垫好还是席梦思好 棕垫什么牌子好 齐鲁人才网上的企业都经过有关部门的审核了吗 如何在iphone上下载网页上的视频和音乐? 老公是外地农村户口,怎样才能在北京上保险? 外地人在北京市没工作单位。个人能否自己交社保 户籍外地女一直在北京挂靠单位自己交社保,到50岁缴纳11年,剩余几年是... 外地农村户口在京从事自由职业此前未缴纳过社保,能自己交社保吗? 洛阳邙山拘留所管饭免费吗 一个火力厂里有煤重4030千克,合多少吨;这堆煤烧84小时,合多少天? 请问联通手机,能接听记录电话吗?在手机通话和别人吵架了,但是我旁边... 我的手机有自动应答功能,如果朋友来了电话,并给我留了录音。请问... 镁对孕妇的作用 孕期补镁的食物有哪些? 下列饮食习惯正确的是( ) A.吃菠菜时,和豆腐同食,可增强对钙的吸收 B... ...其中正确的是( )A.带足大米以免在外国饮食不习惯B.戴顶帽子,以_百 ... 0是整数吗?如果是 是为什么呢 安卓手机可以实现控制电脑包括开关机吗远距离 ...是从那天算起?然后我是包了三个月。请问什么时候到期 我在9月1日开通的电信宽带,但是发票上写是8月29日,费用是几月份算起... 我的电信宽带是10月份到期,但现在九月份刚到就欠费停号了,充了10元钱... 我家开通中国电信天翼宽带,开通1年,今年2月份开通的,可是现在才8月,他... 小米充电宝被连续摔了两次,对机体伤害大吗?还能像原来一样吗? 税务局代开增值税专用发票能作废吗 电子税务局代开专票代开好了,第二个月取票会不会有影响 30号电子税务局代开的专票到下个月一号取会有影响吗 代开的发票取票期限 税务局开的专票怎么作废 华中师范大学2022年湖北普通本科录取分数一览表 越剧《孔雀东南飞》剧情简介 孔雀东南飞分集剧情 高级时间相关单光子计数技术基本信息 越南芽庄亲子游攻略6日游 芽庄亲子游需要带什么 为什么Excel2010中选择部分单元格后就无法动了? 《风雨送春归》讲了什么故事?为何形象会固化呢? 佳士得上海:当相机成为主流,为何艺术家还坚持画肖像?我们用四张画回应...