代码改变世界

测试驱动开发TDD系列(一)

2010-07-29 23:44  Virus-BeautyCode  阅读(4816)  评论(6编辑  收藏  举报

 

  

 

引言

  这个系列来自我读《Test-Driven Development in Microsoft .NET》这本书的一些内容,以及一些自己的体会。

正文

  1、什么是测试驱动开发?

  可以用下面的两句话来定义。

  •   在你已经写好一个测试失败的自动化测试用例之前,绝不写一行代码。
  •   消除代码重复。

  第一句话很好理解,就是在写代码之前,先写一些测试失败的自动化脚本,测试肯定是失败的,因为没有任何实现。因为测试包含代码必须满足和实现的需求。如果没有需求,就不需要实现任何功能。这条可以防止我们实现没有测试和不需要实现的功能。

  但是我还是有一点疑问,就是如果一行代码都不写,连接口没有,自动化脚本又测试什么呢?也只能写一写手动测试脚本,功能性的测试脚本。针对具体实现的自动化脚本,也还是要等接口出来才可以写吧,你们说呢?

  第二点是说在应用中不应该有重复的代码。代码重复是一种典型的不良软件设计,会导致矛盾问题。如果有代码重复,在看见的时候,程序员就应该消除它。

  2、简单的设计

  因为测试覆盖了需求,所以在写代码的时候,你的工作就是不多不少的满足需求。每个人都理解“不少”(因为少了软件没有办法工作了),但是不是每个人都理解“不多”。

  “不多”是什么意思呢?想象回到有人让你在现有系统上添加功能的时候,然后你说“没有问题,在之前我就已经想到会发生这个了,我已经加入了这个功能的代码”。你被看做是英雄,因为你预料到了这个需求,并且在解决方案中已经实现了它。

  想一下在你为了额外的功能增加复杂性的时候,抽象类,等等,那些没有人让你实现的功能。这些额外的代码必须随着那些使用中的代码一起维护。事实上,维护这个软件的负担在加重,因为它超过了实际的适用范围。因此你需要为不多、不少而奋斗,可以参考下面:

  •   代码满足了当前客户的要求。
  •   代码通过了所有的测试。
  •   代码做了需要做的每一件事。
  •   代码的类数量最少。
  •   代码保持了最少数量的方法。

  优先级最高的就是:代码满足了当前客户的要求。在你满足了适当的需求之后,下一个高优先级的是:代码通过了全部的测试。其次就是其他的了。

  有一句话,原文是:

  You might think that achieving simplicity is an easy process. Think again—it’s often very difficult. However, the simpler the code is, the more resilient it is and the easier it is to modify.

  我是这么理解的:

  你一定认为完成这些简单的事情是一个非常容易的过程。自己想想,通常它很困难。但是,代码越简单,它越有弹性,越容易修改。

  我不知道是不是我理解错了,还是这句话本身就是错误的呢?我不认为代码越简单越好,应该保持适度,甚至是应该相对应该复杂一点。如果类最少就是好的,那就写几个类好了,每个类几个方法,方法要少吗,那就每个方法写上几千行。这样的代码还能有弹性吗?还能容易修改吗?这么说来的话,分层和设计模式是最扯蛋的了,他们会导致很多的类,很多的方法。还有就是设计原则:SRP,单一职责原则,更是要求类的职责要单一,每一个类只应该有一个改变它的理由。这不都是矛盾的吗?如何理解呢?还是我太极端的理解了书中的意思呢?

  3、重构

  重构可以理解为,改进代码本身,但是不影响功能。重构是TDD的关键环节,因为在增加测试的时候,需要重新定义代码的设计。例如:你在代码中看到了重复,你就要移除它。如果需要引入复杂性来移除重复,也是正确的,因为是实际需要的,而不是预期设计的。

  4、红/绿/重构

  红、绿、重构,定义了实现每一个测试的过程。这个过程的目标就是工作在一个小的,可验证的过程,可以提供及时的反馈。

  •   编写测试代码。
  •   编译测试代码,它肯定会失败,因为你还没有写任何实现的代码。
  •   编写实现的代码。
  •   运行测试,观察测试结果,可能是红色的。
  •   使得测试通过。
  •   运行测试,观察测试结果,直到变绿。
  •   重构代码,消除重复代码。
  •   重复上面的过程。

  这就是著名的红绿条,不断的修改代码,直到进度条变成了绿色。因为,红色代表没有通过测试,绿色代表通过了测试。然后再对代码进行重构,消除代码中的重复。