服务器 频道

基于接口数据变异的App健壮性测试实践

  本文整理自美团技术沙龙第77期《美团亿级流量系统的质量风险防控和稳定性治理实践》,主要介绍了对网络返回数据进行变异的客户端健壮性测试实践经验。文章第一部分介绍客户端健壮性测试的基本概念;第二部分分享了基于接口返回数据变异的App健壮性测试方案设计的思路;第三部分主要解读了变异数据的构造和异常检测方案设计;第四部分介绍了精简变异数据的探索方案。

  01 什么是客户端健壮性

  在维基百科的定义中,健壮性(Robustness)是指一个计算机系统在执行过程中处理错误,以及算法在遭遇输入、运算等异常时继续正常运行的能力。IEEE中将健壮性定义为系统或组件在存在无效输入或压力环境条件下可以正常运行的程度。早在1989年,Barton Miller首次提出了模糊测试的概念,通过向目标应用抛出随机字符串的方式来测试UNIX应用程序的健壮性;而在1996年的Ballista项目中,研究人员探索根据API定义的数据类型,对操作系统或软件接口进行自动化测试方法。两个项目均以“无应用程序崩溃或挂起”作为测试验证通过的标准。

  在移动端App领域,健壮性可以理解为App运行时遭遇环境异常或者输入异常时客户端能够继续正常运行的能力。

  其中,环境异常主要分为操作系统异常、外部环境异常、硬件环境异常三大类。比如内存不足、CPU负载过高、线程池满载、内存分配失败、网络连接失败等。输入异常主要分为系统输入和用户输入。比如网络接口返回的数据异常、应用内缓存、数据库文件读写异常,这类的异常属于在系统输入异常;在电话号码输入框场景,用户输入的空格、富文本则属于用户输入异常。  

  对于这些风险,如果App没有处理,理论上都可能会产生展示异常、交互异常、性能、安全等问题,导致用户无法继续使用或在使用过程中产生不好的体验。比如用户操作App下单过程中,API请求出现故障未返回状态码为200的响应,App由于没有获取到预期接口响应的信息而发生崩溃,就会中断用户的使用流程。  

  02 基于接口数据变异的App健壮性测试方案设计

  在实际的客户端测试执行过程中,测试人员会考虑测试异常输入的场景,但由于成本无法做到无穷尽的测试,同时还存在人工执行遗漏的风险。

  从美团App平台业务的历史故障分析中,我们发现:网络请求返回的数据与实现预期不符引发的Crash或核心功能缺失问题导致的故障占比最高,且影响面较广。比如接口返回非预期数据时,客户端处理数据类型转换异常导致闪退,即使5分钟内操作降级仍影响了百万量级的用户。因此美团平台业务App的健壮性测试探索优先从发现网络请求返回数据导致的异常开始。

  针对于发现请求接口返回客户端非预期数据导致的Crash,或者核心模块缺失问题这个诉求,我们调研后发现方案的基本原理都是相似的,即以网络请求的原始响应为基础,根据规则进行变异构造,使用代理工具改写响应体返回给客户端,在端上设备做异常检测。但是都存在一些问题不能满足诉求,比如测试变异数据是根据预置或者自定义规则随机生成组合,随机性过大,不能有效拦截健壮性问题;但如果不做随机,产生的用例组合量过大,测试不能在合理时间范围内结束;另外在检测能力方面,不具备发现业务异常或功能模块异常的能力。

  因此,我们结合通用方案做了一些自定义改造,整体检测方案包含静态检测和动态检测两部分。

  静态检测,主要是指静态代码扫描,将典型代码编写规范问题转化为自定义静态代码扫描规则,管控增量代码,同时长期治理存量风险。比如自定义了PrimitiveParseDetector、ColorParseDetector,管控业务必须使用健壮性测试通过的工具类。

  动态检测,是指结合触发时机,构造并注入变异数据后,识别App运行时是否出现崩溃、挂起或业务功能模块异常。比如在集成事件/回归事件触发自动化测试运行,构造触发异常的数据进行动态测试,然后监测是否出现了异常。核心动作包含构造变异数据和完成检测两部分。比如将接口响应体中表示颜色含义的Key对应的Value值构造成非色值,然后检测客户端请求处理接口数据时是否出现崩溃或挂起。

  下文重点介绍端到端的动态检测方案。

  03 变异数据的构造和异常检测

  对于美团App来说,首页有多种形态,对于某种特定形态,除了控制请求数据外还需要控制实验、策略等一系列因素,才能保证测试对象的唯一性。一个页面中包含多个异步请求,因此请求的构造也需要和页面路径关联。这些都是采集变异所需的基础数据时需要关注和控制的。

  响应体由基本类型数据和复合类型数据组成,相同基本类型的数据可能具备不同的业务语义,需要根据语义的类型做变异规则的区分对待,才能保障业务场景覆盖。

  因此,如何保障变异数据构造的全面性和准确性,是我们面临的首要挑战。  

  要解决数据构造全面性问题,首先要解决页面描述方案,这样才能控制获取基础数据的唯一性。在解决方案中,我们构建了页面描述的特征规则,解决用户视角的页面标识问题。需要的信息包含端信息、页面路由信息、实验策略账号信息、页面标识模块合集等。通过页面请求数据自动录制的方式,自动更新迭代请求数据和页面之间的绑定关系,使得基础数据能够随需求迭代更新,从而通过变异规则构造生成的用例也能够自动更新。  

  在用例变异生成构造上,对于响应体里的Value设置了语义匹配规则,比如字符串的语义可能代表颜色、页面跳转路由、动静态资源链接(即图片资源数据/视频文件/GIF文件),需要区分特征分别按语义构造异常数据。

  比如在图片的变异数据构造里,除了需要构造非图片链接情况外,还要考虑不同图片格式、非图片格式以及非合法的图片剪裁格式拼接等场景。

  我们对接口返回数据使用脚本做了初步的语义分析,人工二次校正后建立了基本数据类型和语义的映射集合,结合基本数据类型边界值和语义定义了初始的变异规则。然后对历史的线上健壮性问题和线下测试发现的健壮性Bug的变异数据进行整理,作为增补的变异规则。

  在自动化测试执行过程中,我们基于App可测性改造提供的能力,对测试场景进行了控制,同时基于布局视图的解析SDK、App异常上报SDK提供的能力,完成了对App异常的通用检测。  

  04 变异数据的精简方案

  伴随着变异规则的丰富,自动生成的数据量级是巨大的,数据的变异组合如果按照全覆盖方式来生成组合数量就是指数级增长。比如对于1种有7种变异取值的变量,如果存在n个此类型变量,就会产生7^n种数据组合,并且在实际业务场景中很多组合情况是没有意义的。

  如何在保障用例构造全面性的情况下精简变异构造的用例数,是我们面临的第二个挑战。解决方案包含2个策略:1)数组元素结构一致时,删减构造的用例数;2)结构不完全一致的数组元素,引入编辑距离和并查集算法判断节点相似性,节点不相似,可以在一次数据生成里做合并构造。

  我们可以把请求响应的JSON理解成树,第一个解决思路是判断树中节点、路径的相似度,相似节点删减构造。

  如果路径、节点相似,可以推测路径即业务逻辑也是一致的,比如页面上的一些列表元素,可能是数据结构对象完全一致数组,如果对每个数组对象中的每个元素进行全用例构造,生成的变异数据量极大,且对业务场景或代码逻辑的增量覆盖有限,因此我们决定将构造逻辑优化,进行删减构造。即假如数组中元素的结构完全一致,那么同含义的字段可以为他们分配不同的变异构造值,然后删减掉无效的构造情况。应用这种方法可以有效降低28%左右的用例构造数量。

  如图数组的3个元素中均存在“resourceName”键值对,假如每个键值对有3种变异取值,按照全排列方式进行用例构造将会生成有9份变异数据,在删减构造情况下,可以分别为它们构造一个特定的变异值,这样变异生成用例数量可以从9减少为1。  

  在对业务接口返回数据的数据结构进行分析后,我们发现在层级越深的场景下,距离根节点越近的两个节点,业务逻辑耦合和结构相似程度越低,它可以进行合并构造,相互逻辑之间不会产生影响,比如有两个键值对,每个键值对的Value有3种变异取值,在合并构造情况下,可以从排列组合的6份数据减少到3份数据。  

  基于这个思路,我们在实践中引入了编辑距离和并查集算法,以节点路径为参照,对树的每一层的每两个节点计算编辑距离,生成一个n*n矩阵;同时以树的高度减去节点位于的层数作为权重,修正编辑距离。基于这样的计算,会产生多个编辑距离矩阵。

  为了尝试最大化合并构造用例效果,我们把编辑距离做了0,1矩阵转化。其中,由于编辑距离为1的两个节点可能存在业务逻辑耦合关系,必须放在同一个组里分别构造,所以我们把编辑距离大于1的情况转化成了0,最后得到了一个0,1的编辑距离矩阵。  

  在0,1矩阵情况下,我们使用了图的连通性概念,如果A和B连通,B和C连通,那我们认为A和C连通,转化到这里的概念就是A和B相似,B和C相似,那么A和C相似,它们应该被放在同一个组里分开进行构造,那么在同层元素构造时,我们会从每个分组里取到一个节点,对这些规则进行变异组合构造。  

  基于以上两个策略进行精简后生成的变异数据量较精简前降低了40%,同时代码覆盖率没有明显变化,并且保持不变的健壮性问题发现能力。

  美团App和优选App都接入了这个工具,在新需求阶段可以人工触发运行,还可以结合客户端组件集成事件和回归事件做自动触发。至今应用一年时间内,发现了几十个问题。  

  

  05 总结及展望

  在健壮性工具建设一期里,我们实现了App页面加载展示场景的健壮性问题检测,支持崩溃、卡死和部分功能异常这三类异常检测。另外,基于节点相似性优化变异数据生成策略能够在保持效果不变的情况下有效控制测试时长,但是否有更优的合并算法和推荐算法,还需要更多的尝试。  

  在后续工具的迭代还会继续围绕异常构造和异常检测这两个方向,支持更丰富的构造能力和检测能力,以及更高效的构造效率。  

  

  短期建设上,我们将会从业务视角出发丰富自动化变异数据生成建模,完善客户端异常通用异常检测能力,完成通用前后端交互的数据构造类型(比如:长连接消息)的覆盖;长期建设上,需要支持更丰富的数据和环境构造能力,通过智能化用例生成,提升测试效率。

0
相关文章