我讨厌单元测试:滕振宇谈如何进行单元测试

原创 2012年03月27日 23:30:07

(本文首发于InfoQ中文站:http://www.infoq.com/cn/news/2012/02/I-Hate-Unit-Test

说起单元测试的好处相信大家都能列举出不少,可是很多时候,开发人员面对自己产品的代码,想写单元测试却无从下手,久而久之,便会有人大喊:“我讨厌单元测试。”资深敏捷咨询师腾振宇(Daniel Teng)在GTUG-TopGeek开发工程管理沙龙就以此为题,结合最近的一个项目,和大家分享了他对单元测试的一些看法。

Daniel先介绍了下最近的一个项目,虽然不是遗留系统,但代码已经惨不忍睹,而且缺乏必要的测试保障,要修改代码可谓举步维艰。例如,一段代码和结对伙伴读了半小时没读懂,找来原作者看着注释又想了10分钟,终于才搞明白这段代码是做什么的。根据二八原则,先找到那20%的点,修改它带来80%的价值。最直接的做法就是寻找代码库里最常被修改的文件,一般的文件只有几次修改,有的文件则被修改了几十次,每个人都在往复杂的代码里加入新的东西,但没有人往里面加测试,于是第一步就是为它增加测试。

很多开发者会说老项目就算了,如果新启动一个项目,我就会写单元测试了,Daniel认为这是一个“美好的梦想”,很多原因会打破它:

  • 代码已经很烂了,又没办法下手了
  • UI不好测
  • 认为这是QA的工作
  • 写的单元测试找不到Bug
  • 代码的外部依赖太多
  • 代码稍作修改,测试也要一并修改,太麻烦了

究其根本原因,是开发者根本不会写单元测试!满足什么标准的测试才是单元测试呢?根据《修改代码的艺术》,需要访问数据库的测试不是单元测试,需要访问网络的测试不是单元测试,需要访问文件系统的测试不是单元测试……

为了更方便地进行单元测试,业务代码应避免以下情况:

  • 存在太多条件逻辑
  • 构造函数中做的事情太多
  • 存在太多全局状态
  • 混杂了太多无关的逻辑
  • 存在太多静态方法
  • 存在过多外部依赖

例如,在代码中存在硬编码,或者是直接创建了一个数据库连接,这种做法都是比较危险的,因为在测试时没有办法“偷梁换柱”。

想要写好单元测试,学会重构是很重要的,重构的过程类似于清理厨房,虽然和做饭没太大关系,但可以让您下次做饭更方便,心情更好。可以重构的地方包括,在待测试类与其依赖之间增加一层Test Fixture;将创建逻辑与业务逻辑分开等等。重构可以采取以下策略:

  • 编写测试代码建立基本的防护网。在单元测试和功能测试之间要有取舍,如果单元测试实施成本很高,可以先加功能测试。
  • 通过增加中间层来打破依赖,不是为了去掉依赖,而是为了后续的修改以及测试的便利。
  • 将第一步中编写的功能测试换成单元测试。

最后,Daniel还为大家提了一些建议:

  • 项目里的破窗要修好,别容忍别人加新的破窗,用测试将破窗保护起来。
  • 当你离开一个地方的时候,要让它比你来的时候更整洁干净。(童子军军规)
  • 不停地重构你的代码,每次走一小步。

随后有人提问,如何评估一个单元测试的质量,用代码行覆盖率是否可行。Daniel认为没必要去追求代码行覆盖率,真正要覆盖的是逻辑,而不是代码行。通过结对编程可以减少低质量的单元测试,人都喜欢改变,但没人喜欢被改变,不要强求结对编程,让他看到好处,尝到甜头,吸引他来做结对编程,没有人喜欢落后,比如50%的人在做结对了,剩下的人自然会想尝试。

当被问及单元测试是否是必须的时候,Daniel回答这并不是必要的,而是需要进行综合的衡量,比如你的竞争对手一周前推出了一个产品,你需要在一周内完成产品研发并上线,这时可以选择写或者不写单元测试,对于没有写过单元测试的人,一开始是需要上手的成本的。

如果您也对单元测试的话题感兴趣,不妨关注腾振宇的博客微博,也可以观看会议视频


滕振宇谈如何进行单元测试

说起单元测试的好处相信大家都能列举出不少,可是很多时候,开发人员面对自己产品的代码,想写单元测试却无从下手,久而久之,便会有人大喊:“我讨厌单元测试。”资深敏捷咨询师腾振宇(Daniel Teng)在...
  • wxyFighting
  • wxyFighting
  • 2013年04月30日 15:50
  • 980

用AS编写单元测试代码步骤

1.被测试类 2.测试类: 3.在 AndroidManifest.xml 中添加指令集 instrumentation 和测试库 uses­library 4.在目录视图中找到TestStudent...
  • zsr0526
  • zsr0526
  • 2016年11月13日 11:29
  • 1026

用于web类库代码的单元测试

用于web类库代码的单元测试 最近把appcache的功能放到了公用类库中,写单元测试时发现不了 HttpContext,  代码如下: using System; using System.Coll...
  • huwei2003
  • huwei2003
  • 2015年12月23日 09:55
  • 1208

Android Studio中进行单元测试

在Android开发过程中,我们往往忽略了单元测试功能, 主要还能还是大家觉得 真机在手,运行调试特别直观。 不过如果我们能够养成单元测试的习惯,相信能更加提升我们应用开发的速度。 当我们创建...
  • qwe380948730
  • qwe380948730
  • 2017年08月21日 16:19
  • 301

为什么很多程序员不喜欢写单元测试?

业界良心。。。。 点击打开链接https://segmentfault.com/q/1010000002415710 我认为这和懒惰与否没有关系,测试不是必须要写的,有人说:雇主不是为测试而...
  • lein_wang
  • lein_wang
  • 2016年08月03日 16:15
  • 426

as中单元测试框架

原文链接: http://www.jianshu.com/p/bc99678b1d6e 基本单元测试框架 Java单元测试框架:Junit、Mockito、Powermockito等;An...
  • luomoBM
  • luomoBM
  • 2016年12月15日 12:55
  • 401

基于SSM或者SSH的三种单元测试方式

今天总结一下两种单元测试方法,这个废话不多说,直接上代码(配置文: 第一种方式(通过配置文件+原始方式获取bean): import org.junit.Test; import org.spring...
  • buyaoshuohua1
  • buyaoshuohua1
  • 2017年07月26日 23:16
  • 1048

tp框架单元测试库tpunit

thinkphp本身并没有提供相应的单元测试支持,所以这里介绍一个可以对tp进行单元测试的库tpunit。 Tpunit这个库是依赖于phpunit的,其特点是易用、方便和非入侵式。   使用T...
  • a767536305
  • a767536305
  • 2016年06月08日 09:58
  • 807

SSH中如何进行单元测试

相信不少朋友都遇见过类似问题,现在介绍一个JUNIT4的测试方法。 首先在已经集成好SSH的环境中 添加 junit4.jar     spring-test.jar 接着在项目中新建一个s...
  • CJaver
  • CJaver
  • 2014年08月12日 16:30
  • 2567

Android中如何简单的做单元测试

单元测试 单元测试(模块测试)是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为。例如,你...
  • JavaAndroid730
  • JavaAndroid730
  • 2016年11月24日 22:51
  • 1901
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:我讨厌单元测试:滕振宇谈如何进行单元测试
举报原因:
原因补充:

(最多只允许输入30个字)