关于如何提高代码可测试性的一些看法

在这些条件下,伪造一个RGHConnection对象最好的方法是对RGHConnection类应用接口提取。如果你手头一个支持重构的工具,那么它很可能也会支持接口提取方法。我们来看一下接口提取后的情况:

<interface> 
IRGHConnection 
+connect() 
+ disconnect() 
+RFDIReportFor(id:int):RFDIReport 
+ACTIOReportFor(customerID:int) ACTIOReport

  由于retry()和fromPacket()不属于业务相关方法因此只需要在实现类中增加这两个方法,至此我们可以轻松的构建出一个FackeConnection类,并使它能够提供我们所需要的反馈信息,然后将这个伪造的对象用在测试中:

public class FakeConnection implements IRGHConnection 

    public  RFDIReport report; 
    public void connect() {} 
    public void disconnnect(){} 
    public RFDIReport RFDReportFor(int id) {return report;} 
    public ACTIOReport ACTIOReportFor(int customerID) {return null;} 
}

  下面我们来写测试

void testNoSuccess()throws Exception{ 
  CreditMaster master = new CreditMaster("crm2.mas",true); 
  IRGHConnection connection = new FakeConnection(); 
  CreditValidator validator = new CreditValidator(connection,master,"a"); 
  connection.report = new RFDReport(....); 
  Certificate result = validator.validatorCustomer(new Customer(...)); 
  assertEquals(Certificate.VALID,result.getStatus()); 
}

  虽然FakeConnection类看起来有点奇怪:它的方法要么是空的要么就简单的返回null。这种情形并不常见。更糟的是,它有一个任何人都可以看到的并随意设置的公共变量。这样一个类似似乎违反了所有的良好准则。但你要看到,实际上并非如此。对于一个用来使得测试可行的类,规则是所不同的。FakeConnection中的代码并非产品代码。它永远也不属于最终投入运行的应用,而只是为了测试工具和测试而诞生。

  有了这个fake类我们接下去便可以做更多的相关测试。这就是提高代码可测试性和遇到教难构造的的类的时候所采取的一种方法。若代码设计阶段就将RGHConnection设计为接口,那么在后面的测试中会是测试更加方便,使代码在后期的重构也会更加方便。

本文是在读了《Working Effectively with legacy Code 》第九章,关于在无法将类放入测试用具中时遇到的四种最为常见的问题:

  (1)无法轻易创建该类的对象。

  (2)当该类位于测试用具中时,测试用具无法轻易通过编译构建。

  (3)我们需要用到的构造函数具有副作用。

  (4)构造函数中有一些要紧的工作,我们需要感知到它们。

  这四个问题在进行单元测试或者接口测试的时候,会对测试工作造成很大的阻碍,这就是一个代码可测性的问题。当遇到这样的问题的时候,有两种方法,第一、强行构建一个类去完成测试,但是这会造成测试的时候大部分工作都耗费在构建这样一个类的过程中;第二、重构代码,使代码具有可测性。本文将通过书中的列子来简单介绍一下如何提高代码的可测性。

  如在一个计费系统中,我们有一个未测试的Java类:CreditValidator。

public class CreditValidator
       {
             public CreditValidator (RGHConnection connection,
                                             CreditMaster master,
                                             String validatorID) {
       }
     Certificate validateCustomer(Customer customer) throws InvalidaCredit{
      }
     public class RGHConnection
        {
              public RGHConnection(int port, String Name, String passwd) throws IOException {
             }
         }
    }

  我们可以看到CreditValidator构造函数含有三个参数RGHConnection,CreditMaster,validatorID。其中RGHConnection对象在构造时会连接到一个服务器,这个链接被用来从服务器上获取必要的信息,以检查客户的余额。

  宁一个类CreditMaster,则提供一些我们在检查余额的过程中会用到的策略信息。该类的构造函数会从一个文件中加载相关信息,并把这些信息保存在内存中以备后用。

  如果按照我们开头讲的强制构造一个类来完成测试,如下所示:

public void testCreate() throws Exception {
       RGHConnection connection = new RGHConnection(DEFAULT_PORT,"admin","rii8ii9s");
       CreditMaster master = new CreditMaster ("crm2.mas",true);
       CreditValidator validator = new CreditValidator(connection,master,"a");
}

  虽然我们构建一个这个样的类,但是你能忍受这个测试的速度,根据《Working Effectively with legacy Code 》书中提到大于1秒的单元测试,都不叫单元测试。因此在测试中建立到服务器的连接并不是一个好的主意。首先其好事就比较长,况且服务器也并不总是处于服务状态。可想而知RGHConnection是一个令人恼火的参数。我们的设想是:若能创建某种伪造的RGHConnection对象并使CreditValidator相信它是一个真正的RGHConnection的话,就可以避开所有链接的问题了。

  首先来看一下RGHConnection所拥有的方法:

RGHConnection
+ RGHConnection(port,name,password)
+ connect()
+ disconnect()
+RFDIReportFor(id:int):RFDIReport
+ACTIOReportFor(customerID:int) ACTIOReport
+retry()
+fromPacket():RFPacket

  看上去RGHConnection中有一些方法是用来处理与连接相关的任务的:如connect、disconnect以及retry。另外还有一些业务方法。因此如果要伪造一个RGHConnection对象的话,那么这个伪造的对象也必须拥有这些方法也能提供一样的信息。

====================================分割线================================

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-11-08 22:33:16

关于如何提高代码可测试性的一些看法的相关文章

提高代码质量:如何编写函数

提高代码质量:如何编写函数 函数是实现程序功能的最基本单位,每一个程序都是由一个个最基本的函数构成的.写好一个函数是提高程序代码质量最关键的一步.本文就函数的编写,从函数命名,代码分布,技巧等方面入手,谈谈如何写好一个可读性高.易维护,易测试的函数. 命名 首先从命名说起,命名是提高可读性的第一步.如何为变量和函数命名一直是开发者心中的痛点之一,对于母语非英语的我们来说,更是难上加难.下面我来说说如何为函数命名的一些想法和感受: 采用统一的命名规则 在谈及如何为函数取一个准确而优雅的名字之前,首

11步提高代码质量和整体工作效率

  这篇文章要介绍的,是我作为专业程序员这些年来学到的能真正提高我的代码质量和整体工作效率的11件事情. 1. 永远不要复制代码 不惜任何代价避免重复的代码.如果一个常用的代码片段出现在了程序中的几个不同地方,重构它,把它放到一个自己的函数里.重复的代码会导致你的同事 在读你的代码时产生困惑.而重复的代码如果在一个地方修改,在另外一个地方忘记修改,就会产生到处是bug,它还会使你的代码体积变得臃肿.现代的编程语 言提供了很好的方法来解决这些问题,例如,下面这个问题在以前很难解决,而如今使用lam

如何提高代码质量(管理篇):代码复查

也许你是一位项目经理,也许你是一位项目骨干成员,或者开发小组长.在我发表"如何提高代码质量"的这一系统文章后,有许多网友都向我抱怨,说他无法把握整个项目组成员的代码质量.我想,这也是所有项目组普遍存在的问题吧,它通常表现为以下几个问题: 软件项目普遍存在的问题 1)新手.任何项目组成员都不可避免地出现新手,他们往往是刚刚从大学毕业的学生.这些新手由于软件开发时间太短,往往技术不成熟,没有形成良好的开发习惯,所以编写代码质量较差,问题很多.他们常常成为项目组的"鸡肋"

嵌入式操作系统能提高代码可移植性吗?

问题描述 嵌入式操作系统能提高代码可移植性吗? 同一个平台,从高级芯片到低级芯片转移都这么麻烦,何况不同平台之间的转移.编写可移植的的代码是很重要的.嵌入式操作系统能够提高可移植性? 解决方案 不同平台,不同系统的嵌入代码,没什么可移植性. 当然,和写代码的人有关,像一些开源的项目,基本上不修改或很少的修改就可以跨平台的. 但这只是软件,而不是嵌入式系统.系统的代码,移植性不高! 解决方案二: 可移植性有几个层次: 源代码的可移植性(不修改源代码,或者只修改很少的代码就可以移植到另一个平台) A

利用Java反射(Reflection) 机制提高代码的行覆盖率

在本文中,您将看到如何通过使用反射机制,在外部直接对目标类中的不可访问成员进行测试,以提高被测代码数量:以及通过修改 Cobertura 源码,使其支持通过正则表达式来过滤不需要进行单元测试的代码,以降低代码总数.代码覆盖率的提高,减少了单元测试过程中未被覆盖的代码数量,降低了http://www.aliyun.com/zixun/aggregation/7155.html">开发人员编写或修改单元测试用例的时间成本,从而提高了整个单元测试的效率. 单元测试是软件开发过程中重要的质量保证环

提高代码可读性的十大注释技巧分享_相关技巧

本文讲述了提高代码可读性的十大注释技巧.分享给大家供大家参考,具体如下: 很多程序员在写代码的时候往往都不注意代码的可读性,让别人在阅读代码时花费更多的时间.其实,只要程序员在写代码的时候,注意为代码加注释,并以合理的格式为代码加注释,这样就方便别人查看代码,也方便自己以后查看了.下面分享十个加注释的技巧: 1. 逐层注释 为每个代码块添加注释,并在每一层使用统一的注释方法和风格.例如: 针对每个类:包括摘要信息.作者信息.以及最近修改日期等: 针对每个方法:包括用途.功能.参数和返回值等. 在

提高代码性能技巧谈—以创建千行表格为例

创建|技巧|性能 微软的开发周期中很重要的一块是调整产品的性能.性能调整也是开发者应当留心的关键部分之一. 经过多年发展,业界对于如何优化Win32程序性能已经有非常多的了解. 现在开发者遇到的问题之一是不太清楚是什么导致DTHML和HTML页面运行快或者慢.当然,有一些很简单的方法--比如不要使用2MB大的图片.我们曾经使用过另外一些有趣的技巧提高了DHTML页面的性能,希望它们能帮助你改善自己的页面性能. 这里我使用了一个建立Table的程序例子.其中用document.createElem

最大限制地提高代码的可重用性

    重用是一种神话,这似乎正在日渐成为编程人员的一种共识.然而,重用可能难以实现,因为传统面向对象编程方法在可重用性方面存在一些不足.本技巧说明了组成支持重用的一种不同方法的三个步骤. 第一步:将功能移出类实例方法由于类继承机制缺乏精确性,因此对于代码重用来说它并不是一种最理想的机制.也就是说,如果您要重用某个类的单个方法,就必须继承该类的其他方法以及数据成员.这种累赘不必要地将要重用此方法的代码复杂化了.继承类对其父类的依赖性引入了额外的复杂性:对父类的更改会影响子类:当更改父类或子类中的

最大限制地提高代码的可重用性,克服传统面向对象编程方法在可重用性方面的不足

编程|对象     重用是一种神话,这似乎正在日渐成为编程人员的一种共识.然而,重用可能难以实现,因为传统面向对象编程方法在可重用性方面存在一些不足.本技巧说明了组成支持重用的一种不同方法的三个步骤. 第一步:将功能移出类实例方法由于类继承机制缺乏精确性,因此对于代码重用来说它并不是一种最理想的机制.也就是说,如果您要重用某个类的单个方法,就必须继承该类的其他方法以及数据成员.这种累赘不必要地将要重用此方法的代码复杂化了.继承类对其父类的依赖性引入了额外的复杂性:对父类的更改会影响子类:当更改父