程序员一般都不喜欢写测试代码。而不久之前,我也是其中一员。从自身的经验出发,以前反感写测试代码的理由有以下几点。
- 觉得写测试代码不是创造性劳动。相比实现代码,写测试代码的时候确实少了一份激情。因为这些代码并不会给 Application 增加 feature,或提高性能。花了很多时间,进度却没有向前,难免有所抵触。
- 觉得测试代码没有价值。传统的 Web 开发方式中,我们确认自己的代码能够正常运作的方式通常是亲自去浏览器上操作运行后的页面。等到自己感觉 OK 了,为了应付客户要求或者纯粹追求覆盖率,才不得不写测试代码。此时自己对实现代码已经颇有信心,所以写完测试代码后,绝大多数情况下测试都是能够 pass 的,pass 不了多半也是测试代码写的有问题。所以会感觉测试代码并没有发挥出应有的价值。
- 测试代码很难维护。无论是 Application 的需求有变化,或是改动了一些代码。经常发现会破坏了原有的测试代码,导致我们改完了实现代码后不得不再去修改测试代码,使它能够跟上时代的步伐。经过几次之后,测试代码并没有引导我们的开发,反而成了累赘。
- 测试的执行速度很慢。特别是 Ruby 项目的测试,有些项目变大以后执行一次全套的测试甚至需要一个多小时。而平时的开发过程中,执行单个文件中的测试需要一两分钟的案例屡见不鲜。
对测试代码的态度出现转变的转折点出现在10月底去北京参加的 RubyConfChina 2013,两天的时间里听了十几位嘉宾的演讲,而其中有3个演讲是专门讲测试的。分别是 Test your Rails application with pleasure、 RSpec: the good parts and the tricky parts、 Discovering Better Object Oriented Design with Tests。之前在看《Eloquent Ruby》这本书时,作者就说到 Ruby 社区可能是最喜欢写测试的程序员群体,Ruby 的测试框架和各类辅助测试的工具不胜枚举。这次也证实了此言非虚。
回来以后正好工作上开始了新项目,自己便趁此机会将学到的东西应用到项目开发中,看看测试究竟是否真的有那么神奇。几个星期下来,自己的感受如下。
- 测试代码质量提高。新项目中开发时,我尽可能放弃了人肉测试这一调试方式。Ruby 的 Capybara 和 Poltergeist 等工具提供了用代码来模拟用户在浏览器上的操作的功能。同时也尽量强迫自己使用TDD的开发流程,也就是测试先行,虽然目前还没有达到100%的 TDD。这种方式下,如果心中有不安,就会增加测试的 case,因此测试代码的质量很高。测试全部pass就意味着目前考虑到的确认点都没有问题,可以安心的继续后面的开发。反正都是要写测试代码的,所以让它们变的更有价值一些,不是很好吗?
- 信心增强。有了完善的测试代码后,就可以放手去重构代码或是试验更好的实现方式了,只要测试通过就说明代码没有问题,根本无需亲自去页面上确认。
- 节约时间。由于开发和测试使用的是不同的数据库,所以以前经常需要准备两套数据。一套是开发数据库的,用于人肉测试。另一套是测试数据。而现在不仅节省了肉测的时间,也省去了造数据的功夫。相当于开发效率加倍了。还有上面讲到的确认重构或修改代码有没有问题,只需花一分钟不到的时间跑一下测试即可,这部分时间也能节省不少。
总的来说,测试既节约了时间又增加了信心,所以更加愿意完善自己的测试代码,结果信心越来越强,形成了良性循环。所以如果你还是很抵触写测试代码,不妨放下成见,拥抱测试,相信你会感受到测试带来的那种美好的感觉。