cover_image

AI和流量回放: 革新自动化测试

作者:熊小伟 高途技术
2023年08月23日 02:04

图片

 


引言



    「自动化测试是一种思维认知」,这对工作中运用自动化测试来高效支持业务交付至关重要。如果我们没有意识到这是「思维认知」层面的,大概率会有两种结论:自动化测试是万能的自动化测试无用论。讨论为什么出现这两种结论,归根结底是由于对自动化测试的认知不足。本质上是没有阐述清楚成本和收益之间的关系,得出结论常常如下:

初学者认为只要开展了自动化测试,就能替代手工测试,并做好业务交付。相反在使用场景不明确,盲目铺设自动化用例,过度夸大自动化测试作用,结果长时间发现不了 bug。

 

     假设我们接受“自动化测试是一种思维认知”层面的说法,就可以开始讨论自动化测试在日常工作中如何去运用了。一次自动化测试的生命旅程,可以分为两段:前期维护自动化用例,后期运用用例。

图片

      在这个生命周期的前期需要考虑如何降低维护成本,后期需要提升发现问题的准确性和执行工作上的自动化占比。

       一旦我们理解了这一点,我们就可以将这次生命旅程切片成小的增量步骤,这样就有了一条实现目标的清晰路径。


用户路径


     

       每一次的自动化开始都是从代码诞生开始,以接口测试为例:一个接口的诞生到上线会经历三个阶段:技术反讲阶段定义接口协议,研发开发阶段实现接口逻辑,测试执行阶段完成覆盖。

图片

    技术反讲阶段定义接口协议,以 java 为例这个阶段开发人员只需要在 Controller 层,定义好 DTO 和 VO。如示例:
/** * 获取迭代列表 * @param request * @return */@RequestMapping("/queryList")public ReturnEntity<List<BsIterationResponseVO>> queryList(@RequestBody BsIterationRequestDTO request) {    //new 一个返回的VO    List<BsIterationResponseVO> vo = new ArrayList<BsIterationResponseVO>();    return  ReturnEntity.buildSuccessResponse(vo);}

      然后在web的子工程POM文件配置gaotu-yapidoc-plugin,后续配置好对应的yapi项目地址,测试人员就能完整拿到一份标准的接口信息包含不限于:path,RequestBody..etc。通过以上路径,我们可以接入AI模型简化接口用例的维护流程。当然这种情况是不能完全替代人工测试的,因此团队成员仍需对生成的用例进行审查和优化,以确保用例的质量和准确性。
      研发开发阶段实现接口逻辑,这个阶段开发人员,开始聚焦的接口逻辑的实现,我们给上面的接口开发一个实现类:

@Overridepublic ReturnEntity<List<BsIterationResponseVO>> queryList(BsIterationRequestDTO bsIterationRequestDTO) {    if (bsIterationRequestDTO.getPageDto() == null) {        return ReturnEntity.buildAlertResponse("分页不可为空");    }    LambdaQueryWrapper<BsIteration> bsIterationQueryWrapper = BsIterationWrapper.toQueryWrapper(bsIterationRequestDTO);    PageHelper.startPage(bsIterationRequestDTO.getPageDto().getPageNum(), bsIterationRequestDTO.getPageDto().getPageSize());    List<BsIteration> bsIterationList = bsIterationService.list(bsIterationQueryWrapper);    log.info("当前列表内容为", bsIterationList);    PageInfo<BsIteration> pageInfo = new PageInfo<>(bsIterationList);    List<BsIterationResponseVO> trafficCleanRuleResponseVOList = BsIterationWrapper.buildBsIterationResponseVO(bsIterationList);    bsIterationRequestDTO.getPageDto().setCount((int) pageInfo.getTotal());    return ReturnEntity.buildSuccessResponse(trafficCleanRuleResponseVOList, bsIterationRequestDTO.getPageDto());}

   为了覆盖这段代码实现逻辑,从代码上看我们需要有几种参数组合1、将DTO中不传参数pageDTO 2、根据不同的参数组合构造bsIterationQueryWrapper 3、根据分页覆盖边界。现实情况是如果按照实现逻辑去覆盖对于测试人员来说成本较高,为了解决这种问题我们可以采取录制线上或者线下的流量,通过流量回放补充接口自动化用例,以增加用例的覆盖范围和准确性。

  经过AI大模型+流量回放,我们可以根据代码覆盖率查看还有多少代码没有被覆盖到,最后用手动方式补全用例。总结下来:

按照用户路径,我们将自动化分三个阶段切片,前两段降低接口维护成本,我们需要借助AI大模型和流量回放来前置提升接口覆盖。但是这两种方式无法解决“业务语义”下的场景覆盖,因此不能完全替代手工维护成本。



AI 加持下的自动化测试



     讨论一次完整的自动化测试,我们可以将自动化分为3种类型:功能用例的自动化,增量变更的自动化,存量变更的自动化。

图片

    这里我们只讨论增量变更的自动化,因为最有效的AI应用的场景是基于"识别变更"能力,因此第一步我们要去通过代码变动找到影响到的接口,再结合AI能力生成对应接口用例。识别变更依赖三方开源组件包

Java Call Graph:根据class信息解析生成Java项目中类、方法调用完整链路

apidocs:Spring项目接口解析工具,用于解析项目下所有Controller类及服务接口信息

Jgit:GIt管理工具Java版,用于代码拉取、增量分析

完整实现逻辑如下:

图片

    在上述基础之上,通过chatGPT的API可以帮助测试人员快速实现API的自动生成,系统自动运行测试代码,并生层测试报告和异常日志。反馈给开发及时去发现和解决问题。


流量补全的思考



    事实上,正常业务交付中存在各种因素会打破正常的交付节奏:紧急的需求插入,人员的变更,灰度的不通过等。这种在支持快速业务迭代的背景下,测试人员会选择性的去跳过大部分的回归测试工作。而这部分用来回归的测试工作大部分是用来补全历史代码没有被覆盖到的问题。但是现实情况是,流量回放用来补全测试范围,要解决两个大问题:1、流量的噪声和数据偏移;2、存储层的mocker。当前已经有较多的实现方案解决流量噪声和数据偏移,因此我们重点讨论怎么解决存储层的mocker问题。这里有一个方案

图片

      一次完整的流量录制需要包含从用户侧的调用,以及请求下游产生的调用。如果我们将DAO外部的IO层调用使用JAVA方法进行埋点拦截录制。就可避免回放时对存储层的操作。


如何评价自动化测试成本


      

       强调一下:AI大模型和流量补全,都是为了降低自动化维护的成本,但是不能完全替代人工测试。可以持续去优化这块的能力,按照以下方向去优化:

1、通过非人工方式生成的精准用例个数占比,精准生成用例对代码的覆盖率。

2、减少执行后报错的聚合 和 排查时间

3、降低没有被覆盖的诉求场景和测试类型。

导向是:
效率=(自动化占比+覆盖率占比)/2=(迭代平均自动化case/(手工case+自动化case)*0.4+增量覆盖*0.6)/2
拦截率=bug发现方式(自动化+覆盖率)/(线上bug+线下bug)=2.75%


继续滑动看下一个
高途技术
向上滑动看下一个