作者:京东物流 刘红妍
导读:
在主动化测试实践中,为了更好的契合被测事务场景,需求不断优化结构分层结构。本文结合产品模块化思路,意在介绍经过战略方式改造原本杂乱分支句子代码,经过理论讲解、思路剖析、计划规划、及代码演示,供给主动化脚本重构的落地计划。
在本年的灵敏团队建造中,我经过Suite履行器完结了一键主动化单元测试。Juint除了Suite履行器还有哪些履行器呢?由此我的Runner探索之旅开端了!
1 痛点
跟着运送事务场景的不断丰富和主动化脚本量的不断累积,日常在review用例时发现,现在大家仍停留在针对需求定制化用例编写,无法进步用例可复用性和可编列性。当事务流程中间某一环节发生变化时,不但需求重新修正脚本,还会影响当前使用其他用例履行成果。所以,如何规划高复用性脚本成为现在主动化建造的关键节点。
规划理论
了解,首要 MCube 会根据模板缓存状况判别是否需求网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产品转化为视图树的结构,转化完结后将经过表达式引擎解析表达式并获得正确的值,经过事情解析引擎解析用户自定义事情并完结事情的绑定,完结解析赋值以及事情绑定后进行视图的烘托,最终将方针页面展现到屏幕。从规划稿动身,进步页面搭建功率,亟需解决的核心问题有:
2.1 规划理念
根据面向对象程序规划理念,规划者应遵从高内聚与低耦合准则,一般程序结构中各模块的内聚程度越高,模块间的耦合程度就越低。高内聚意味着一个类所能供给的功用应该是相关的,即一个类不要规划得包括很多互不相干的功用,低耦合代表要合理规划模块的颗粒度,即要保证一个模块可独立存在,降低模块之间杂乱依靠关系。
2.2 战略方式
战略方式定义了一系列的算法,将每一组相关的算法封装起各个战略分支,从而将分支相关的代码躲藏起来,而且使它们之间能够相互替换。战略方式让算法的变化不会影响到运用算法的客户,期望能够进步程序的可扩展性。
解决思路
了解,首要 MCube 会根据模板缓存状况判别是否需求网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产品转化为视图树的结构,转化完结后将经过表达式引擎解析表达式并获得正确的值,经过事情解析引擎解析用户自定义事情并完结事情的绑定,完结解析赋值以及事情绑定后进行视图的烘托,最终将方针页面展现到屏幕。从规划稿动身,进步页面搭建功率,亟需解决的核心问题有:
3.1 基本思路
根据运送事务同一个流程存在不同场景,如询价服务接上游下发询价单节点,需求区分来历履行不同逻辑,现在规划五个算法才能,根据后期事务不断扩展,还会有更多算法加入进来,这个时分需求考虑一个好的结构对代码进行优化。或许前期大家经过if…elif…else 分支句子就可完结,但在考虑体系的健壮性和可保护性,这里就不能很多运用if分支句子。因为每一种算法才能的代码量极大且算法参数几十个,在跟着更多上游接入或许存在十几个乃至更多else分支,很简单顾此失彼,牵一发而动全身。所以,运用战略方式规划一系列算法,再供用例拼装调用,进步代码的可读性和可复用性。
3.2 计划剖析
长处:
-
代码解耦,便于保护;
-
防止运用难以保护的多重条件选择句子;
-
能够运行时动态切换算法;
-
开闭准则。无须对上下文代码进行修正,就能够添加新的代码。
缺点:
-
如果算法逻辑,较为固定,不常常修正,运用战略方式只会添加代码量
-
必须知道所有的详细战略类及它们的区别。
计划概述
了解,首要 MCube 会根据模板缓存状况判别是否需求网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产品转化为视图树的结构,转化完结后将经过表达式引擎解析表达式并获得正确的值,经过事情解析引擎解析用户自定义事情并完结事情的绑定,完结解析赋值以及事情绑定后进行视图的烘托,最终将方针页面展现到屏幕。
4.1 环境依靠
Laputa结构简介:
Laputa结构根据 Pytest 集成了对API接口主动化, 以及对 Web使用, 移动端使用和 Windows 桌面使用 UI 等主动化的才能。具有可视化的Web界面东西, 便于装备履行规则,关联履行脚本, 触发用例履行,检查履行成果。供给CI集成服务,调用Jenkins API跟踪继续集成成果,开放接口,完结流水线主动化测试。
图1 主动化结构架构图
4.2 分层改造
图2 主动化用例分层图
4.3 战略规划
图3 战略方式规划图
4.4 操作过程
- 将频繁修正的算法进行抽取,独立为详细的算法类;
2.创建笼统基类,完结一个约好的笼统战略办法;
-
所有独立的算法类,必须完结基类中的笼统战略接口;
-
树立上下类,该类能够动态的对算法进行setter,创建调用详细算法的办法,上下文可经过该办法与详细的战略交互;
-
客户端进行调用,传入详细的算法类,上下文动态履行详细的算法使命。
规划实践
了解,首要 MCube 会根据模板缓存状况判别是否需求网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产品转化为视图树的结构,转化完结后将经过表达式引擎解析表达式并获得正确的值,经过事情解析引擎解析用户自定义事情并完结事情的绑定,完结解析赋值以及事情绑定后进行视图的烘托,最终将方针页面展现到屏幕。
5.1 询价接单接口改造
如源代码结构,根据不同事务来历,写在一个办法里经过if…else…分别拼装场景,一旦上游任一体系存在需求变化,当前接单接口调用逻辑需求变化:
【python】
def receive_enquiry_bill(**kwargs):
params=[{}]
params[0].update(kwargs)
if params[0].get("enquirySource") == 8:
pass
elif params[0].get("enquiryWay") == 2 and params[0].get("payMode") == 2:
pass
elif params[0].get("enquiryWay") == 2 and params[0].get("payMode") == 3:
pass
if params[0].get("enquirySource") == 46:
pass
if params[0].get("enquirySource") == 20:
pass
改造结构:
上下文类
【python】
class AlgorithmStrategy(object):
def __init__(self, algorithm_name):
self.algorithm_name = algorithm_name
@property
def algorithm(self):
return self.algorithm_name
@algorithm.setter
def algorithm(self, name):
self.algorithm_name = name
def execute_algorithm(self, params):
return self.algorithm_name.execute(params)
算法基类:
【python】
class CreateEnquiryBillBaseAlgorithm(ABC):# 算法才能基类
@abstractmethod
def read_params(self, **kwargs):
scenario=kwargs['scenario'] if "scenario" in kwargs and kwargs['scenario'] else 'base'
return resource_custom_data[self.__class__.__name__][scenario][0].update(kwargs)
@abstractmethod
def execute(self, params):
return jsf_receive_enquiry_bill(data=json.dumps(params)
不同算法:
【python】
class CreateTFCEnquiryBill(CreateEnquiryBillBaseAlgorithm):
def read_params(self, **kwargs):
params = super().read_params(**kwargs)
params[0].update({"businessCode": kwargs['businessCode'] if 'businessCode' in kwargs else f"TJ{laputa_util.date_time_str(fmt='%y%m%d')}{laputa_util.get_random_num(8)}","receiveBeginTime": tms_util.data_time_str(minutes=100),"deliveryBeginTime": tms_util.data_time_str(minutes=180)})
return params
def execute(self, params):
return super().execute(params)
class CreateECLPClodEnquiryBill(CreateEnquiryBillBaseAlgorithm):
def read_params(self, **kwargs):
# 若当前场景参数与根底参数改动较大主张直接在Yaml里另写Key
params = super().read_params(**kwargs)
params[0].update({"businessCode": kwargs['businessCode'] if 'businessCode' in kwargs else f"ECO{laputa_util.date_time_str(fmt='%y%m%d')}{laputa_util.get_random_num(8)}","receiveBeginTime": tms_util.data_time_str(minutes=100),"deliveryBeginTime": tms_util.data_time_str(minutes=180)})
return params
def execute(self, params):
super().execute(params)
return jsf_do_assign(data=json.dumps(params))
算法注入运用:
【python】
def receive_enquiry_bill(algOne=None, sceOne=None, **kwargs):
"""
Args:
algorithm: 事务类型
scenario: 测试场景:履行过程,履行数据
Returns:
"""
if algorithm:
# 选用字典方式进行手动注册算法,由python动态查找
st = {"TFC": CreateTFCEnquiryBill(), "ECLP冷链": CreateECLPClodEnquiryBill(), "TC": CreateTCEnquiryBill(),"终端用车": CreateTerminalEnquiryBill()}
query_algorithm = st.get(algOne)
return query_algorithm.execute(query_algorithm.read_params(scenario=sceOne, **kwargs))
else:
pass
当有需求变化,只需修正其一战略规则内部代码,如【分单战略需求】,除运送内部体系TFC下发询价指定个别标签,其他上游没有添加标签下发功用,则只需修正CreateTFCEnquiryBill()代码即可。
5.2 Common用例拼装
拼接task客户端办法组成case,运用feature拼装测试数据,数据驱动测试办法履行。
【python】
@pytest.mark.parametrize("params", test_data('test_enquiry_core'), indirect=True)
def test_enquiry_core(params):
enquiry_code = receive_enquiry_bill_core(**params).get("data")
return quote_enquiry_bill_core(enquiry_code=enquiry_code, **params)
总结
了解,首要 MCube 会根据模板缓存状况判别是否需求网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产品转化为视图树的结构,转化完结后将经过表达式引擎解析表达式并获得正确的值,经过事情解析引擎解析用户自定义事情并完结事情的绑定,完结解析赋值以及事情绑定后进行视图的烘托,最终将方针页面展现到屏幕。
跟着运送八大产品建造方向逐渐清晰,主动化渠道需求从使用维度重构到产品维度,在脚本不断融合宽和耦过程,如何在新的分层方式规划高复用性脚本,需求大家结合各自事务条线不断优化改进。