介绍一下 TDD
TDD 全称 (Test-driven Development),Test 这个词语表明了它与测试不可分割的关系,开发人员听到测试自然产生抗拒心理,不过不要慌,这里的测试具有存在的必要性,也能够对开发产生辅助推动作用,如果想了解更多 TDD 的详情可以查看维基百科的测试驱动开发。
TDD 的流程是一个红(test that fails)、绿(pass the test)、蓝(refactor)的循环过程,如下图。
这个过程中讲究测试先行,大家肯定有疑问,代码都还没有我写测试干什么?这里的测试并不是测试已经实现的功能代码,而是利用测试描述业务需求,这是一个梳理确认需求的过程,当然这个测试肯定是失败的,毕竟实现功能的代码还没有完成。利用测试描述完需求后就是实现它,不过 TDD 不提倡一步到位,而是建议小步快走,分阶段性实现,业务代码完成后测试自然会是通过的绿色。那接下来我们是不是可以开发下一个功能了?并不是,实现功能的代码只是实现了功能,绝大多数人(当然也包括我在内)并不是天才,初步实现的代码质量还有进一步提高的空间,这个时候需要放下实现功能的情绪开始对当前业务代码的重构,因为一开始就有了测试,重构的可靠性自然有所保障,于是你就可以开始精进代码的过程,每个功能的实现都重复这个循环进行。
TDD 的是与非
以上对 TDD 的流程描述可以概括出这样几个优点
- 测试对需求的描述使需求明确
- 测试使代码正确性有所保障
- 测试的保障性前提下可以进行重构,提高代码质量
- 小步快走可以保证犯错在可控范围内
这样看来 TDD 真是毫无破绽,但还是那句老话「没有银弹」,TDD 并不能解决所有的问题,它也有自己的缺陷。如果有开发的功能中有对其他服务的调用,你需要进行 Mock,Mock 时对数据的准备会花费你的精力;如果初始的设计本身就存在问题,那后面的修改中不仅需要修改业务代码,连测试代码可能也会被波及,也就是说极有可能需要维护业务代码和测试代码;TDD 的掌握是需要大量练习的,比如小步快走的测试需要控制在什么粒度,这是个吃经验的问题,只有通过大量的练习才能很好的掌握。
不过绝大多数人都不是天才,测试可以框定错误发生的范围,对我这种普通人来说是没有坏处的,而且测试保障情况下的重构可以让自己的代码提升质量,看起来更加舒服。当然也有些问题需要我去实践,比如使用 Spring 框架时的测试启动加载就要耗费不少时间,这样的情况下 TDD 应该如何去实践?耗子叔的文章中也有讲到过 TDD 的一些弊端,详情可以查看TDD并不是看上去的那么美。
所有的知识学习都是个动态的过程,学习后需要通过实践不断来修正,其他知识如此,TDD 也是如此,在它们适用的场景下才能真正发挥威力。