基于真实bug的GUI自动化测试标准设计

Posted on
Software Analyze and Testing

论文Benchmarking Automated GUI Testing for Android against Real-World Bugs的学习笔记,作者是Ting Su老师。

总览

在自动化GUI软件测试中,有一个关键问题:“测试工具如何有效地、全面地找到实际存在的crash bug(How effectively and thoroughly can these tools find crash bugs in practice?)”。本文的主要围绕这个问题展开工作,制定了一个名为THEMIS的标准来比较自动化GUI测试工具的有效性。

目前的研究主要聚焦于使用不同的测试工具,对多个app进行测试,比较它们找到crash bug的个数和被测代码的覆盖率。这些方法都是基于软件和测试工具,来对未知的crash bug进行检测,这种检测方法提供的信息很有限,无法很好地解释上述的关键问题。

本文的核心思想在于:构建包含真实bug(ground-truth)的数据集,并检验测试工具能否在app上检测出这些bug

这种做法有以下的好处:

  • 可以更直接、更深入地分析测试工具的有效性。基于未被检测到的真实bug,分析各工具的短板,并可以进一步地总结所有工具存普遍存在的问题,帮助测试工具更好地发展。
  • 增加测试工具的可靠性,分析测试工具在“bug去重”时是否存在策略上的缺陷,使得两个不同的真实bug被判定为相同,从而让结果变得不可靠。

为了达到这个目的,本文基于多个专家的经验,从1,829个开源安卓软件中人为选择了20个开源项目的52个真实bug。这些bug都被标注了“高优先级”等字样,并且影响了软件的主要功能,或是影响的用户范围较广,表明了这些bug的重要程度。

基于真实bug数据集,本文提出了3个研究问题:

  • RQ1:现有的测试工具是否能够有效、全面地检测到真实的bug。
  • RQ2:现有的测试工具是否存在共同的短板,使得它们无法发现一些特定的bug。
  • RQ3:有哪些因素制约了测试工具对真实bug 的检测,如何针对这些因素对测试工具进行改进。

测试工具

为了研究这些研究问题,本文选择了8个流行的测试工具:

  • Monkey:能够随机生成GUI事件(touch、gesture、random texts)和系统事件(volume controls、navigation)。

  • APE:结合随机策略和深度优先搜索策略生成GUI事件序列,同时基于决策树算法,在运行时对生成模型进行不断优化。

  • HUMANOID:基于深度学习,利用神经网络来预测当前GUI状态下,最合适的GUI事件。

  • COMBODROID:利用一系列简短、独立的测试用例,通过分析它们的数据流向和GUI过度关系,结合成为若干个较长的GUI事件。

  • TimeMachine:将GUI的布局定义为状态(state)

    • 若在测试过程中发现一个较好的状态(如调用了之前没有调用过的函数),则认为该状态是一个interesting state,并将其记录。
    • 若当前的状态没什么进展,则将状态恢复到最近的一个较好的状态,并继续开展测试。
  • Q-TESTING:基于强化学习的思想

    • 当某个GUI状态与上一个相似时,获得较小的reward
    • 当某个GUI状态与上一个差别较大时,获得较大的reward

    从而生成较具代表性的GUI事件序列

  • SAPIENZ和STOAT:SPAIENZ使用了基因算法、STOAT使用了随机模型。

实验部署

数据集构建

  • 收集开源软件:本文以两种方式收集开源安卓软件:

    1. 从F-Droid中爬取
    2. 在Github上以“Android”和AndroidManifest.xml为关键词进行搜索

    最终获取1,829个安卓软件。

  • 筛选严重问题(critical issues):通过Github API,爬取这些安卓软件的issue及其对应的issue label,总结出111个相关标签。从这些标签中,本文筛选出了一些和“严重问题”相关的标签,并总结为12个短语,每个短语包含若干个标签,如短语“block”包含“blocking-release”和“blocked”,此处筛选出200个与这12个短语相关的软件。

    对于不包含issue label的项目,本文从标题、内容或评论中筛选出包含短语关键词的issues,此处选出209个软件。

    最终筛选出409个包含严重问题的软件。

  • 获取严重问题信息:针对上一步的筛选结果,根据以下原则筛选issues:

    1. 包含关键词”crash”或“exception”
    2. 包含清晰的复现步骤
    3. 在2017年1月之后提交

    最终筛选51个软件的228个严重问题信息,其余被剔除的信息大多没有清晰的复现步骤或是较为过时。

  • 对issues进行验证和归档:本文人为地检查了这228个问题,具体步骤如下:

    1. 查看和理解bug报告
    2. 定位出现问题的代码版本
    3. build该代码版本的程序
    4. 复现bug
    5. 归档bug数据

    由于bug报告中的描述不全、版本不符、build代码耗时、文档不全等问题,这个过程相当耗时。同时对于不满足以下条件的问题,本文也予以剔除:

    1. 无法理解bug报告的描述
    2. 无法定位发生问题的代码版本
    3. 无法将代码build为可执行程序
    4. 无法在安卓7.1上复现bug
    5. 步骤过于简单,不需要用到测试工具(比如启动时就会crash)
    6. 复现成本较高,如对于Github app的测试,需要人工创建一个正常的项目,并且包含commit、issues和branches

    最终从20个软件中筛选出52个严重问题,这些问题的以下信息被归档记录:

    1. 可执行APK程序
    2. bug复现的视频
    3. 出现问题时的栈信息
    4. 其它,如对于需要登录的软件的登录脚本

最终的数据集统计结果如Table 3所示,本文也记录了每个项目的代码行数和问题的复现步骤数等信息,这些问题都可以被很容易地复现,崩溃原因也较为明确,对于一个较为理想的测试程序来说是可以发现这些问题的。

THEMIS的架构

THEMIS可以简单地用以下命令,验证不同测试工具在不同软件下的作用:

themis --avd avd_name -n dev_cnt --apk apk_name 
-o output_dir --time testing_time 
--repeat run_cnt --tool tool_name
[--login login_script] [--gui] [--check_crash] [--coverage]

:<<!
--avd: 设备名称
--n: 设备池大小
--apk: app名称
--o: 输出路径
--time: 测试时间
--repeat: 重复次数
--tool: 测试的工具
--login: 登录脚本(可选)
--gui: 是否展示GUI屏幕(可选)
--check_crash: 是否检查崩溃
--coverage: 记录代码覆盖率
!

本文在构建THEMIS过程中,针对各个测试工具存在的问题,花费了许多时间开展以下适配工作:

  • APE:当长时间运行时,会出现内存不足和磁盘空间不足的情况,这是由于它会把所有的GUI状态都保存在内存中,同时产生大量的输出日志文件。在和原作者讨论后,本文在测试过程中使用了2GB的RAM,1GB的内部存储(internal storage)和额外1GB的SD卡存储来解决这个问题。另外,在测试工作初期,APE经常因为一些问题崩溃,这些问题也向开发者做出反馈并得到解决。
  • HUMANOID:主要花费的时间在于找到匹配的TensorFlow版本和一些过期的依赖库。另外,它所依赖的DROIDBOT在使用时也有一些问题,本文也予以解决。
  • COMBODROID:本文为其增加了并行测试的模块,并使其支持登录脚本。同样的,该工具在测试初期也有一些bug,也通过联系作者得到解决。
  • TIMEMACHINE:本文主要做了以下三点适配
    • 该工具在收集代码覆盖率时使用了EMMA模块,但它对近期的app支持度不高,本文将其替换为了JACOCO模块。
    • 本工具由于运行在虚拟机上,所有时间相关的信息都会丢失或者不准确,本文额外实现了一个模块,对时间相关信息进行记录。
    • 实现了该工具的并行测试、登录脚本的支持和谷歌服务的支持,同时修复了一些明显的bug。
  • 其它工具的部署较为顺利

实验配置

实验在64位ubuntu 18.04上运行,配置64核 AMD 2990WC CPU和128GB内存。所有app在安卓7.1模拟器(API级别25)上运行,每个模拟器配置2GB内存,1GB的SD卡和1GB的内部存储,基于X86 ABI镜像。为了不占用内存,所有外部文件(图片、音频、PDF、文本等)都保存在SD卡中。

对于每个需要登录的bug,分别注册一个账号,并在每次执行前清空账号信息。由于SAPIENZ只支持安卓4.4,所以本文只测试了其中19个可在该工具上稳定复现的bug。

对于每个bug和工具,本文都配置一个单独的模拟器,并重复5次。每次需要执行约6个小时,实验需要耗费10,920个小时。本文同时运行16个模拟器,总共花费28天

实验结果

RQ1: 量化bug检测能力

本文从3个方面量化测试工具的bug检测能力:

  1. 有效性:能够从52个bug中找到多少个?不同工具找到的bug有何不同?
  2. 稳定性:在对同一个bug重复多次实验的情况下,工具是否可以稳定的找到该bug。
  3. 效率:检测这些bug需要花费多少时间?
  • 有效性分析

    Table 3的后9列记录了各个工具检测到bug的情况。其中空集符号中的$\times$表示该bug没有被任何工具检测到,M表示MONKEY,A表示APE,H表示HUMANOID,C表示COMBODROID,T表示TIMEMACHINE,Q表示Q-TESTING,Sa表示SAPIENZ,St表示STOAT。

    从结果看,有18个bug(34.6%)没有被任何一个工具检测到,说明现有的测试工具对测试真实bug的能力还有很大的提升空间

    Table 4的Found Bugs部分展示了各工具找到的bug个数,表现最好的APE仅发现了一半的bug,具体情况如下:

    M A H C T Q Sa St
    #Found Bugs 22 24 18 21 15 10 3 19
    #Missed 30 28 34 31 37 41 16 33
    # Miss Percentage 57.7% 53.8% 65.4% 59.6% 71.2% 78.8% 84.2% 63.5%

    本文还两两之间比较了测试工具发现的bug(如图左下角),分析这些bug的重合程度:

    可以发现,没有一个工具可以完全胜过其他工具,但当它们共同使用时,之间达到互补的效果。

  • 稳定性分析

    表中的数据反映了测试工具在对bug测试的过程中,是否包含一定的随机性。由表可知,很多bug在5此实验中,只被检测到1次,比如APE和TIMEMACHINE所发现的bug中,分别有6个(25%)和7个(46%)bug仅被检测到一次。这表明了现有的测试工具在检测bug中包含了一定的随机性,没有很稳定的表现。

  • 效率分析

    下图描绘了各个工具在各个bug检测所花费的时间箱形图

    其中,COMBODROID、APE、Q-TESTING所花费的时间较少,具体来说,这三个工具在第一个小时的测试量分别为19/21、20/24、9/10。

    下图的右上角,通过箱形图两两对比了工具间的测试时间,此处使用的是两个工具共有的bug:

    此处使用了Mann-Whitney U test来检验两组数据的均值是否有差异,当p值小于0.05是拒绝原假设(原假设为两组数据均值没有差异),并使用d值来判断差异程度:

    • $d<0.3$时差异较小
    • $0.3\le d\le 0.5$时差异中等
    • $d>0.5$时差异较大

    可以看到APE在效率方面效率表现最好,引起各工具之间效率差异的主要原因还是他们测试策略的差异。

RQ2: 测试工具存在的共同问题

本文基于18个未被任何一个工具测试发现的bug,做出以下分析:

  1. 从GUI和代码层面分析bug的特点
  2. 分析测试工具的实现方式和测试策略
  3. 通过bug复现的视频,与工具原作者讨论原因

具体分析结果可以用下表表示:

本文将存在的问题分为五类:

  1. 测试用例过于深入:

    在表中用“#Distinct Transit.”表示测试用例涉及的页面数量。

    18个bug中,12个bug(66.6%)涉及的页面数量大于5个,每个页面上又需要大量的交互事件,有的bug甚至需要80,000多个步骤才可以被复现,这让测试工具难以生成相应的事件序列。

  2. 需要特定的文本输入:

    18个bug中,4个bug需要文本输入,其中3个bug的文本输入是corner-case或是特定的非法输入。但现有的工具大多通过随机生成字符串的方式,对文本输入进行测试,所以很难覆盖到这些问题。

  3. 需要改变系统设置或软件设置:

    18个bug中,3个bug需要通过改变设置发生,其中2个是改变系统设置(如改变系统语言后会产生bug),而现有的工具并没有考虑改变设置所带来的影响。

  4. 拥有特定的用户交互

    18个bug中,12个bug需要特定的交互事件。举例来说,WordPress在发表文章时,需要上传一系列图片。若图片还在上传时,文章就被作者删除,则会引发问题。

    通过检查这18个bug 的相关代码,本文发现这些代码需要在不同的回调函数之间,执行一系列的交互。以WordPress的问题为例,这个问题涉及到了删除文章的GUI事件与上传图片的后台线程进行交互。

  5. 需要与其它app交互

    18个bug中,有5个需要和其它app进行交互,从而获取一些特定的数据(如从别的app获取图片),而现有的工具大多只是在app内部进行测试。

RQ3: 制约因素和改进方式

本文测试工具在bug测试上的表现,总结了三个制约因素:

  • GUI测试策略
  • GUI状态抽象的粒度
  • 测试时的启发式操作

GUI测试策略

本文发现,在测试时使用一些直接的、细粒度的操作,可以更有效地发现bug。如APE、COMBODROID和STOAT发现的bug比HUMANOID、TIMEMACHINE和Q-TESTING多。

HUMANOID和Q-TESTING基于深度神经网络来指导事件序列的生成,TIMEMACHINE启发式地寻找一些没有被访问过的页面。这些方法都尽可能地覆盖更多的页面,但这并不意味着就能够找到bug。

相反,APE通过不断地优化状态抽象(State Abstraction)来区分不同的app状态(这些状态可能是同一个页面的不同GUI布局),COMBODROID在代码层面,通过数据流之间的关系来生成事件序列,STOAT通过随机模型来优化事件之间的组合。这些工具都利用了更细粒度的信息来生成事件,于是更容易发现一些bug。

GUI状态抽象的粒度

本文发现,GUI状态抽象的方式,能够很大程度上影响工具的bug检测能力:粒度越细的工具,能够找到的bug越多。

举例来说,TIMEMACHINE和Q-TESTING没有检测到WordPress和NextCloud的bug,这是由于它们的状态抽象准则比较粗糙(分别是C-Lv3的变体和介于C-Lv2与C-Lv3之间的粒度)。因此,TIMEMACHINE无法找到一些可能引发问题的状态,作为它的interesting state(会被保存的状态);而Q-TESTING在区分状态时,只将两个不同使用场景的页面定义为不同的状态。具体的状态抽象粒度可以看这篇文章

而上述的这些无法被粗粒度方法检测的bug,在APE、HUMANOID和COMBODROID中都可以被检测到。HUMANOID和COMBODROID都使用了洗粒度的C-Lv4准则,而APE进一步提出了一个对状态抽象的动态优化策略。

但对于MONKEY来说,它没有做任何的状态抽象,而是独立地对每一个页面生成随机的GUI事件,这样使它的可扩展性较差。对于一些bug,可能需要点击在角落的较小的组件,这让它找到这个组件的概率比较低。

测试时的启发式操作

本文认为,虽然一些启发式操作并不是一些测试工具的核心优势,但是它们趋势能提升自己的bug检测能力。

举例来说,MONKEY本身是不支持长按操作的,所以某些bug是无法发现的,而其它基于MONKEY的测试工具能够找到它们,因为这些工具额外实现了长按操作。另外,APIE和COMBODROID实现了一些特别的文本输入策略,这些策略也模仿了用户的交互操作:

  1. 长按文本输入框,选择已输入的文本
  2. 清空所有内容
  3. 输入随机的文本

基于这种启发式的操作(而不是直接清空文本),这两个工具可以发现MaterialFBook中长按、复制、黏贴的bug。

同样的,一些工具使用了启发式的方式来增加测试的有效性,比如APE和COMBODROID随机地引入MONKEY的随机测试策略(而不是一直使用自己的策略),从而发现一些随机操作下更容易引发的bug。如MONKEY会因为随机的swipe而唤起下拉菜单,并通过随机的点击事件更改设置。

讨论与总结

与现有的方法对比,本文利用了真实的bug作为检验指标,从而可以深入分析RQ1-RQ3提出的问题

应用

基于本文的分析结果,可以在三个方面开展应用:

  1. 基于RQ1-RQ3的分析结果,为完善现有的测试工具提供了思路,同时也引出了许多研究问题,如:如何找到系统设置相关的bug、如何设计好的GUI抽象准则。
  2. THEMIS工具能够衡量一个新的测试技术的量化性和质量,如:基于本文的比较方法,将该技术与现有工具的bug检测情况和效率进行对比,同时可以挑战18个所有工具都没有被检测出来的bug,从而证明它的有效性。
  3. THEMIS架构可以用于其它问题的研究,如bug复现、问题定位和程序修复等。

效度威胁

本文有两个潜在的效度威胁:

  1. 本文构建的数据集是否具有代表性
  2. 本文分析结果的准确性

对于第一个问题,作者与行业专家进行深入讨论,精心设计了软件和问题选择的准则,并从大量的安卓软件中,基于开发者标注的issue类型,选择出一些重要的bug。同时本文找到的bug也具有不同的特征,且这些bug的复杂程度与一般的bug没有太大的差异,所以具有一定的泛化性。

对于第二个问题,本文精心设计了实验架构,并且和各工具的开发者一起分析实验的结果。本文的几个作者也基于交叉验证的方式,对实验数据进行验证,并将THEMIS工具开源。