一、背景介绍
黄金眼PAAS化数据服务是一系列实现相同指标服务协议的数据服务,各个服务间按照所生产指标的主题作划分,比如交易实时服务提供实时交易指标的查询,财务离线服务提供离线财务指标的查询。黄金眼PAAS化数据服务支撑了黄金眼APP、黄金眼PC和内部各类大屏的数据查询需求。为了业务能进行正确的数据洞察和决策,需要保证PAAS化数据服务提供数据的准确性。
随着业务需求的快速迭代,数据服务经常需要对查询口径,查询维度,查询指标做调整,因此需要高效的自动化回归测试手段来保证每次需求迭代的质量。PAAS化数据服务的自动化测试面临着一些问题:
-
**查询场景多:**指标服务协议支持查询的指标和维度数量多,手动测试难以覆盖线上所有请求场景;
-
**请求参数复杂:**指标服务协议请求参数是复杂嵌套对象,已有的Python DIFF工具难以通过http的方式调用数据服务JSF接口;
-
**返回参数对比难:**指标服务协议返回参数通过索引来定位字段名称所对应的值,如果字段索引不一致,或者数据集合内元素无序,容易造成对比误报。
针对请求场景的多样性和指标服务协议的特殊性,我们实现了面向黄金眼PAAS化数据服务的专用DIFF工具,通过录制线上流量,再回放到测试和线上环境中,对比返回结果,并对请求回放效率和对比结果误报问题做了针对性的优化。这种方式能够保证线上查询场景的全覆盖,减少手动构造请求场景的人工介入,并且提供足够高效的自动化回归测试能力赋能研发自测。
经过一段时间的建设和迭代,黄金眼PAAS化数据服务DIFF工具已经实现对黄金眼交易实时,交易离线,财务离线三个服务的覆盖,月均DIFF执行次数超过40次。
下面本文将介绍黄金眼PAAS化数据服务DIFF工具建设中遇到的挑战和实践经验。
二、问题和思路
2.1 PAAS化协议调用难点
黄金眼PAAS化服务实现的都是相同的指标服务协议,其请求参数是一个复杂的嵌套对象,并且criterions集合中的每个过滤条件对象使用Jackson的@JsonSubTypes注解实现多态解析。根据JSF团队http调用文档的说明,调用具有复杂嵌套对象接口需要给每个嵌套对象加上"@type": “包路径+类名”,并且推荐使用 JSON.toJSONString (instance, SerializerFeature.WriteClassName) 生成具有类型特征的JSON串,如下图所示,而生成前又必须使用Jackson将请求参数反序列化成实例对象。如果执着在python脚本中使用http方式调用此类JSF接口,需要自己识别每个过滤条件的实现类。为了实现PAAS化数据服务JSF接口的便捷调用,使用java编写的DIFF工具因此诞生。
2.2 主要挑战
Java编写的DIFF工具可以解决PAAS化数据服务接口调用的问题,但在现有DIFF脚本的实际使用中,面临着以下两个挑战:
2.2.1 请求回放效率问题
单线程回放
对所录制的请求进行接口调用和结果对比,是单线程去遍历请求List来实现,单个请求在对线上和测试两个环境的接口调用成功后,再进行返回结果的对比,只有对比结束后才去回放下一个请求。但实际上,上一个请求和下一个请求的回放之间,并不需要有调用时序。这种使用单线程进行请求回放的方式,会极大降低执行效率,导致diff执行时间过长。
同步调用接口
除此之外,对于线上和测试两个环境接口的调用,采取的是同步的方式,一个环境的接口返回结果后,才去调用下一个接口。同理,两个环境的接口调用之间,没有依赖关系,一个环境接口的返回值不会影响下一个接口的调用,只需要保证两个环境接口调用都有返回值后,再进行结果对比即可。
2.2.2 对比结果误报问题
索引不一致
PAAS化协议的返回参数结构如下所示,可以看到body.data数据集合具有最多的信息要素,是主要的对比目标,meteData.metaIndex数据索引定义了数据集合子元素中每个值代表的具体字段名称,比如[1234,12345.41,“11068”]中的三个值分别代表成交父单量、成交金额和主品牌id。如果两个环境接口的返回值字段名称索引不统一,但根据索引实际取到的字段名称所对应的值相同,这种情况下直接遍历数据集合子集合去对比,会得到对比有差异的结论,但实际上