您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
Being Agile 单元测试认知篇
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
Being Agile 单元测试认知篇
自猿其说Tech
2021-01-25
IP归属:未知
260240浏览
敏捷测试
业务敏捷
计算机编程
#### 前言 - 不做完整回归测试就不敢上线; - 回归时间太长,业务、产品、测试、研发各个都要陪着; - 明明没有改动,但还是出了BUG; - …… 这些痛苦都在告诉你:自动化测试是必然选择,而单元测试必然中的必然。因为单元测试是一切测试的基础,长远看,研发投入成本最低,反馈最快。 <center>**自动化测试金字塔**</center> <center>![](//img1.jcloudcs.com/developer.jdcloud.com/ce735b99-7289-4a68-886f-44bf8053d5c320210118155331.jpg)</center> #### 一、什么是单元测试? ##### 1. 什么是单元? 了解什么是单元测试之前,我们有必要先对“单元”在团队范围内有一个共识的概念,这个“单元”的概念对于我们单元测试粒度的选择至关重要;我们实际开发过程中一个服务、组件、工具方法都可以作为单元,一个理想化的“单元”应该有以下特性: - 最基本的特性:可测试性(Testable); - 有明确的单一职责(Single Responsibility),接收输入,经过处理,得到预期结果; - 以某一目的进行组合的整体,方法(Method)是单元中的最小单位; - 一个相对独立(Independent),没有过多外部依赖的逻辑单元。 ##### 2. 什么是单元测试? 单元测试是对一个独立工作单元行为的正确性进行检验的工作,是一段自动化的代码,是可快速运行、快速响应的,基本是用单元测试框架编写的,只要产品代码不发生变化,单元测试的结果是稳定的;另外,单元测试在测试家族的定位中,属于基础级别,**由研发人员自己编写。** **对于团队来说,应先从业务系统的核心逻辑开始做起。** ##### 3. 什么不是单元测试? **① 跨边界的测试** - 单元测试背后的思想是,仅测试这个方法中的内容,测试失败时不希望必须穿过基层代码、数据库表或者第三方产品的文档去寻找可能的答案! - 当测试开始渗透到其他类、服务或系统时,此时测试便跨越了边界,失败时会很难找到缺陷的代码。 - 测试跨边界时还会产生另一个问题,当边界是一个共享资源时,如数据库。与团队的其他开发人员共享资源时,可能会污染他们的测试结果! **② 非独立的测试** - 如果发现所编写的测试对一件以上的事情进行了测试,就可能违反了“单一职责原则”。随着时间的推移,向类或方法种添加了更多的不恰当的功能后,这些测试可能会变的非常脆弱。诊断问题也将变得极具有挑战性。 #### 二、单元测试的好处 ![](//img1.jcloudcs.com/developer.jdcloud.com/4904c5e6-56e1-4d0f-85aa-040ce1861ebd20210118155656.png) #### 三、什么是好的单元测试用例 ##### 1. 可自动化的: 使用3A方法设计出来的测试用例,可以通过Junit等测试框架自动执行并自动验证结果符合预期。 - Arrange : 准备测试环境,测试数据 - Act : 执行被测方法,收集实际执行结果(actual value) - Assert : 验证实际执行结果是否与预期结果一致 ##### 2. 完整的: 要覆盖核心方法、核心方法分支、边界条件,异常情况,包括六个方面,统称为: **Right-BICEP:** - Right----结果是否正确? - B----是否所有的边界条件都是正确的? - I----能否检查一下反向关联? - C----能否用其它手段检查一下反向关联? - E----是否可以强制产生错误条件? - P----是否满足性能条件? **边界条件** 代码中的许多Bug经常出现在边界条件附近,我们对于边界条件的测试该如何考虑? - 一致性----值是否满足预期的格式 - 有序性----一组值是否满足预期的排序要求 - 区间性----值是否在一个合理的最大值最小值范围内 - 引用、耦合性----代码是否引用了一些不受代码本身直接控制的外部因素 - 存在性----值是否存在(例如:非Null,非零,存在于某个集合中) - 基数性----是否恰好具有足够的值 - 时间性----所有事情是否都按照顺序发生的?是否在正确的时间、是否及时 ##### 3. 可重复使用: 能够多次执行,并且得到相同的结果; ##### 4. 独立性:单一职责 一个测试用例覆盖一个场景,不依赖其他模块,不依赖执行顺序。 通过制作测试替身的方法,消除对其他模块的引用,专注于当前被测试的单元: - 通过 MOCK 框架隔离对其他模块/系统的依赖。 - 通过数据准备和清理事件消除测试用例之前的影响。 ##### 5. 专业性: 实现代码的规则,也适合于测试代码,符合SRP 单一职责原则, DRY原则: - 避免随机结果 - 尽量避免断言时间的结果 - 避免测试中的逻辑,即不该包含if、switch、for、while等 - 不要保护起来,try…catch…,出现异常直接导致用例失败即可 - 少用sleep,延缓测试时长的行为都是不健康的 - 准确易读的用例命名:如Test+被测函数名+condition+result #### 四、单元测试的框架四、单元测试的框架 ##### JUnit 是一个Java语言的单元测试框架。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。Junit是一套框架,继承TestCase类,就可以用Junit进行自动测试了。 ##### TestNG(Next Generation) 比JUnit单元测试框架更强大,它提供了更多的扩展功能,可以通过注解、分组、序列和参数化组织和执行自动化测试脚本,因此它适合运行更复杂的自动化测试用例。 TestNG的优点: - 漂亮的HTML格式测试报告 - 支持并发测试 - 参数化测试更简单 - 支持输出日志 - 支持更多功能的注解 ##### Mockito 可以创建和配置mock对象.使用Mockito简化了具有外部依赖的类的测试开发。 ##### PowerMock 是Mockito的一种增强,PowerMock可以调用Mockito的方法,但是对于Mocktio不能Mock的对象或者方法,我们可以使用PowerMock来实现。比如Mockito不能用于static Method, final method, 枚举类, private method,这些我们都可以用powermock来实现,当Powermock和mockito结合使用的时候,我们需要考虑兼容性的问题。两者的版本需要兼容。 ##### UnitTest 自研可视化单元测试组件,屏蔽过程中复杂的方法调用,mock处理,结果对比。让用户聚焦入参构造以及出参的预测。 接入地址:https://cf.jd.com/pages/viewpage.action?pageId=141215859 常规的方式,我们一个测试用例,大部分精力是花在构造入参以及结果对比上了。另外,过程服务的mock也浪费很大的精力。 该组件可以帮我们自动识别出、入参结构,已经过程服务的mock过程,我们只要关心入参以及结果预测就好了。 ##### 五、单元测试示例 代码样例: https://git.jd.com/braveclub/unit-test-demo 欢迎clone! 欢迎贡献! **——基本场景** https://git.jd.com/braveclub/unit-test-demo/blob/master/unittest-demo/src/test/java/com/jd/braveclub/DemoTest.java **——断言示例** https://git.jd.com/braveclub/unit-test-demo/blob/master/unittest-demo/src/test/java/com/jd/braveclub/asserts/AssertTest.java **——需要MOCK** https://git.jd.com/braveclub/unit-test-demo/blob/master/unittest-demo/src/test/java/com/jd/braveclub/service/IdentityServiceTest.java #### 六、老司机碎碎念 ##### 1) 对于老系统,我们怎么写单测,何时写单测 关于老系统由于各种历史原因,有的系统可能写了单测,但是跑不起来了,有的可能根本就没有写单元测试,还有就是之前的方法逻辑太深,不可测,这种情况下,我们也补不起单元测试。而且我们的开发排期也非常紧,没有时间写单元测试啊。 但是,我们真的对自己写的代码那么自信吗?或者将工程启动然后通过JSF进行调用测试。这个时候我们会发现如果有单测是多么爽的事儿。 因此,对于老系统,**我们编写单测的原则是:随着需求走。循序渐进,坚决不一口吃个胖子。**当需求来了,需要改某个逻辑,那么我们就想办法针对本次修改的方法进行编写单测。 在进行逻辑方法进行单测时,我们可以借助Mockit将外部依赖进行屏蔽,确保我们单测是最小的粒度。 ##### 2)如何编写高效的单元测试呢? 上文中也提到,单测也要遵循软件设计思想、抽象、隔离原则,这需要我们对公共的代码逻辑进行抽象,对非必要的依赖进行隔离,来保证待测试方法的可测性。 聚焦本系统的业务逻辑:通过合理的使用Mock对象,将外部依赖进行隔离。如果依赖的方法为本系统的服务,那么应该有单独的单测对该服务进行测试覆盖。 使用测试工具类,避免重复造轮子达到快速单测已经聚焦业务。比如数据库常用的测试工具包DBUnit,随机对象生成器easy-random。Spring-test包中的ReflectionTestUtils工具对私有方法进行单测。 在数据层面,在单测前需要准备数据,为了避免依赖可以使用MariaDB来替换MySQL。embedded-elasticsear等来替换Elasticsearch。 ##### 3)对于C#代码的单元测试用例攻略 https://www.cnblogs.com/tianqing/p/12822936.html #### 七、如何度量单元测试效果 - 增量代码的单元测试的覆盖率:行覆盖率、类覆盖率、方法覆盖率; - 单函数圈复杂度,参考https://joyspace.jd.com/page/srRd63gIBscU_F9i2v4G,单函数代码行数(低于80) - 测试缺陷数 #### 八、单元测试推进节奏 - 会写,全员可写 - 写的好,同时关注程序设计的可测性问题 - 识别可测性问题,熟练使用重构方法进行重构;识别代码架构设计问题;测试用例与业务代码同步编写 - TDD,期望目标。 #### 感谢: **本文由俱乐部以下同学共同完成,希望更多同学加入进来!!!** - 中台技术:周仑、高鹏 - KA销售:王重阳 - 中台仓储:杨涛 - 中台配运:鞠万奎 - 运输平台:刘海鸣 - 国际研发:张豪堃 - 质量效能:宋宁 ------------ ###### Being Agile 京东物流技术发展部效能提升部 ###### 作者: 勇敢者俱乐部 ----------- 更多敏捷相关,推荐可与下方优秀作者聊一聊 ![](//img1.jcloudcs.com/developer.jdcloud.com/a90e1ffa-4240-46b6-9b73-34728eec73ca20210118160723.png)
原创文章,需联系作者,授权转载
上一篇:Being Agile!快坦白支援的时候都想了啥?
下一篇:【技术干货】企业级扫描平台EOS关于JS扫描落地与实践!
相关文章
前端DevOps流水线实践
Being Agile 单元测试认知篇
单元测试与重构
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
最新回复
丨
点赞排行
共0条评论
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号