走出回归测试困境,爱奇艺精准测试体系建设
8月7日下午,爱奇艺技术产品团队举办了第17期“i技术会”,本次技术会的主题是“智能化、精准化测试前沿探索”,本次沙龙与TesterHome社区联合举办。
其中,来自爱奇艺的技术专家苏慧为大家带来了“爱奇艺精准测试体系”建设的分享,讲述了爱奇艺精准测试实践过程中,为了走出回归测试困境、实现精细化测试能力建设进行的一系列技术攻坚,例如采用自研代码覆盖率工具,改变原生代码覆盖率工具实现方式,支持服务端多人并行测试以及微服务调用链串联,最终实现回归测试质量与效率双向提升。
福利!!! 关注公众号,在后台回复关键词“测试”,就可以获得本次i技术会嘉宾分享PPT和录播视频。
以下为“爱奇艺精准测试体系建设”干货分享,根据【i技术会】演讲整理而成。
01
为什么要做精准测试?
精准测试是为了解决回归测试的质量和效率问题。
在具体的业务中,产品功能的迭代、缺陷修复等等是极为常见的需求场景,但这些看似微小且常见的改动都有可能会对产品庞大的历史功能产生影响,所以需要通过回归测试进行质量保障。
回归测试在多个场景都可能会被引入,除上文提到的两种外,测试完成之后需求发生变更、合并代码上线阶段、客户端封版之前的集成测试阶段等等都会涉及。
而在回归测试的过程中,首先会遇到测试范围如何选取的问题。
如果每次都对全量用例进行回归,随着项目的快速迭代,用例库中的用例数量也会不断攀升,回归成本也将居高不下;如果不做全量回归,就需要人工判断回归范围,而这往往依赖于测试同学和研发同学的沟通、测试同学的经验积累或部分同学的代码走读。这些方法都较为主观,往往不够准确,容易出现质量风险。根据爱奇艺历史数据,由历史功能影响引入的问题比重达到了50%。
所以精准测试就是要解决传统回归测试的问题,通过技术的手段让回归测试变得精准,提升其质量和效率。其基本方法为,在用例执行过程中,通过代码覆盖率工具记录用例与代码的映射关系,保存在知识库中。当代码发生变动时,可以通过查询知识库,准确找到本次变更的代码影响了哪些测试用例,有针对性地进行回归。这样就能够达到提高测试效率,同时减小质量风险的目标。
02
爱奇艺精准测试体系建设
爱奇艺精准测试体系主要有以下三个特点:
(1)从使用场景上看,支持客户端和服务端多端使用,支持手工和自动化测试场景,和爱奇艺内部的多个平台联动,打通了整体使用流程;
(2)从实现层面看,可以准确捕获单个用例的代码覆盖。服务端能做到系统级串联,客户端则能实现多组件整合;
(3)从精准度方面看,已实现用例和代码分支或代码块级别的关联。
下图是爱奇艺精准测试体系整体架构图,中间的红色部分是核心的精准测试服务,负责建立用例和代码映射关系知识库并根据GIT提交记录计算测试范围及影响范围。
在采集用例执行代码的过程中,不同的终端需要用到的代码覆盖率工具也会不同。目前,爱奇艺精准测试体系已经能够支持安卓端、iOS客户端以及服务端。
在与外围平台的集成上,服务端可以和环境平台结合,通过环境平台实现代码覆盖率工具的安装;客户端则可以和构建平台做集成。
因为爱奇艺当前大部分使用场景为手工测试,因此我们也将其和公司内部用例管理平台进行了打通,配合使用。
03
精准测试实现方案与关键问题解决
精准测试的实现方案主要有两个关键步骤,第一步是在用例执行过程中采集用例和代码的映射关系,建立知识库。第二步是当代码发生变更时,通过查询知识库,进行测试范围的精准推荐。
1.用例代码关系采集实现方案及关键问题解决
这一步骤首先要借助代码覆盖率工具。
目前,在爱奇艺,代码覆盖率工具的安装可以通过与构建平台的结合,在构建过程中自动安装,无需人工介入。构建平台可以灵活控制本次编译是否开启覆盖率功能,如果开启,客户端会编译带有覆盖率工具的安装包,安装到移动设备上。服务端则会将覆盖率工具挂载到被测应用上,然后部署到测试环境中。同时,构建平台会把本次编译产物和编译信息,发送给精准测试服务,用于后续代码覆盖解析。
工具安装后测试服务器或者APP上即可以执行测试,手工或自动化执行均可。
用例执行结束后,精准测试服务会采集当前测试的代码覆盖率数据,并进行一系列处理如单个用例代码覆盖的匹配、服务端系统级串联、客户端多组件聚合等,最后利用代码覆盖率数据、编译的产物以及源代码,解析得到当前用例所执行的代码信息,包括用例执行了哪些类,哪些方法及基本的语句块,并将其保存在知识库中。
在这一步骤中,存在以下几个关键问题:
1.关键问题一:服务端单用例代码采集
现实中,我们的测试环境往往无法独占,如果采用开源的代码覆盖率工具,会出现以下问题:当多个人在同一环境并行进行测试的时候,我们采集到的是这段时间所有测试请求覆盖的代码,而无法知道具体的代码行与用户之间的对应关系,进而影响对测试范围的判断。
为了解决这个问题,爱奇艺提出了两种方案。
第一个方案是给每个测试同学搭建一套独立测试环境,保证在一段时间内这个测试环境没有其他人的干扰。另外,我们还要保证测试用例之间是串行执行的,不能并发。
这个方案原理非常简单,但落实到操作上,给每个人搭建一套测试环境接入成本较高,保证所有测试用例串行执行,执行效率较低,落地的可能性极小。
因此,第二个方案就应运而生了。爱奇艺采用自研的代码覆盖率工具,改变原生代码覆盖率工具的实现方式,让它能够支持多人使用、并行测试。
上图的上半部分是原生代码覆盖率工具,它只能获取到一段时间内,所有测试请求覆盖的代码,如果同一测试环境中、同一时间内有多人共同使用,采集到的代码就无法准确映射到单个测试用例上。
下半部分是爱奇艺自研的代码覆盖率工具,通过字节码插装技术,给每一个请求打上一个请求维度的标识,然后把代码覆盖信息按照请求维度进行记录和保存。同时,它会拦截每个请求的请求数据,比如请求接口、参数、header信息(包含来源用户IP)等。这样就可以知道当前用户或本条用例执行了哪个测试请求,它所覆盖的代码是什么,解决了多人同时使用测试环境的问题。
2.关键问题二:服务端微服务架构
为了提升服务的可扩展性,目前我们的很多业务都会采用分布式的微服务架构。以支付业务为例,当用户发起支付请求时会经过网关层服务,转发到产品层服务,然后调用具体支付渠道服务,整个过程中还会用到基础服务层的多个基础服务,共同完成一次请求任务。
但是在测试的过程中,我们可能只会从最外层发起调用,执行系统级测试。这个过程中有一个关键问题:在采集用例对应的代码映射关系时,怎么把底层微服务串联起来,体现整体(系统级)代码覆盖情况?此外,在衡量代码改动影响范围时,也不能仅考虑单个模块的影响,服务间调用关系的影响也必须纳入考量范围之中。当底层服务发生改动时,我们需要知道它所关联的是具体外侧模块上的哪个用例。最后,对这类微服务底层模块变更的影响范围的判断也比较困难,容易出现问题。
为了解决微服务串联的问题,爱奇艺参考了APM工具原理,给每个请求打上一个链路级别的标识,即链路的TraceID,放进请求的Header里,在不同微服务模块之间传递。我们只需获取每个请求的TraceID,具有相同TraceID的请求就表示在同一个链路上,把同一链路上所有请求执行的代码都和测试用例关联起来,就可以完成系统级的串联。
3.关键问题三:客户端多组件聚合
客户端多组件聚合的问题和服务端微服务架构问题有些类似。
近年来,客户端开发模式逐渐向组件化的方向发展,例如对于安卓系统来说,一个组件对应一个SDK;对于IOS,一个组件则是一个POD。
组件化一方面是为了让各个业务线进行独立的代码管理和开发,降低代码耦合;另一方面,是为了抽取出一些基础的组件以便复用。以爱奇艺app为例,其主工程中包含很多提供基础功能的基础组件如网络、播放、搜索、支付组件等等,还包括各个垂线业务的业务组件。所以在采集用例覆盖代码的时候,我们不能仅考虑主工程代码,还要将各个组件的代码聚合起来。
聚合多组件的方法是:在打包平台上打包的时候,主工程和每个独立的组件都会把各自打包的编译产物和编译信息上传到存储服务中。爱奇艺从APP获取覆盖率数据之后,需要找到每个组件的编译产物进行解析。这首先需要找到主工程中组件依赖关系管理文件,比如IOS工程中的podfile。其次,通过解析podfile找到当前工程依赖的每个组件对应版本的编译产物,就可以实现多组件的解析和聚合。
2.测试范围精准推荐的实现方案及关键问题解决
用例代码映射关系采集完成之后,便要利用知识库进行测试范围精准推荐。
当需求提测或者代码发生变更,可以通过手工触发或者CICD流水线自动触发测试范围评估。我们首先要获取代码变更的起始和终止版本,通过git查询出两个版本之间所有代码提交记录,解析发生变化的代码,然后反查知识库,计算出当前需要测试的范围。
如果是手工测试,可以将影响用例自动生成手工执行的测试计划。如果是自动化测试,在流水线里触发相应自动化用例执行即可。
但在第一个版本的精准推荐完成之后,仍然存在部分推荐效果不佳的状况。例如当底层或公共代码发生改动时,由于这些代码关联的用例较多,系统会推荐出大量冗余用例,影响测试效率。此外,我们对推荐用例进行分析时,发现其中某些用例和我们改动的代码逻辑并不相关。
这就引出了这部分的一个关键问题:推荐精准度提升。
针对这一问题,爱奇艺提出了降噪和分支级别精准两种解决方案。
1.推荐精准度提升——降噪
以客户端测试场景为例,用例在设计过程中因为执行步骤较长,在执行路径中可能会关联一些非验证点的页面或者操作。
例如,下图中这三个用例都关联到了“打开首页”这一相同的前置步骤,当首页代码发生变化时,这三个用例都会被推荐出来,但这和我们的预期并不相符。
对此,爱奇艺采用设置基础用例的方法进行降噪,把其他用例都会关联到的公共操作或者一些起到承接作用的步骤设置为基础用例。比如图中的用例1——打开首页操作就可以作为基础用例,当基础用例关联代码发生变更时,我们仅推荐基础用例,其他的用例不再推荐,这样便可以达到部分降噪的目的。
2.推荐精准度提升-分支级别精准
在第一个版本的精准推荐方案里,精准度是代码的方法级别或函数级别。我们会把用例和代码的具体方法进行关联,在精准推荐时,首先解析出有哪些方法发生变更,然后反查影响用例。但按照方法粒度去进行推荐可能产生用例冗余。以下图的方法为例,这个方法中共两个分支,用例1执行a=0分支,用例2执行a=1分支。当分支a=0内的代码发生变化,若以精确到方法级别的推荐策略进行推荐,这两个用例都会被推荐出来,但实际上用例2是完全不会受到影响的,这样就产生了冗余用例。
针对这个问题,爱奇艺对精准推荐方法做了升级,由之前的精确到方法级别优化为精确到代码分支级别。
首先,在建立知识库的时候,就要将用例与代码分支进行关联。在进行分支解析时,我们会得到用例执行的分支条件(下图右侧红色部分)及分支的内容即分支所对应的代码块(下图右侧蓝色部分)。知识库建立后,精准推荐时差异代码的计算也要精确到有哪些具体的分支发生变更。这里的方法是首先将本次提交代码的分支条件与用例库中用例的分支条件进行匹配,匹配一致再对比分支内容有无变化。如果发生变化,则需要做推荐,如果没有发生变化,就说明它不受影响,也无需进行回归。
04
爱奇艺精准测试应用场景与效果
下图是爱奇艺精准测试平台能力展示。
通过平台,可以实现对知识库进行查询,查看每个用例所关联的代码信息;另外,也可以看到每次精准推荐的结果,对这一结果进行分析,如有哪些用例被推荐出来、出于什么原因被推荐、因为哪些代码的变更导致被推荐等等。
另外平台还提供异常监控能力,这是因为在用例代码录制过程中,尤其是在手工测试中,很有可能出现因测试同学人为操作原因导致用例没有被正确记录下来的情况,从而影响精准推荐的准确性,进而影响到测试质量。
因此,爱奇艺会对关联的代码文件比较可疑的用例进行监控,可以在平台上进行确认,或者重新录制,以保证知识库的准确性。
精准测试体系在爱奇艺服务端、客户端手工测试及自动化测试场景中落地后,也实现了较好的效果。
在手工测试场景中,爱奇艺在服务端和客户端多个业务线、多种回归测试场景中使用精准测试体系,数据显示,针对回归测试的用例量级有较明显的裁减,并且没有出现因回归不全面而导致的问题。
对于自动化测试而言,其使用精准测试的原因一般是自动化用例量级过大、执行的时间过长或自动化结果的分析成本过高。
上图右侧是一个非常经典的自动化落地的场景:服务端流量录制回放。要把线上用户的真实流量转到线下回放,进行回归测试。但是,线上流量量级非常大,不可能做全量回归。
因此,爱奇艺首先通过代码覆盖率工具将一些代码执行路径重复的请求过滤掉,这样可以去掉大部分请求。然而,过滤之后的用例在项目中测试或者CI过程中执行,量级仍然较大。因此爱奇艺又增加了一层精准筛选。最终,无论自动化CI执行时间还是自动化最终结果的分析时间都得到显著降低。
05
未来规划
未来,爱奇艺会对精准测试分析体系进行进一步完善,扩展更多的使用场景来建立测试流程整体上的闭环。
首先在精准回归领域,会扩展更多应用时机,例如监控客户端灰度期间代码变更,给出回归测试建议;实现前后端精准测试联动,对于前后端集成测试用例,可以同时关联前端代码和后端代码,实现全链路精准。另外,还可以采取更加智能化的推荐方法,比如自动给测试用例划分等价类、通过智能算法给不同的用例推荐不同的回归优先等级。
其次,还会向其他更多的环节拓展,例如利用精准测试促进研测协同。当在测试过程中遇到bug的时候,可以通过精准测试技术在测试环节将bug执行的代码轨迹记录下来,再配合智能缺陷定位方法辅助bug定位。
最后,可以对测试结果进行充分度分析,分析测试的用例是否完全覆盖了变更代码,如果没有覆盖,可以通过一些方法帮助用例的手工补充,甚至自动生成用例进行补充。
福利!!! 关注公众号,在后台回复关键词“测试”,就可以获得本次i技术会嘉宾分享PPT和录播视频。
也许你还想看