一、前言

半年前在公司团队内推动单元测试的落地,略有一些心得,记录在此。如有不同观点或建议,请在评论区留言,一起探讨。

定义:单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。

单元测试从长期来看,可以提高代码质量,减少维护成本,降低重构难度。但是从短期来看,加大了工作量,对于进度紧张的项目中的开发人员来说,可能会成为不少的负担。

本文从为什么要写单元测试,何时写,写多细这些我们最关心的问题展开讨论,试图解答如何在进度紧张的项目中,通过写有效的单元测试来提高代码质量的问题。

二、单元测试要写多细

酷壳上有篇关于“单元测试要做多细”的文章,文章是从StackOverflow上的一个问题讨论开的。这个问题是–

“TDD需要花时间写测试,而我们一般多少会写一些代码,而第一个测试是测试我的构造函数有没有把这个类的变量都设置对了,这会不会太过分了?
那么,我们写单元测试的这个单元的粒度到底是什么样的?并且,是不是我们的测试测试得多了点?”

点赞最多的答案是–

老板为我的代码付报酬,而不是测试,所以,我对此的价值观是——测试越少越好,少到你对你的代码质量达到了某种自信(我觉得这种的自信标准应该要高于业内的标准,当然,这种自信也可能是种自大)。如果我的编码生涯中不会犯这种典型的错误(如:在构造函数中设了个错误的值),那我就不会测试它。我倾向于去对那些有意义的错误做测试,所以,我对一些比较复杂的条件逻辑会异常地小心。当在一个团队中,我会非常小心的测试那些会让团队容易出错的代码。

这个答案给人感觉对单元测试持一定的否定态度和不感冒态度,但是这一最佳答案的回答者是Kent Beck!正是那位极限编程、测试驱动开发和单元测试以及JUnit的创造者Kent Beck。Kent Beck的答案,正好回答了单元测试要写到什么程度这个问题。单元测试不是越多越好,而是越有效越好!进一步解读就是哪些代码需要有单元测试覆盖:
1. 逻辑复杂的
2. 容易出错的
3. 不易理解的,即使是自己过段时间也会遗忘的,看不懂自己的代码,单元测试代码有助于理解代码的功能和需求
4. 公共代码。比如自定义的所有http请求都会经过的拦截器;工具类等。
5. 核心业务代码。一个产品里最核心最有业务价值的代码应该要有较高的单元测试覆盖率。

三、何时写单元测试

写单元测试的时机不外乎三种情况:

(1)一是在具体实现代码之前,这是测试驱动开发(TDD)所提倡的;

(2)二是与具体实现代码同步进行。先写少量功能代码,紧接着写单元测试(重复这两个过程,直到完成功能代码开发)。其实这种方案跟第一种已经很接近,基本上功能代码开发完,单元测试也差不多完成了。

(3)三是编写完功能代码再写单元测试。我的实践经验告诉我,事后编写的单元测试“粒度”都比较粗。对同样的功能代码,采取前两种方案的结果可能是用10个“小”的单测来覆盖,每个单测比较简单易懂,可读性可维护性都比较好(重构时单测的改动不大);而第三种方案写的单测,往往是用1个“大”的单测来覆盖,这个单测逻辑就比较复杂,因为它要测的东西很多,可读性可维护性就比较差。

建议:我个人是比较推荐单元测试与具体实现代码同步进行这个方案的。只有对需求有一定的理解后才能知道什么是代码的正确性,才能写出有效的单元测试来验证正确性,而能写出一些功能代码则说明对需求有一定理解了。

四、为什么要写单元测试

这其实是问单元测试能带来什么好处。之所以把这个问题放在最后讨论是因为如果一上来就说单元测试多好多好,终究还是会缺乏说服力。

而有了上面讨论做铺垫,我们更加清楚单元测试的使用场景,以及它做得到和做不到的。

单元测试的作用:

(1)让我们对自己的代码有信心

修改了代码后单测依然通过的,起码说明我们的修改没有破坏程序的正确性。这从主观上能增加我们对代码的信心。虽然单元测试通过了并不意味着程序就没有bug了,但我们也要了解到这可能不是单元测试的问题。单元测试顾名思义是测试一个”单元”,这个”单元”一般是类或方法,而不是整个系统。对整个系统的测试那是集成测试,功能测试的职责。单元测试追求的是快速反馈,频繁执行。集成测试虽然测“全局”,但成本较高,所以执行频率较少。两者使用场景不同,目的不同。

2)为代码重构保驾护航

看到代码很差劲,想重构,但又担心重构之后出问题,怎么办呢?如果有单元测试情况就不一样了,重构完代码,跑一遍单元测试,如果单元测试都通过,基本上可以保证我们的重构没有破坏原来代码逻辑的正确性。不过前提是之前的写的单元测试质量很好,覆盖率很高。当然这仅限于小范围的重构,比如重构一个类或者函数的实现,但对于大刀阔斧的重构(比如单体重构成微服务,面向库表模式重构成DDD),就不适用,那个时候要重写单元测试了。

(3)通过单元测试快速熟悉代码

单元测试不仅起到了测试的作用,还是一种很好的“文档”,通过单元测试,我们不需要深入的阅读代码,便能知道这段代码做什么工作,有哪些特殊情况需要考虑,包含哪些业务。

五、小结

  • 何时写
    单元测试与具体实现代码同时进行。

  • 写多细
    哪些代码需要有单元测试覆盖:
    1、逻辑复杂的
    2、容易出错的
    3、不易理解的,即使是自己过段时间也会遗忘的,看不懂自己的代码,单元测试代码有助于理解代码的功能和需求
    4、公共代码。比如自定义的所有http请求都会经过的拦截器;工具类等。
    5、 核心业务代码。一个产品里最核心最有业务价值的代码应该要有较高的单元测试覆盖率。

单元测试系列一-为什么要写单元测试,何时写,写多细相关推荐

  1. java 单元测试_在springboot中写单元测试解决依赖注入和执行后事务回滚问题

    往期文章 「Java并发编程」谈谈Java中的内存模型JMM 面试官:说说你知道多少种线程池拒绝策略 为什么不要在MySQL中使用UTF-8编码方式 前言 很多公司都有写单元测试的硬性要求,在提交代码 ...

  2. springboot 事务嵌套问题_在springboot中写单元测试解决依赖注入和执行后事务回滚问题...

    往期文章 「Java并发编程」谈谈Java中的内存模型JMM 面试官:说说你知道多少种线程池拒绝策略 为什么不要在MySQL中使用UTF-8编码方式 前言 很多公司都有写单元测试的硬性要求,在提交代码 ...

  3. 单元测试系列之五:Mock工具之Mockito实战

    更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6780719.html 在实际项目中写单 ...

  4. Android单元测试系列(3)-Mock之Mockito

    目录 一.官网 二.Demo示例 1. 目录结构 2. 被测试的类 3. 测试类 三.Mockito方法说明 1. mock对象创建 2. Mockito框架中的常见方法说明 2.1 常见的打桩方法 ...

  5. Android单元测试系列(3)-Mock之PowerMock

    目录 一.官网 二.Demo示例 三.PowerMock常用的测试方法 1. Private 1.1 私有变量 1.2 私有方法 2. Final 3. Static Android单元测试系列(3) ...

  6. 写单元测试应该注意什么

    写单元测试应该注意什么 转载于:https://www.cnblogs.com/yishenweilv/p/10899695.html

  7. 单元测试系列之八:Sonar 数据库表关系整理一(续)

    更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 简介:Sonar平台是目前较为流行的静态代码扫描平台,为了便于使用以及自己二次开发,有必要对它的数据库结构进行学习 ...

  8. 为什么从前那些.NET开发者都不写单元测试呢?

    楔子 四年前我虽然也写了很多年代码,由于公司虽然规模不小,却并非一家规范化的软件公司,因此在项目中严格意义上来说并没有架构设计.也不写单元测试,后来有幸加入了一家公司,这家公司虽然也是一家小公司,但是 ...

  9. springboot 系列教程十:springboot单元测试

    2019独角兽企业重金招聘Python工程师标准>>> 单元测试 springboot 支持多种方式的单元测试,方便开发者测试代码,首先需要在 pom 文件中添加 starter & ...

  10. 写单元测试的好处(转)

    许多开发者都有个习惯,常常不乐意去写个简单的单元测试程序来验证自己的代码.对自己的程序一直非常有自信,或存在侥幸心理每次运行通过后就直接扔给测试组测试了.然而每次测试组的BUG提交过来后就会发现自己的 ...

最新文章

  1. Squid配置二级代理(父代理)
  2. 树莓派应用实例2:环境温湿度测量
  3. java RSA加密解密--转载
  4. 学画画软件app推荐_今日推荐:拍照摄影APP之稀缺软件篇
  5. 2022年中国品质直播选型与应用白皮书
  6. node.js 资料
  7. 移动App的原型创建工具
  8. 异常处理1:复习、异常概述和异常体系结构
  9. activiti学习资料(架构描述)
  10. python将PDF文件转化为图片
  11. Netty+WebSocket服务器完成Web聊天室(纯文字)
  12. 计算机专业学习自然辩证法,深度学习 自然辩证法
  13. FORCE_CONSTANTS中3阶力常数大小与原子间距的分析脚本
  14. 一分钟搞懂app热更新
  15. 互联网舆情系统的架构实践
  16. 我只说一次,这样用领英开发国外客户,屡试不爽!
  17. Element UI 应用精讲
  18. 维特比算法的简单实现
  19. BZOJ3677: [Apio2014]连珠线
  20. 【Please, upgrade your dependencies to the actual version of cor问题】

热门文章

  1. 使用Kinect2作为Oculus游戏应用的输入设备
  2. 面试——路径、转发与重定向的区别
  3. 重装Linux系统后的软件安装 及 常见操作_持续更新...
  4. 【签约】ManageEngine卓豪签约中国大饭店 | 智能解析日志、洞察威胁,提升数据安全合规性
  5. 单体架构、SOA架构、微服务架构的优点缺点以及区别联系
  6. 苹果开发那些事儿-D-U-N-S 号申请
  7. Android 播放器 mov,Android 调用系统播放器
  8. openbravo与淘宝对接文档一
  9. windows API 实现精确的打点计时器
  10. java泡泡屏保,js 模拟气泡屏保效果代码