当前位置: 首页 > news >正文

【JUnit实战3_05】第三章:JUnit 的体系结构(上)

JUnit in Action, Third Edition

《JUnit in Action》全新第3版封面截图

写在前面
继上一章大致了解 JUnit 5 提供的新功能、新特性后,这一章又从框架层面探讨了 JUnit 经历的版本演进过程。这也是往往在大部头的技术类资料中才会见到的“养料”。初学者往往对快速入门的小册子心动不已,对 500 页以上的硬骨头退避三舍,甚至不惜反复找很多本小册子来巩固所学。殊不知想要深耕一门技术,除了充分理解其中的技术特性外,更要熟悉这些新功能诞生时的历史背景和使命。任何特性的引入都不是毫无征兆的,而往往是为了解决当时的某个或某类痛点问题而生的。初学者经常对炒得天花乱坠的热门新词和层出不穷的新技术倍感压力,其中部分原因就是只看到了新技术的多和快,却鲜有对背后的强大推力和技术演进的本质规律有一个冷静客观的把握。本章探讨 JUnit 架构所经历的版本更迭过程,恰巧可以作为了解上述底层逻辑的绝佳案例。

文章目录

  • 第三章 JUnit 的体系结构(上)
    • 3.1 软件架构的概念
    • 3.2 架构演进要素之——轻量化
    • 3.3 架构演进要素之——模块化
    • 3.4 JUnit 4 的架构特点

第三章 JUnit 的体系结构(上)

Architecture is the stuff that’s hard to change later. And there should be as little of that stuff as possible.
架构是那些日后难以变更的部分,应当尽可能减少这类内容。

—— Martin Fowler

本章介绍与 JUnit 架构相关的知识点,从 JUnit 4 的架构特点切入,再讨论旧版架构存在的问题以及新版 JUnit 5 重点关注的部分,让读者对 JUnit 的架构特点及演进过程有一个大致的了解。

3.1 软件架构的概念

Fig3.1

如图所示,软件架构的概念类似建筑物的体系结构,刻画了架构在整栋建筑物中的基础性地位。软件架构本身通常难以移动和替换,类似建筑物的底座;位于中间的各个部件则代表具体的设计层(design);最顶部则代表软件的惯用模式(idiom)。虽然底座难以整体移动和替换,构建底座的架构元素反倒应该具备一定的灵活性且易于更换。JUnit 4JUnit 5 的架构演进过程完美诠释了这一观点。

3.2 架构演进要素之——轻量化

Fig3.2

为了形象说明轻量化在架构演进中的作用,书中讲述了一个电话簿的故事。面对两家供应商生产的同等价位、同等规格的电话簿,公司采购最终的策略是优先考虑更小巧轻便的那家供应商,因为同等情况下更小巧的尺寸意味着更高的信息密度;从使用习惯来考虑,人们也更愿意优先取用小巧便捷的电话簿。JUnit 5 也遵循了轻量化的原则。

3.3 架构演进要素之——模块化

Fig3.3

相比之下,模块化的案例则略显生硬:一个运动鞋制造商为了降低生产成本将产地迁到低成本地区,面对当地频繁的新鞋失窃,决策层最终决定将左右脚的鞋子分开生产,从而节省了雇佣保安的额外费用。真正的模块化带来的核心价值在于 灵活性、可复用性和效率的提升,而不是解决“防盗”这种风马牛不相及的问题。

要说明模块化带来的好处,可以类比传统咖啡和定制咖啡之间的差异:旧模式下,每一款咖啡新品都像一个大包大揽的函数,里面包含了制作新咖啡的所有步骤,存在的问题主要是效率低下,点单的灵活性较差,库存管理复杂,同时存在创新瓶颈。采用定制模式后,将一杯咖啡解构为 基础模块 + 组装规则模块,例如确立几个独立的基础模块:

  1. 基底模块:意式浓缩、茶汤
  2. 奶制品模块:纯牛奶、燕麦奶、厚椰乳
  3. 风味模块:香草糖浆、焦糖糖浆、抹茶粉、巧克力酱
  4. 顶料模块:奶泡、肉桂粉

以及几个组合规则:

  • 一个杯型(如中杯)默认包含1 份 基底和 1 份 风味。
  • 更换奶制品或额外增加风味/顶料需要 额外付费
  • 所有模块通过 搅拌和融合 这个标准动作来连接。

这样一来,生产效率不仅因模块化大幅提升,同时也贴合了用户的多样化选择,库存管理上也可以精细到某个模块的开销,既优化采购环节,又减少了浪费。

最重要的是通过将复杂系统(整个菜单)拆分为可复用、可互换的模块,最终实现了 效率、灵活性和可扩展性 的飞跃。

3.4 JUnit 4 的架构特点

探讨旧版 JUnit 4 的架构有助于更好地理解和使用 JUnit 5,同时也为了兼顾当前大量基于 JUnit 4 构建的测试代码。

旧版 JUnit 发布于 2006 年,当时采用了笼统的单体架构,所有功能都集合在一个 jar 文件内,使用时只需在 classpath 下添加该文件即可。

所谓成也萧何败也萧何,当初 JUnit 4 作为亮点的架构设计反而成了进一步演进的缺陷,并最终催生了 JUnit 5 的问世。

主要体现在以下三个方面:

  • 模块化设计:单体设计致使可扩展性不足。
  • runner 测试运行器:JUnit 4 自带的解决功能扩展问题的方案之一,通过添加 @RunWith 注解并传入自定义的 runner 运行器类,间接实现 JUnit 4 的功能扩展。该自定义类须实现 JUnit 4 的抽象 org.junit.runner.Runner 类,并重写继承的 getDescription() 方法和 run() 方法。具体处理逻辑主要利用了 Java 的反射机制来实现。
  • rules 测试规则的设计:JUnit 4 提供了另一种扩展方案,须实现接口 org.junit.rules.TestRule 并重写其 apply() 方法,然后在利用 @Rule 注解注入目标测试类。底层逻辑依然是 Java 反射机制。

因为反射机制破坏了 OOP 编程的封装原则,但书中并未展开解释,这里有必要补充说明。运行基于反射机制编写的 JUnit 4 测试代码,使得开发者可以绕开公共接口,直接窥探目标类或方法的私有状态。尤其是代码中直接设置 method.setAccessible(true) 的操作,相当于直接告诉 JVM 无视 private 这些修饰符,可以随便调用设计者限定的内部逻辑。一旦内部实现发生变更,即便公共接口不受影响,测试代码的运行也会立即失败,无形中推高了运维成本,也使得测试代码变得更加脆弱。

此外,测试方法在 JUnit 4 中还必须声明为 public 公有方法,并且方法名还必须满足特定的命名规则(testXYZ)才能被反射机制成功识别,给人一种 测试代码并不是为了表达测试意图而书写、倒更像是为了满足框架的反射调用需求而书写 的本末倒置的感觉。

最后一个致命缺陷才是书中说的,JUnit 4 只考虑了开发者的测试体验,却忽视了流行的代码工具对集成测试框架迫切需求。主流 IDE 工具和代码构建工具想要集成 JUnit 不得不深入框架内部,只能利用反射机制来访问受保护的私有类、方法或成员变量,不得不让这些工具与 JUnit 深度绑定,为后续升级带来巨大阻力,市场亟盼更轻量的基于模块化设计的全新测试框架,于是 JUnit 5 应运而生。

(上篇完)

http://www.dtcms.com/a/513004.html

相关文章:

  • Oracle 打补丁指南
  • 蓝奥声智能插座:从“用电计量”到“设备健康预测”的跨越
  • 网站域名到期广东网站建站公司
  • 林地变化检测技术拆解:基于语义分割的双时相卫星影像比对实现方案
  • 网站建设明细报价表 xlsiis发布网站的教程
  • Vue3 大文件上传实战:切片上传 / 断点续传 / 秒传 / 暂停恢复 / 全局并发控制
  • Qt qmlplugindump浅谈
  • 网站后台登陆代码表白网站制作源码
  • 广告设计用到的软件福州网站seo优化公司
  • 微分运算电路(波形转换电路)
  • 阿里云网站目录建立网站得多少钱
  • (二)React开发环境搭建与目录结构分析(零基础友好)
  • wordpress取消评论审核南京seo公司教程
  • 时间敏感网络(TSN)
  • 三轴云台之多算法协同技术篇
  • 深圳html5网站建设价格用记事本做电影介绍的网站
  • 延吉网站建设多少钱江苏泰州海陵区建设局网站
  • 建站行业的发展前景做个淘宝客网站怎么做
  • 建站哪家好 discuz网页设计专业设计课程
  • 站长工具 网站改版怎么建设公益网站
  • face_recognition :一个 “开箱即用” 的人脸识别工具
  • 赣州培训学做网站自己做电影下载网站
  • 如何建立自己的企业网站无锡网站建设套餐
  • 天水做网站的如何选择镇江网站优化
  • 网站开发时遇到的问题php建网站
  • 网站怎么做运营推广公司装修合同模板
  • 数据结构八大排序:堆排序-从二叉树到堆排序实现
  • 四川建设厅的网站线上推广招聘
  • 网站设计贵不贵常州网站建设方案策划
  • STM32 USART框图简介