Cui.Liqiang

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

  TDD是现在很流行的一种软件开发实践。此文一作个人体会总结,二作给对TDD有兴趣的但是还不是很熟悉的同学一个分享。

  对TDD本文从三个方面加以说明:What, Why, How.

  首先说明什么是TDD。全称是测试驱动开发。从字面可以看出其中包含两层含义。我们把实现产品功能的代码称为产品代码,第一层含义就是编写的代码需要有测试。这些测试也是以代码的形式存在,称为测试代码。因此很容易通过这些测试代码对产品代码进行自动化测试。这些测试可以分为:单元测试,集成测试,功能测试。这些不同种类的测试具体是做什么的会在How的段落加以说明。TDD的第二层含义就是“驱动”二字,也就是说先写测试代码,然后再编写产品代码让测试代码通过。

  关于Why,同样从上面提到的两层进行解释。如果没有自动化测试,那么只能使用手工测试。编写自动化测试需要一定的代价,肯定要比手工测试付出更多的工作。但是一旦测试编写出来就可以被反复的使用,把测试人员从繁重而重复的手工测试中解放出来,从而能让他们更多的把精力放在用户体验和探索性测试上。如果产品代码有完备的测试覆盖,那么开发人员就可以放心的去添加新功能,而不用担心自己不知不觉引入的bug或者破坏了之前的功能,因为你可以通过运行一遍之前所有的测试来得到快速的反馈,从而趁热打铁,对代码行进及时修改。那么为什么要测试先行呢。做软件的过程就是把业务需求转换成产品代码的过程。那么首先就要对业务需求进行分析。写文档是一个比较传统的组织和分析需求的手段。但是文档这东西都是用人类的语言写成的,包含了人的主观想法和措辞。不同的人看同一份文档可能会有不同的理解,然后就需要进行反复讨论和确认。另外写过软件的同学大概都会有这样的体会:需求感觉已经说得很明白了,然后着手去写代码,就发现还是有一堆问题,也许是和之前代码有某些相关性,导致该功能不能这样设计,也许还有一些其他的原因。也就是说代码层级的反馈是最真实最直接的。既然如此为什么不把分析好的需求以代码的形式展现出来呢,也就是测试代码。和文档相比,测试代码是严谨的,通过就是通过,不通过就是不通过,不会有人有不同的理解。同样其直接作用在代码库上,可以得到快速反馈。这里可以看到编写测试代码本身就是梳理需求的过程。同时编写测试代码也是设计的过程,因为测试中会去调用现在还不存在的类和类的方法,也就是定义好了实现该功能所需要新加的类或者方法的签名。而且这样的设计过程是从严格严谨的需求出发的,没有任何的预先设计,所以可以保证没有多于无用的设计,所有的被“驱动”出来的接口,类都是为了实现该功能而存在的,这也能在一定程度上节省开发时间。在此基础上进行编码就很靠谱,心里很有底了。

  稍微总结下TDD的好处:快速真实的反馈,需求驱动的设计,可以快速反复进行的回归测试,这些都能够很好提高软件开发的质量和速度。当然这些都不是白来的,是需要付出代价的。首先编写测试代码是需要时间的,在后期软件功能进行调整的时候,也要遵循先改测试的原则。有付出,也有好处,这就需要权衡到底是我付出的多还是得到的多。个人认为,在开发人员对工具和技术能够很熟练的掌握的前提下,TDD的好处是很明显的。

  说了What和Why,接下来谈谈How。上面提到了不同种类的测试。下面一一加以说明。

  1. 单元测试。通常这种测试是针对一个类的接口方法来进行的。但是一个类肯定不是单独存在的,一定会对其他一个或者多个类有依赖关系。这时就可以使用mock技术对其依赖的类的行为进行模拟,从而达到单独测试该类的目的。单元测试只涉及到一个类,因此这种测试能够最快速的得到反馈,是最基本的测试类型。
  2.  集成测试。这种测试往往是一个端到端的测试。也就是说从应用的最前端一直到底层数据库都会进行真实的操作。这样的测试需要进行运行时环境的模拟,测试数据的准备等等。
  3.  功能测试:这种测试和前面两种的最大区别是它是从用户操作视角出发,再真正的运行环境上模拟用户操作的某个场景。来验证其正确性。

  就Java而言,Junit是比较常用的一个测试框架。结合不同的其他工具可以进行多种测试。如结合mock进行单元测试,结合selinum可以做web功能测试。对于单元测试来说,TDD应该被严格的执行,因为它的反馈很直接,很快速。但是对于后两种,一般反馈周期都很长,对于这种测试,需要灵活掌握。但是对于新手来说,最好是严格的执行所有的步骤。等到能够灵活掌握了,再随心所欲的去发挥。

  做TDD还不是很久,理解的深度和应用的广度也很有限,欢迎讨论,指教。

posted on 2010-12-24 22:39  Cui.Liqiang  阅读(713)  评论(0编辑  收藏  举报