想当年毕业设计是测试驱动开发,所以从刚入行开始对单元测试、测试驱动开发有比较深入的认识,刚开始一直作为敏捷开发的忠实粉丝。但是几年工作下来,我开始对单元测试持矛盾的态度:单元测试当然是一种很好的创举,但是具体使用当中,它却经常会产生副作用。这当然不是因为单元测试这一思想有问题,而是实践这一思想的人的问题。

  当前很多公司使用单元测试的怪现象:

  很多公司为了说出去好看——我们的开发遵循敏捷开发,拥有近的单元测试覆盖率,所以代码质量有非常可靠的保障。但是实际上,单元测试都是软件已经开发完成之后加上去的,而且经常还是由专门分配的几个人去写单元测试的,而这几个人根本不熟悉需求,甚至根本没有参与开发过程,或者参与得很少,而分配给他们写单元测试代码的时间当然也很紧张,因为这也是需要成本的。所以,终导致的结果是——为了达到覆盖率目标,为每个方法(不管有无必要)加上单元测试,简单看一下这个方法,然后从对这个方法的肤浅理解出发,即开始动手,写一个或很少的几个测试用例,这样单元测试覆盖率的要求达到了,可是这样的单元测试有用吗?答案不言自明。

  这种怪现象一般可能具备哪些特征呢?

  1、整个开发过程完全之后写单元测试——这是单元测试的时机问题

  2、由非开发过程的参与者写单元测试——这是单元测试的执行者的角色问题

  3、由不了解需求的人员写单元测试——这也是单元测试的执行者的角色问题

  那么,这种行为会带来哪些副作用呢?

  1、这浪费了时间和人力成本

  2、这会带来负面的情绪影响

  这些人是带着抵触的厌烦的情绪投入工作的,因为明知这样的工作是无用功,仅仅是面子工程,却不得已而为之,自然没有兴趣没有热情,而这一情绪会横向和纵向地散发,从而给团队带来负面的影响。

  3、这些单元测试代码毫无用处,甚至产生负作用

  对于后来者来说,这种单元测试代码没有任何作用,因为写作者本是在不了解需求的基础上仓促写的,那么自然对后来者理解需求没有任何益处;而且如果后来者相信的这份单元测试代码,没有充分地调查具体的实现代码,还会因此产生误解。

  单元测试到底要怎么写?何时写?

  这是一个很值得探究的问题,但是有十足的必要。

  在网上上看到“如何控制单元测试的粒度”这篇文章,文章是从StackOverflow上的一个问题开始引入的。

  这个问题是:

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

  问题的佳答案是:

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

  看了这个佳答案,给人感觉对单元测试持一定的否定态度和不感冒态度。但是知道这一佳答案的回答者是谁吗?是Kent Beck。对,正是那位极限编程、测试驱动开发和单元测试以及JUnit的创造者Kent Beck。Kent Beck的答案,正好回答了单元测试该怎么写、要写到什么程度、何时应该写这几个问题。