【IT168 评论】这几年了陆陆续续的学习过不少技术,但真正能够对自己的工作起很好帮助的是在不多,测试驱动是其中之一。前段时间国外的有位程序员Karl Seguin整理了一篇文章叫The 7 Phases of Unit Testing ,很快在译言网上也有了翻译《单元测试的七种境界》,作为一位测试驱动开发的粉丝也像借这篇文章整理一下自己的学习过程和体验
1. 以各种借口拒绝单元测试Unit Test,比较常用的是“你没有足够的时间(进行单元测试)”。
无论是对单元测试的老手还是新手编写单元测试还是有一定得工作量的,而且单元测试也需要掌握大量的测试框架和工具(光一个junit或testng你很难工作地很happy)。所以在这个阶段开发人员往往会觉得单元测试很难写、很费时,自然而然会使用没有足够的时间(进行单元测试)的借口,其实在这个阶段开发人员需要积极地学习和掌握测试框架和理解单元测试理念。
2. 尝试单元测试并且立刻开始在自己的博客商鼓吹单元测试和测试驱动开发Test Driven Development的好处。
开发人员在这个阶段学习很掌握了一些单元测试的工具并在实际工作中加以的运用,并很好的解决了一些问题,意识到了单元测试的价值。我自己也向同事和同学介绍过相关的技术,希望大家对相关的技术能很好的学习和运用,现在回想那个时候对单元测试的技术的掌握和理解都是不完整的,只能说是初窥门径而已。
3. 单元测试一切。为了能够完成单元测试,而将私有private的方法和属性修改为内部internal;为了达到单元测试覆盖率100%而测试getter() 和 setter() 属性(方法)。
这样的阶段很明显,特别是遇到private,static方法的测试时会感到很麻烦,所以往往采用了一些不优美的解决方式,目的是能够对相关的方法和类进行单元测试,但没有从根本上意识到是自己的设计有问题,从而导致可测试比较差(testability)。至于对getter和setter 方法进行测试到是没有过,可能只自己所在的公司一直都没有片面的强调过测试100%覆盖率吧。
4. 无法忍受脆弱的单元测试,在没有弄明白是什么的时候,就匆忙转向“集成测试"。
单元测试也是代码,只要是代码就会有设计、编码上共同的问题,比如设计模式的运用、重复代码的问题。在无法理解和单元测试中“单元”和“隔离”这两个名词的情况下,会想要通过集成测试来实现单元测试。我自己没有运用过集成测试的工具,但用dbunit直接模拟数据库的情况,从而将多个类“集成”起来测试是这个阶段最常用的单元测试方法。实际上用dbunit直接模拟数据库也是非常脆弱和繁琐的,mocking才是王道。
5. 发现了一种模拟 mocking 框架,并且乐于使用强制语义(strict semantics)。
mocking是单元测试中不可缺少的重要组成,Java的单元测试方案中Easymock和Jmock是两个成熟的Mock框架。但 Mocking的学习和理解可能是单元测试工具中最具有难度的地方了,通过运用Mocking你会发觉之前很多工作(比如数据库模拟)都是浪费时间、精力和无效的。
6. 模拟mock所有可能模拟mocked的对象。
通过在单元测试中运用Mocking真正贯彻了单元测试的“单元”和“隔离”的原则,不过Mocking是在件繁琐和困难的事情,这时候就需要考虑什么是必须要mock的、什么可以不mock的。
7. 开始真正有效单元测试。
恭喜你终于达到了这个阶段,你已经将面向对象设计、设计模式、单元测试、重构等一些技术都融汇到了一起,你终于可以根据自己的意愿编写真正有效的单元测试了。在这个阶段可能你掌握或有了一套测试框架,这套测试框架整合了junit、testng、jmock、easymock、dbunit、xumlunit、unitils等一系列你测试工具使你的编写单元测试效率是之前的3-4倍或者更多。