背景
接口自动化一直以来都是质量保障的重要一环,在接口自动化日常工作中,我们致力于场景的覆盖与结果校验。随着业务的高速发展,高效保质的迭代自动化用例成了我们的一个研究方向,其中用例结果校验的及时性、完整性、可维护性是我们遇到的一个很大的难题。
痛点
笔者所属团队,日常工作是围绕商品相关业务展开。在平时的自动化脚本编写中,我们发现:
商品模型返回字段多(一个模型一般有几十到上百个字段),逐字段人工断言,成本较高;
商品原自动化工程里有大量重复的校验逻辑,梳理成本较高;
随着业务发展部分非核心字段逐渐也变成了核心字段,例如商品编码,现在已经成为了很多商家 ERP 系统识别商品数据的关键标识;
部分字段更新如何保证其他字段没有被更新掉,尤其是一些存在默认值的字段,更新的时候极易被默认值覆盖。
传统校验方式我们一般只会校验核心字段或者用例相关字段,比如:价格、库存等等。但是基于上述第 3、4 点原因,我们发现需要去做全字段校验,而 全字段校验学习成本高、维护代价大、代码熟悉程度要求高 是面临的三大难题,那么如何做到快速、优雅全字段校验成为我们必须去解决的问题。
目标
我们的目标是争取对用例返回字段进行全量校验,同时也要大幅提升用例编写效率。
场景分析
我们对现有的自动化用例场景进行分析,得到以下结论:
待测试的后端接口一般分为操作接口和查询接口两类;
一个操作类接口落库后的数据一般会对应一个或者多个查询类接口;
查询类接口会返回大量业务字段。
接下来我们分别针对操作、查询这两类接口进行处理。
实践前的准备
为了让大家更好的理解后续内容,我们先对有赞目前的测试环境进行一个概述:(详细内容可参见:有赞环境解决方案),环境示意图如下:
目前有赞测试环境采取的是弱隔离策略,分为基础环境和测试环境。基础环境部署应用的代码分支版本同线上一致,项目环境部署的则是应用特性分支代码,两个环境共用一套存储。当一个业务请求进来时,根据一个标志位(内部简称 sc)来判定是否要走到项目环境,如果请求的是项目环境且项目环境有该应用,那么此请求会被路由到项目环境中,否则请求到基础环境里。
实践
下面介绍一下我们整体思路:
读接口校验:分别请求基础环境和项目环境,对比两个环境的返回结果,如果一致说明代码改动对此接口用例没有影响,进而可以判定用例校验通过;
写接口校验:一般写接口落库的数据可以通过一个或者多个读接口拿到,那么同样的写接口分别在基础环境和项目环境进行落库,只要对应环境的读接口返回结果一致,那么校验通过;
不论读写,都有一些随机字段,为了降低接入成本,需要提供计算忽略字段能力。
读接口校验思路
读接口校验相对简单,分别请求基础环境和项目环境,根据返回值的异同来判定用例是否通过。我们可以借鉴 AOP 的思路,切入点为 dubbo 请求前后,在切面中分别请求基础环境和 sc 环境,根据两次返回值来判定用例是否通过。
整体流程如下:
PS:sc 环境即为部署了应用特性分支代码的环境
根据上述流程图,可以看到重点在忽略字段生成以及比对逻辑,思路如下:
dubbo 接口返回值基本都是一个对象,参考 jsonpath 思路,通过递归可以获得一个 Map(k:路径,v:路径值)。举个例子,返回值的类为
假设返回对象 itemId 为 1,shopId 为 2,那么拆解出 Map 为{"/itemId":“1”,"/shopId":“2”},对象的比较转换为 Map 的比较。通过两次基础环境返回值的比较,不同的路径值对应的路径,就是下次比较要忽略的路径。
对象拆解成 Map 核心代码如下:
按照上述代码拆解出项目环境返回值对应的 Map(k:路径,v:路径值),根据上一步骤获得的忽略路径和基础环境返回值,即可计算出两次返回值一致与不一致的字段路径。代码不再赘述,感兴趣的读者可以在留言区讨论。
写接口校验思路
写接口相对读接口会复杂一些,篇幅所限,主要讲解核心逻辑。写接口校验整体逻辑与读接口类似:总共触发三次请求,前两次所有读写接口在基础环境执行,计算出忽略字段以及记录下来基础环境返回值。第三次所有请求都在项目环境,获取接口在项目环境的返回值,接下来排除掉忽略字段,比较基础环境和项目环境接口对应的返回值即可完成校验。
整体流程如下:
重试时机很重要:写接口不同于读接口,读接口可以在不同环境里多次重试,而写接口考虑到幂等性,在数据清理之前是不能发起重试的。清理数据可能在 afterMethod、afterClass、afterTest、AfterSuite 各种阶段,为了保证数据清理代码在第二次执行之前被执行,我们考虑实现监听器方法 ISuiteListener.onFinish 方法来触发第二次。
如何触发第二次执行:TestNG 除了通过 xml 文件触发,还支持通过新建对象来触发执行,我们采用新建 TestNG 对象来触发第二次执行。
忽略字段计算时机:切面需要在用例执行第 2 遍时候进行计算忽略字段,执行第 3 遍进行接口返回值的比较。
测试用例中一般都存在着读、写接口两类用例,只有写操作用例需要在三遍 suite 中均执行,读操作用例只需要在最后一次 suite 执行即可。综合考虑,前两次的 suite 希望只执行写操作的 case。因此实现 testNg 监听器方法 IMethodInterceptor.intercept,拦截器上只返回此次 suite 执行的测试用例,从而达到前两次只执行写操作的 case。我们采用在写操作用例挂上一个注解,标识为写操作用例,方便拦截器判断用例类型。核心代码如下:
不足
目前仅支持 dubbo 接口,后期考虑扩展到前端 node 层接口校验
目前强依赖基础测试环境,为了更好的兼容性,后期考虑引入存储方式来解除基础环境依赖
本文转载自公众号有赞 coder(ID:youzan_coder)。
原文链接:
https://mp.weixin.qq.com/s/_9HIrichpu4sXXXASTWVBQ
活动推荐:
2023年9月3-5日,「QCon全球软件开发大会·北京站」 将在北京•富力万丽酒店举办。此次大会以「启航·AIGC软件工程变革」为主题,策划了大前端融合提效、大模型应用落地、面向 AI 的存储、AIGC 浪潮下的研发效能提升、LLMOps、异构算力、微服务架构治理、业务安全技术、构建未来软件的编程语言、FinOps 等近30个精彩专题。咨询购票可联系票务经理 18514549229(微信同手机号)。
评论