单元测试 VS 跟踪调试

前些天在程序员杂志上看到同门大师兄WPC的文章"Javascript程序调试 - 不调之调”,有些感触,文章通过诙谐的语言讲述了作者在Thoughtworks工作时处理Javascrip调试问题的对策 - 通过应用Selenium页面测试工具来减弱甚至消除对调试的需要。

其实,敏捷开发推荐的测试驱动开发对于跟踪调试的态度正是“不调之调”,跟踪调试在绝大多数情况下是不得已而为之的,是开发人员遇到bug时最后的选择。在敏捷开发过程中几乎是不需要跟踪调试的,它通过单元测试减弱甚至消除对跟踪调试的需要。

在非测试驱动开发的情况下,当遇到bug时,一般程序员会做几件事,要么直接意识到问题所在然后去修改bug,要么在程序中可能出问题的地方设置断点,进 行跟踪调试,确定并修改bug。在测试驱动开发的环境下,如果bug不是失败的单元测试体现的,说明已有的测试没能覆盖某一个潜在的需求,此时需要增加单 元测试来体现这个需求,这个(或多个)测试会失败,问题会被定位,此时可以放心地去修改bug了。但大多数情况下bug是通过失败的单元测试体现的,此时 单元测试会帮助定位bug。

看来,对付bug,要么进行跟踪调试,要么编写单元测试来定位问题,后者相比前者有如下好处:
1)单元测试是可重复的,而跟踪调试的过程不能被自动重复,就算遇到同样的问题只能从头再做一遍。
2)单元测试揭示、记录并确保了一个潜在的需求,而跟踪调试没有显式地揭露背后的需求,而只是默默地把它解决掉了,本次调试的经验也没有记录下来,如果将来的某天这个bug又出现了,它不一定会被及时发现,就算发现了,也需要从新跟踪调试。
3)单元测试失败后比较容易定位bug,bug往往可以很快改正(敏捷开发通过很多实践保证软件的质量,软件质量将影响修改bug的难易程度),而跟踪调试往往是痛苦的,有时需要很高的技巧和耐心,这个相信大家都有感受,最难受的是,你不是到什么时候才能搞定这个bug。

在测试驱动开发的环境下,如果某个测试报错,但不容易看出来是那里的问题,结果你有一种冲动想跟踪进去调试,这便是一个信号,此时你需要做的是拆分或是增加新的测试,让问题显而易见,而不是真的进去调试。
如果你是想跟踪某一个失败的测试函数,看看是哪一个断言出了错,或是某个断言内部判断了太多问题(对容器的断言会导致对容器内每个元素的断言,此时从失败 信息上不容易判断是哪个元素的问题),你想看看具体是哪一部分出了错,此时你需要将这个测试函数拆分成几个独立的测试函数,或是将那个超级断言(比如前面 提到的对容器的断言)拆分成几个独立的,更明确的断言。如果你是想跟踪到被测试的代码里去,此时你需要写新的测试,将问题定位到更窄的范围里,直到问题比 较容易被暴露出来。

前面的讨论也是在说,一个好的单元测试既要"意义明确"又要"粒度适中"。
每一个单元测试函数都是通过将一个新需求持续地应用到被测试的类中来保证类行为的正确性,单元测试函数(或一组测试函数,比如一组三角测试函数)需要是意 义明确的,因为它暗指一个需求,一个意义明确的需求。如果你将某个类的所有测试函数名字罗列在一起,你会发现不经意中,你给这个类写了一个漂亮的需求文档 (Agile是有文档的,而且和代码严格同步)。
再说“粒度适中”,每个测试函数都测试类行为的某一个方面,只要一旦测试失败,能够比较容易定位问题(或是能够比较容易地通过一组针对同一需求的其它失败的测试函数定位问题),粒度就是合适的。

要求这么多,编写单元测试是不是很难呢?不是的,和所有其它的Agile最佳实践一样,良好的结果是演进出来的,你不需要在前期做艰难的决策,但却要随时准备变化,还要有发现坏气味的敏锐嗅觉。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值