我们说过项目级的质量保障中,一个很关键的活动是单元测试。那么到底如何来做单元测试呢?这里先讲一个有关单元测试的小故事。

  这个故事说的是Morgan Conrad。

  早晨,一名程序员向大师提了一个问题:“我想写一些单元测试。我应该为多少代码写测试呢?”

  大师回答:“不要为多少担心,写一些好的是了。”

  程序员笑了,鞠了一躬,离开了。

  ……

  几天之后,第二个程序员问了相同的问题。

  大量指着一锅烧开的水说:“这里面该下多少米呢?”

  这个程序员对这个问题感到奇怪,回答到:“我怎么能告诉您呢?这要看你准备请多少人吃饭了,看他们有多饿,还看您提供不提供别的食品,你是否有足够的米,等等。”

  “答得很对。”大师说。

  第二个程序员笑了,鞠了一躬,离开了。

  ……

  后,第三个程序员问了同样的有关测试程度的问题。

  “80%,不能再少了。”大师用拳头敲着桌子,用严肃的口吻说。

  第三个程序员笑了,鞠了一躬,离开了。

  ……

  在大师回答第三个问题的时候,一个年青的新手走了过来,问道:“大师,,我听您对同样的有关测试程度的问题做出了不同的回答,这是什么原因呢?”

  大师从椅子上站起来,回答:“给我倒杯新茶,我们谈谈。”

  在他们都在自己杯里倒满热气腾腾的绿茶后,大师开始说话了。

  “对于测试来说,第一个程序员是个新手,刚刚开始测试。现在,他有大量的代码,但是没有测试。他还要走很长的路,这个时候关注测试程度,会摧毁他的信心,一点用也没有。他好去写写,用用测试。他可以以后再考虑测试程度的问题。“

  “相反,第二个程序员已经熟练掌握编程和测试了。当我问她应当往锅里下多少米时,我让她意识到测试的数量是受很多因素影响的。她比我都了解这些因素??这毕竟是她自己的代码。没一个简单的答案,她很聪明,可以自己找到问题的答案,开始工作。”

  “我明白了。”年青的新手说,“但是,如果没有的简单的答案,那么,为什么您对第三个程序员说,‘一定要大于80%’呢?”

  大师一听大声笑得把肚子都鼓了起来,比他喝下去的水还多,涨起来,又憋下去。

  “第三个程序只是要个简单答案罢了??虽然根本没有简单的答案……这样他不用为这个问题困绕了。”

  从这个故事可以看出单元测试虽然很多人都在说,其实并不象大家想象的那么容易,下面来说说单元应该注意的三个关键问题:

  1、单元测试的单元选取

  单元测试,测试对象是单元,似乎很简单,但是单元选取不合理是很多人在做单元测试时候容易犯得到错误。比如C语言编程,很多人直接把每个函数作为单元来对待,把函数作为单元并没有错,错的是并不是所有的C语言函数都是单元。我们在选取单元的时候要注意两点:单元应该高内聚、低耦合。高内聚是一个单元应该是一个实现一定逻辑功能的相对完整的单元,做单元测试我们经常要对一些函数作桩来代替依赖函数的功能,而高内聚保证我们一般不需要在单元的内部做桩;低耦合是,单元逻辑边界应该比较清晰稳定,这样单元测试通过逻辑边界接口来驱动单元的时候,单元测试用例的稳定性相对比较好,不至于经常一点小小的变化要对单元测试用例做大规模变更。

  2、单元测试的度

  前面大师的故事重点说的是单元测试的度的问题,大师没有直接回答这个问题,那么到底单元测试应该做到什么度呢?这个问题连大师都没有正面回答,当然不是那么简单,很多项目在没有正确答案的情况下都用白盒覆盖率来衡量,比如语句覆盖80%,分支覆盖60%等等,项目组以为达到覆盖率目标可以了,殊不知这样恰恰是顾了指标忘了目标,特别白盒覆盖率指标,这些指标只是用来进行辅助判断的,根本的还是应该关注单元的逻辑功能的覆盖,通过代码覆盖率的不足来分析这些代码涉及的逻辑功能测试上的场景缺失。

  那么到底如何做单元测试呢?这里给大家推荐一个方法,那是软件质量分级。因为不同的单元对于质量的要求不同,因此我们针对不同的单元可以采取不同的质量方法。对于低质量要求的单元,我们可以只进行基本的代码走读等基本代码质量保障活动可以了;一般的交付质量要求的单元,我们除了基本的代码走读之外,一般要求至少的代码语句覆盖和基本代码静态检查;一些质量高的单元可能还需要增加更加深入的覆盖,比如80%的分支判定覆盖,增加动态检查等;对于高质量要求的单元,除了上面的我们可能还得考虑其他办法,比如不同的编译器,多种不同的静态检查、动态检查等。通过分级的单元测试确保分级的单元质量。

  3、单元测试自动化

  不同公司单元测试的方法可能不一样,但是有一点一点必须保证,是单元测试自动化。因为单元测试的目的是为了保证代码的质量防护,如果不能自动化运行必然不能频繁运行,这样也谈不上对代码的看护了。