爱奇艺移动端APP健壮性测试的设计与实践

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"前言"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一款APP的发布以及新功能的迭代需要经过严格的质量保证,而"},{"type":"text","marks":[{"type":"strong"}],"text":"崩溃性问题"},{"type":"text","text":"是影响APP稳定的头号问题。其中,因前端不兼容后端服务数据格式变更而引起的崩溃问题占有一定的比例。这类崩溃问题一般排查难度较大,且利用常规测试方法通常很难有效降低这种类型缺陷的比例。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"是否有更好的方式来提前预防数据变更导致的崩溃问题?"},{"type":"text","text":"本文将重点介绍爱奇艺技术产品团队打造的APP健壮性测试实践内容。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"背景"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爱奇艺APP拥有丰富的视频资源,需要频繁进行节目上线或者下线、各种活动配置等操作调整。这些内容迭代主要是通过后台管理系统进行,然后下发到APP端并在UI层展示。在版本功能迭代过程中尽管有大量的、针对性的质量保证方法,但是服务端业务逻辑盘根错节,一些极少用到的功能配置可能在历经多次代码迭代后在最新版本APP中出现兼容问题,一些第三方依赖接口可能会因为格式的变化而引发前端UI不兼容甚至崩溃,这对于APP的"},{"type":"text","marks":[{"type":"strong"}],"text":"健壮性、稳定性"},{"type":"text","text":"提出了很大的挑战。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爱奇艺技术团队对线上历史问题进行总结、对行业内前沿技术进行探索,最终经过多次探讨后设计了一种APP健壮性测试方案。团队研发的基础网络库SDK对APP收到的服务端接口返回进行拦截,从网络层进行数据替换。团队根据历史问题的总结、日常经验的积累提炼出一系列数据组合,当APP进入需要测试的页面时,就会去拉取并进行“脏数据”填充,以便尽早发现因数据变更引发的崩溃问题。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/9f\/9fd647c6f20676e2b08c4f47bbdf9ee1.png","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","text":"测试效果图:从图中可以看到页面中的文字被脏数据修改"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"技术实现"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/9d\/9de69da32394b51f35e5ab44dd3b8407.png","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从上图可以看到:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)策略配置是一个独立的Web化模块,APP内“"},{"type":"text","marks":[{"type":"strong"}],"text":"脏数据"},{"type":"text","text":"”注入规则都由策略配置控制。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)APP内的基础网络库SDK模块是一个独立的功能模块,不会对其他功能模块有影响;并具有单独的开关控制,只有开关开启时才对后端返回的数据进行拦截替换。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面将对实现情况进行具体说明。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"一、WEB策略配置--可视化界面"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"策略配置的前提是确认页面的哪些接口请求需要进行校验,通常一个页面有非常多的后端请求,每个请求都会带有很多不同类型的参数,对应的返回数据带了大量的KEY和VALUE,数据配置对测试结果尤其重要。丰富的高危“脏数据”才能极大的提升网络数据测试的效果,如果纯手工输入“脏数据“进行测试,人力成本较高,最终我们通过WEB可视化界面进行数据策略配置,大幅度减少用户对“脏数据”的设计成本,因此策略配置界面的原则是数据通配、操作简单、策略可复用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"--策略示例图-1"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/e4\/e464ce65e11bc92dae4d959ce39a597b.png","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"--策略示例图-2"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/0d\/0d145a5d2960bf927bdc500b94a1ab9f.png","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从策略示例图1、2可以看到,配置分为二部分:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)"},{"type":"text","marks":[{"type":"strong"}],"text":"URL配置"},{"type":"text","text":": "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"被测页面的请求URL,支持域名模糊匹配、多域名同策略、域名参数匹配等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)"},{"type":"text","marks":[{"type":"strong"}],"text":"数据配置"},{"type":"text","text":": "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"支持单节点、多节点、节点移除\/跳过;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"支持同类型、非同类型、emoji表情、#color、null 、空值、object等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可视化页面为用户提供多种默认策略,这些默认策略均是测试中提炼出的经验积累,用户仅需配置待测URL即可使用,极大地降低操作成本。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"二、策略通信原理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"鉴于测试的目标覆盖度以及测试任务执行效率两个维度考虑,我们具有两种遍历JSON的策略:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)"},{"type":"text","marks":[{"type":"strong"}],"text":"刷新单个节点进行顺序访问"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此策略可以覆盖所有节点检查,根据返回结构,依次替换节点数据。具有节点全覆盖的特点。接口返回数据体量大时耗时会较长,所以此方式适用于UI自动化测试。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)"},{"type":"text","marks":[{"type":"strong"}],"text":"刷新遍历所有节点的全节点访问"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此策略每次访问到匹配的URL时从列表内随机获取一个脏数据,对原数据进行替换。具有数据随机性强,遍历灵活度高的特点。接口返回数据体量无论大小,各个节点均有机会被替换,所以此方式适用于稳定性测试。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"遍历策略开发难点:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"任务过程中如有发生崩溃,重启APP后遍历执行仍然会在相同的崩溃节点反复测试,这导致测试效率低下后续测试步骤无法继续进行。为了解决这个问题,测试中SDK维护一个“脏数据”遍历的访问栈使用非递归遍历,会保存遍历栈到本地,不论是重启还是发生崩溃都可以直接从这个栈里恢复访问进度。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"SDK数据拦截实现:"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/43\/43c93e74a30c6029896685304b0fcbe3.png","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通过基于ASM的hook框架编译时指定网络库对应的方法进行hook修改网络库的字节码实现拦截,将JSON数据按指定规则进行修改,最后将数据返回给网络库,传递到请求网络的业务方,此方法能有效地降低对基础库的侵入性能。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"SDK的特点:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"泛用性广"},{"type":"text","text":":移动端有各种不同的网络库在使用,把拦截网络库的功能独立成一个library并适应不同开发团队的技术场景,目前已落地到多个业务线。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"非侵入式对接"},{"type":"text","text":":各业务线通过该SDK对接网络库进行数据拦截,原有网络库无任何侵入式修改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"缺陷管理"},{"type":"text","text":":在业务方使用“脏数据”的过程中发生异常崩溃,SDK自动捕捉异常信息并投递缺陷给模块的负责人,测试任务将重启APP继续测试流程的循环。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"三、测试驱动方式"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"SDK开关打开后,运行我们的测试应用服务,就可以在APP的UI页面上进行操作。操作方式包括:自动化测试、稳定性测试、手工测试。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"自动化测试("},{"type":"text","text":"UI自动化"},{"type":"text","marks":[{"type":"strong"}],"text":")"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们使用UI自动化作为主要的驱动方式之一,UI自动化可以精准到达被测页面,并进行指定场景接口的返回数据替换测试。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/9a\/9a489e6fd2de3b6a33a155cd49c11db8.png","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"针对健壮性测试的UI自动化,无需复杂的步骤,在达到指定页面后,重复触发接口请求。此驱动方式具有编写便利、维护成本低的特点。当被测页面接口返回数据量级较大时,需要耗费较长时间才能达到数据高覆盖的目的,UI自动化无需值守可以极大降低人力投入。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此方式适用于回归测试、大量数据页面、性能压测等测试场景。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"稳定性测试("},{"type":"text","text":"Monkey类测试"},{"type":"text","marks":[{"type":"strong"}],"text":")"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"为了让APP混沌测试覆盖更广,我们将“脏数据”修改方案在稳定性测试中进行实施 , 以低成本实现多页面触达的需求,触发更多页面的后端接口。默认使用全量字段随机注入。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以下是处理逻辑:"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/bc\/bcd1f4fc9234d985e84936f444e4b63f.png","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"根据预埋或者自定义的页面层级访问权重,对APP中的页面进行随机访问。在APP启动且进入预期页面之前打开SDK开关。为了提高修改频率,可以在进入目标页面后适当加入刷新操作(可配置)。期间如触发崩溃问题,则通知SDK侧进行日志提取和缺陷提交,随后关闭SDK,进入下一个循环。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"手工测试"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"特点优势"},{"type":"text","text":":具备灵活度高、成本低,针对自动化难以涉及的扫码、支付等多种场景;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"使用场景"},{"type":"text","text":":在开发准入、新功能测试中落地,针对新增接口节点进行充分验证;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"执行流程"},{"type":"text","text":":配置策略>安装APK>进入启动页>填写策略ID>进入被测页>缺陷分析>自动缺陷管理。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"效果收益及未来规划"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"目前,该技术方案已经推行到多个业务线,在测试过程中召回多个难以发现的缺陷,帮助规避了线上可能出现的崩溃问题;新业务新场景接入便捷,落地投入成本较低,自动化任务几乎零维护;缺陷闭环率达50%以上,有效提升代码的健壮性和稳定性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"未来,团队计划增加更丰富更多变的服务能力,包括:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)提升数据节点覆盖的广度和深度;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)丰富“脏数据”类型与内容形态;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3)接口迭代场景精准匹配,支持数据自动提取解析,针对性测试;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4)支持多台设备并发执行策略的能力,实现分布式数据遍历修改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文转载自:爱奇艺技术产品团队(ID:iQIYI-TP)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文链接:"},{"type":"link","attrs":{"href":"https:\/\/mp.weixin.qq.com\/s\/kQDhrSU3Erk__1XJrUS-qg","title":"xxx","type":null},"content":[{"type":"text","text":"爱奇艺移动端APP健壮性测试的设计与实践"}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章