设计模式之美
王争
前 Google 工程师,《数据结构与算法之美》专栏作者
123425 人已学习
新⼈⾸单¥98
登录后,你可以任选6讲全文学习
课程目录
已完结/共 113 讲
设计模式与范式:行为型 (18讲)
设计模式之美
15
15
1.0x
00:00/00:00
登录|注册

28 | 理论二:为了保证重构不出错,有哪些非常能落地的技术手段?

2. 设计完备的单元测试用例
1. 项目中的单元测试情况及遇到的问题和解决方法
团队没有建立对单元测试正确的认识,觉得可有可无
国内研发偏向“快、糙、猛”,容易因为开发进度紧,导致单元测试的执行虎头蛇尾
写单元测试比较繁琐,技术挑战不大,很多程序员不愿意去写
正确的认知:写单元测试并不是太耗时,覆盖率不是唯一标准
利用单元测试框架简化测试代码的编写
针对代码设计各种测试用例,覆盖各种输入、异常、边界情况
是TDD可落地执行的改进方案
帮助快速熟悉代码
对集成测试的有力补充
有效发现代码中的bug和代码设计上的问题
与集成测试相比,测试粒度更小
测试对象是类或函数,测试代码的逻辑执行
由研发工程师自己编写,用于测试自己编写的代码的正确性
课堂讨论
单元测试为何难落地执行?
如何编写单元测试?
为什么要写单元测试?
什么是单元测试?
为了保证重构不出错,有哪些非常能落地的技术手段?

该思维导图由 AI 生成,仅供参考

上一节课中,我们对“为什么要重构、到底重构什么、什么时候重构、该如何重构”,做了概括性介绍,强调了重构的重要性,希望你建立持续重构意识,将重构作为开发的一部分来执行。
据我了解,很多程序员对重构这种做法还是非常认同的,面对项目中的烂代码,也想重构一下,但又担心重构之后出问题,出力不讨好。确实,如果你要重构的代码是别的同事开发的,你不是特别熟悉,在没有任何保障的情况下,重构引入 bug 的风险还是很大的。
那如何保证重构不出错呢?你需要熟练掌握各种设计原则、思想、模式,还需要对所重构的业务和代码有足够的了解。除了这些个人能力因素之外,最可落地执行、最有效的保证重构不出错的手段应该就是单元测试(Unit Testing)了。当重构完成之后,如果新的代码仍然能通过单元测试,那就说明代码原有逻辑的正确性未被破坏,原有的外部可见行为未变,符合上一节课中我们对重构的定义。
那今天我们就来学习一下单元测试。今天的内容主要包含这样几个内容:
什么是单元测试?
为什么要写单元测试?
如何编写单元测试?
如何在团队中推行单元测试?
话不多说,让我们现在就开始今天的学习吧!

什么是单元测试?

单元测试由研发工程师自己来编写,用来测试自己写的代码的正确性。我们常常将它跟集成测试放到一块来对比。单元测试相对于集成测试(Integration Testing)来说,测试的粒度更小一些。集成测试的测试对象是整个系统或者某个功能模块,比如测试用户注册、登录功能是否正常,是一种端到端(end to end)的测试。而单元测试的测试对象是类或者函数,用来测试一个类和函数是否都按照预期的逻辑执行。这是代码层级的测试。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

单元测试在软件开发中的重要性不言而喻。本文深入探讨了单元测试的概念、编写方法以及其对代码质量提升的重要作用。文章指出,单元测试不仅能有效发现代码中的bug,还能帮助发现代码设计上的问题,是对集成测试的有力补充。此外,单元测试的编写过程本身也是代码重构的过程,能够帮助发现设计和实现过程中的问题,促进代码质量的提升。作者还分享了关于如何编写单元测试的经验总结,包括写单元测试的耗时、代码质量要求、覆盖率、选择单元测试框架等方面的见解。文章强调了单元测试在保证重构不出错方面的重要性和价值,为读者提供了深入了解单元测试的重要性和实践方法的指导。文章还探讨了单元测试难以落地执行的原因,包括写单元测试的繁琐性、团队对单元测试认知的不足以及项目开发进度紧张等问题。最后,文章提出了两个课堂讨论话题,引导读者思考和分享在项目中实施单元测试的挑战以及设计完备的单元测试用例。整体而言,本文全面阐述了单元测试的重要性、编写方法以及实施难点,对于软件开发人员具有重要的指导意义。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《设计模式之美》
新⼈⾸单¥98
立即购买
登录 后留言

全部留言(132)

  • 最新
  • 精选
  • potato00fa
    单元测试很重要,但是为什么大多人都会放弃?我个人觉得最主要的原因并不是代码量大,难以编写等,而是跑单元测试的次数少。很多单元测试都是为了写而写,写完一次可能都不去运行或者只偶尔运行一两次。如果是每次改完代码,都跑一遍单元测试,单元测试的效果会越来越显现。如果只是为了运行一两次或者干脆为了写而写,很容易就会放弃继续写单元测试。

    作者回复: 可以集成到代码管理仓库git中,强制跑单元测试成功之后才能提交

    2020-01-07
    47
  • 之前公司要求新研的代码要达到百分之85的覆盖率,导致纯粹为了覆盖率堆砌了一堆单元用例。有没有单元测试写的比较好的开源框架推荐下?

    作者回复: 哈哈,那就看我的项目啊:https://github.com/wangzheng0822 下面有个ratelimiter4j

    2020-01-06
    4
    43
  • 刘大明
    说起来真的是难受。整个项目中就我一个人写单元测试。每次做的功能都有单元测试覆盖。而且项目中junit包都是我导入的。更加奇葩的是我的功能单元测试领导还不让我提交。说是你的测试代码为什么要提交,我瞬间无语了。

    作者回复: 😂 可以考虑跳槽了

    2020-01-06
    10
    32
  • 拙言
    打卡~ 这里问下王争老师,如果到了具体的业务代码,该怎么写单元测试呢,单元测试正确标准是什么呢,以sql查询到的结果吗?

    作者回复: 涉及到数据库的项目,特别是重度依赖数据库的,确实比较难写单元测试。一种方式使用DBUNIT这样的测试框架来解耦合真正的数据库,另一种方式专门维护一个供单元测试用的数据库。

    2020-01-06
    7
    30
  • yaomon
    程序员这一行业本该是智力密集型的,但现在很多公司把它搞成劳动密集型的,包括一些大厂,在开发过程中,既没有单元测试,也没有 Code Review 流程。即便有,做的也是差强人意。 ---------------------------------------------------------------------------------------- 差强人意:指尚能使人满意。根据文章上文,明显是不能使人满意的意思。处理为语病。

    编辑回复: 差强人意是勉强使人满意,不是十分使人满意。所以这里没问题呢~

    2020-01-06
    12
    15
  • Frank
    以前在开发中,没有写单元测试的意识。开发完功能后,直接去测试一个完整的流程。即前端发请求,服务端处理,看数据库数据。如果功能正确就过。这是从一个功能宏观去考虑测试。而单元测试是更细粒度的测试,它在保证各个“单元”都测试通过的情况下整个功能模块就测试通过了。这样的方式对于我们自己来说对代码可控粒度更细。更能比较清楚的理解某个“单元”在整个功能模块调用链路上的位置,承担什么职责,以及有什么行为。而不是一开始就站在模块宏观角度来思考。通过一个个单元测试的编写,将整个功能模块串联起来,最终达到整个功能模块的全局认知。 这也体现了任务分解的思想。通过单元测试,可以从另外一方面实现对已编写的代码的CodeReview,重新梳理流程。也为以后有重构需求打下基础。 目前参与的项目中有单元测试,但是不够完备。可能由于某些原因(开发人员意识问题,团队对单元测试的执行落地程度不够等)。在写单元测试的过程中,遇到单元测试依赖数据库查询问题,因为存在多套环境,如开发环境,仿真环境,线上环境。对于依赖数据查询的单元测试,只能自己造假数据来解决。不知道还有什么好的解决办法。

    作者回复: 涉及到数据库的确实比较难写单元测试,而且如果重度依赖数据库,业务逻辑又不复杂,单元测试确实没有太大意义。这个时候,集成测试可能更有意义些。

    2020-01-06
    6
    11
  • 逍遥思
    独立开发者,项目代码量 10W 行以内,在可以预见的未来不会超过 20W 行 以前试过 git 各种最佳实践,最后发现一个分支基本就够用了 所以还是忍不住想问问老师,如果项目真没那么大,是否需要单元测试?

    作者回复: 需要的,这个跟项目大不大没太多关系的。单元测试还是为了保证代码少些低级bug

    2020-01-06
    12
    7
  • 小晏子
    参与的项目都有单元测试,不过有些不够完备,缺少了一些corner case的覆盖,感觉后面要注意加上。遇到的一个问题是对于repository层(数据访问层)的测试,用了一个取巧的办法解决的,因为要依赖数据库,可是又没找到对应数据库的mock方式,所以使用了docker镜像的方式来做的,感觉也不错,避免了构造数据的麻烦。不知道还有没有更好的办法?

    作者回复: DBunit了解一下~

    2020-01-06
    8
    6
  • FIGNT
    争哥。马上过年了,过年期间不知道能否多发表几篇在过年期间学习?

    编辑回复: 春节期间正常发布,惊喜待定😂

    2020-01-07
    5
  • 番茄炒西红柿
    问一下单元测试中的依赖问题只能用mock来模拟吗?这样不会导致对下层方法依赖太强,而且用mock模拟感觉代码量也很多,心里感觉也不一定对。如果加入依赖(先倒入测试数据),那不就变成集成测试了吗?

    作者回复: 解耦依赖目前来看就只能用mock的方式。这是跟集成测试最大的区别。

    2020-01-08
    3
    2
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部