测试开发之路—可读性,可维护性,可扩展性(2)

发表于:2016-6-02 08:27

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:ycwdaaaa    来源:51Testing软件测试网采编

  前言
  上一章结尾的比较着急,有一个很常用的设计没有讲,就是 可插拔式设计 ,这次我在这里补充一下吧。平时工作比较忙,我有时间写点就写吧,以后不会再有那么大篇幅的东西了. 因为我发现,篇幅一长我就着急,一着急很多东西我就讲得很浅就过去了,我应该检讨。下面我们来一步一步实现这个机制。
  为了变化,将算法抽象出来
  举个常见的例子,假如我们现在有一个接口测试框架,它是测试http协议的接口,一切工作的很正常。但是如果突然某一天开发那边的架构变化了,为了负载均衡他们将模块分离,并用RPC协议作模块间的沟通。 于是乎一个基于RPC协议的java接口测试需求出现了。即便不是RPC协议接口。普通的java接口测试需求也有很多有获取方式,有用spring管理的,有单纯用Jar包的,也有webservice的。我们不可能一次性的把所有的可能性都想到。只能是碰到的时候再实现。但是我们预料到了之后的变化,就需要留下一种策略能让框架自由的选择哪一种方式的同时,保证可读性,可维护性和可扩展性。这时候千万别if else起来没完,我上一章已经讲过了大堆if else和for 循环嵌套的弊端了。
  所以这时候我们决定把每种接口的获取方式都看成一个算法。这些算法有统一的接口,其他模块调用的时候,是 面对这个接口编程 的,这个思想很重要。现在我们定义这么一个接口。
/**
* 工厂接口:工厂方法返回的是RD待测接口的对象
* 目前的调用方式为:spring,jar包,http接口。所以预计有三个具体工厂类。如果以后出现新的调用方式,实现此接口即可
* 具体工厂类一定要穿件在:com.bj58.daojia.test.InterfaceTool.data.classFactory这个包中。
*
* @author Gaofei Sun
*
*/
public interface IInvokeObjectFactory {
public Object getInvokeObject(String type);
}
}
  这个接口是所有算法的基类,调用方只知道这个接口,针对这个接口编程。每个字类其实都是个工厂类,责任就是给框架创建被测的接口对象,根据不同的创建方式有不同的实现,我们把每个实现都看作一个算法。下面我们看看通过Spring 管理dubbo协议的实现
/**
* 具体工厂类:使用spring获取待测对象
*
* @author Gaofei Sun
*
*/
@Component
public class Spring implements IInvokeObjectFactory {
public static String zkAddress = "zookeeper://192.168.120.88:2181";
// BeanFactory beanFactory = null;
public Spring() {
// beanFactory = new ClassPathXmlApplicationContext("./spring-dubbo.xml");
}
@Override
public Object getInvokeObject(String type) {
try {
System.out.println();
Class temp = Class.forName(type);
return getInvokeObject("daojia_services_interface", temp);
} catch (Exception e) {
e.printStackTrace();
Assert.assertTrue("Sping获取目标对象失败,请检对象名称是否正确,或配置文件是否正确。传入的对象名:" + type, false);
}
return null;
}
private static Object getInvokeObject(String group, Class interfaceClass) {
try {
ApplicationConfig application = new ApplicationConfig();
application.setName("dj-card-client");
RegistryConfig registry = new RegistryConfig();
registry.setAddress(zkAddress);
registry.setGroup(group);
// System.out.println("registry build completed.");
ReferenceConfig reference = new ReferenceConfig();
reference.setApplication(application);
reference.setRegistry(registry); // 多个注册中心可以用setRegistries()
reference.setInterface(interfaceClass);
reference.setVersion("1.0.0");
reference.setCheck(false);
// System.out.println("reference build completed");
Object obj = null;
try {
obj = reference.get();
} catch (Exception e) {
System.out.println("error:" + e.getMessage());
} finally {
// System.out.println("finally." + "houseLeaveService:");
}
return obj;
} catch (Exception e) {
e.printStackTrace();
Assert.assertTrue("Sping获取目标对象失败,请检对象名称是否正确,或配置文件是否正确。传入的对象名:" + interfaceClass.toString(), false);
}
return null;
}
  上面是我们当初通过Spring 去获取dubbo协议的对象的实现,可以看到代码不算少吧。我们还有HTTP的协议,SCF协议(公司自主研发的协议),SF协议(同样是公司自主研发的),每一种协议都需要一些代码去获取对象, 我们想象一下每次用if else 管理的话得多乱.以后每次来换新的协议你都跑来改代码,加个if 分支也是挺痛苦的 . 我们有了接口,有了实现. 现在我们再用一个工厂类来生产这些算法。
  /**
  * 创建带测接口对象工厂的工厂类
  * @author Gaofei Sun
  *
  */
  public class InvokeObjectFactoryFactory {
  private static ConcurrentHashMap<String, IInvokeObjectFactory> map = new ConcurrentHashMap<String, IInvokeObjectFactory>();
  public static IInvokeObjectFactory getInvokeObjectFactory(String type) {
  String temp = convertStringTo1lower(type);
  return (IInvokeObjectFactory) SpringContext.getBean(temp);
  }
  上面的代码很简单,由于我后来把对象都交给spring管理了,所以我们创建算法对象的话,连if else也不用了。直接传一个name进来用spring来为客户端创建算法。于是乎客户端就变成了这样。
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号