前言
测试框架的设计需要适合被测试系统,要依据当前测试问题和系统后续的发展合理设计,避免过度设计导致维护成本徒增。同时被测系统也要依据测试方法提供适当的便利,以提高被测系统的可测性。
本文讲述的是基于动态代理的接口测试设计,在思考如何测试之前需要先了解下被测系统。
简单介绍两个被测系统
一、交易订单系统
交易订单系统基于状态机实现,包括正向流程状态机、逆向流程状态机,下图为正向流程其中的一条链路:
二、支付中心账户系统
支付中心账户系统中不存在状态变更,但所有的操作基本都是对账户余额的操作。所以账户系统可以理解为以账户上下文为纽带对账户金额进行操作的系统,如充值操作使账户可用余额增加,提现操作使账户可用余额减少。
上面两个系统有一个共性,被测系统都可以抽象为由某个特定条件下触发某个操作引起某个主体发生特定变化的系统,如订单操作引起订单状态变化,对账户的操作引起账户金额变更。
如何自动化测试类似系统呢?
我们早期接口用例实现方式:
早期我们编写了很多校验方法用于不同属性的校验,如校验订单状态的方法、校验订单按钮的方法、校验订单服务窗内容的方法。在每个订单操作后依次调用该操作对应的校验方法并传入期望值。早期单条用例可读性可接受,从用例即可知道当前做了什么操作,引起了什么变化,期望值是什么。但也存在一些问题,如:
那么如何解决这些问题呢?仅仅解决眼前的问题就能满足吗?
我们先看下订单系统的一个特点:一组明确的条件可以定义当前订单所处的状态、UI展示等信息。
账户系统如何描述呢:操作充值,导致了余额增加,且条件和结果相对于订单要更加简单。
基于上面的描述,如何改进测试系统呢?似乎只需要拦截操作并构建操作前后的上下文,校验模块通过上下文获取需要的条件匹配当前被测主体的状态、UI进行校验即可。如何拦截?这里就用到了拦截器,依赖JDK中的动态代理实现。
在介绍改进后测试系统结构前先介绍下动态代理
上图是动态代理的UML图,代理类与真正的实现类都继承了抽象的主题类,这样代理类和实际类有相同的方法,可以保证对上层调用方使用的透明性。
写法:
编写一个委托类的接口,即Subject接口
实现一个真正的委托类,即RealSubject类
创建一个动态代理类,实现InvocationHandler接口,并重写invoke方法
那么改进后的用例为:
上图为单个上下文的用例写法,实际测试时往往有多个被测主体,就会有多个上下文维护,多个校验分发的switch。
方案的优缺点如下:
优点:
缺点:
动态代理在交易测试框架中应用
目前接口测试框架中有两个动态代理
动态代理整体的使用理念是拦截对目标类的操作并在目标类的基础上增加切面逻辑,在切面上添加扩展子系统。这就是上面没有展开说的框架能力扩展性。
总结
最后总结一下,设计模式只是抛转,玉是测试系统中的每个模块的设计。后续还有同学介绍如何在当前模式下设计可扩展的清结算校验模块以应对业务高速发展。