APP下载

安卓智能终端自动化测试技术综述

2024-01-11雷丰强刘方青

计算机与生活 2024年1期
关键词:污点测试用例安卓

曹 捷,黄 翰+,雷丰强,刘方青

1.华南理工大学 软件学院,广州 510006

2.微科智检(佛山市)科技有限公司,广东 佛山 528000

随着终端影像技术和处理器芯片技术的不断进步,移动智能终端正步入高速发展的时代。据中国信通院[1]发布的数据,2022 年中国智能移动终端用户规模突破12 亿人。回顾智能终端的历史,1994 年IBM 发布的Simon被公认为是第一款智能手机,其搭载的ZOLUS 系统只有一个第三方应用程序,虽然现在看来有些笨重,但它敲开了智能终端系统的大门。2007 年1 月9 日,苹果公司发布了基于Objective-C、C、C++语言编写的闭源类Unix 系统iOS(iPhone OS)系统。同年11月5日,谷歌公司推出了首个为智能移动终端开发的开源安卓(Android)操作系统。由于安卓操作系统的开源性,自发布以来一直占据了市场的主导地位,目前安卓系统已经拥有超过80%的市场份额和10 亿台活跃设备[2]。安卓系统的开放源代码特性也促进了安卓系统建立起强大的生态圈。我国的一流智能手机厂商全部采用基于安卓系统开发的自研操作系统,如小米的MIUI[3]、魅族的Flyme[4]等。同时,安卓系统不断引入新功能并进行优化,例如人工智能和虚拟现实等技术,从而满足用户需求并保持市场竞争力。

智能终端系统的安全性和质量是至关重要的,而软件测试是确保这一目标的关键[5]。在智能终端系统投入使用之前,必须对可能出现的问题进行检测,并通过相关技术手段对问题进行排除。通常情况下,软件测试占整个软件开发工作量的40%~50%[6]。如何高效地进行智能终端测试以保障系统的可靠性和稳定性已经成为企业面临的重要问题之一。

如今越来越多的恶意应用程序利用智能终端系统的漏洞来窃取用户信息,进而获取用户的精准画像、突破系统限制并最终促进交易转化[7]。近期,反病毒软件公司卡巴斯基正式开展对某大型购物应用程序(application,App)的调查。调查发现该App 的安装程序中含有恶意代码,可以利用安卓系统漏洞安装后门并获得未经授权的用户数据和通知信息,以达到获客、促交易、提高活跃度三个目的[8]。由于用户量过亿的大型应用都会利用其智能终端载体的漏洞来牟利,有必要对智能终端领域做一次全面的自动化测试技术总结分析,供研究人员随时参照相关内容,方便开展后续的研究工作。

为了梳理面向智能终端自动化测试技术发展现状,本文首先通过“Android auto test”“iOS auto test”等关键词检索与综述主题相关的论文。然后对相关论文进行了人工筛选,通过分析论文的题目、关键字和摘要,识别并移除与综述主题无关的论文。最后根据确定的文献中的引文,再次补充相关的论文。需要注意的是,关于iOS系统的自动化测试相关技术论文占比低,大多数有关文献都是以跨平台测试框架出现[9-11]。

综合研究iOS 相关文献后发现,iOS 系统的闭源特性导致相关技术和工具覆盖面相对较少,但也因其闭源而在安全性上普遍优于安卓系统[12]。苹果官方市场AppStore 是iOS 开发者发布应用程序的唯一途径[13]。在提交应用程序之前,开发者需要向苹果注册并进行隐私和安全违规测试。这个长达两周的审查过程可以有效防止黑客编写恶意应用程序并在商店出售。开发者需要提供身份信息以完成注册,并将其嵌入到应用程序中。这种数字签名流程旨在确保应用程序开发者和应用程序的身份都不会被修改或篡改。通过认证流程,iOS 鼓励软件开发人员制作高质量的应用程序。一旦应用程序提交并通过苹果公司认证,任何修改该应用程序的尝试都会打破数字签名封条。最后,只有符合许可协议的应用程序才能被接受并在AppStore中发布。因此,在iOS应用程序开发和发布过程中,注重应用的隐私和安全测试是十分必要的。

安卓系统的开源和自由度理念虽然带来了很多好处,但也导致了其在安全性方面相对被动。与iOS不同[14],安卓不要求应用程序开发者向Google Play注册或获得谷歌颁发的签名证书,这使得开发人员可以为应用程序创建任意数量的签名证书。同时,攻击者可以在互联网的任何网站上发布未经谷歌审核的应用程序[15],从而利用该开放生态系统传播有害软件。尽管谷歌试图防止黑客篡改合法应用程序,但是依然很难确保应用程序开发人员不会创建匿名证书或避免被谷歌捕获。此外,黑客还可以使用著名公司名称欺骗用户,将公司名称放入证书中,在合法应用程序中插入恶意代码并创建特洛伊木马,这是Android最大的安全问题之一。

除了iOS 和安卓外,其他诸如HarmonyOS[16]、FuchsiaOS[17]等的整体分层架构和接口定义与安卓系统类似,但它们的生态系统还未完全建立起来。因此,本文将以安卓智能终端为主要研究对象,探索该领域未来潜在的发展方向,并对相关技术和工具方法进行综述。

首先,本文从安卓系统的应用结构出发,介绍架构特点、关键组件以及相关的运行环境。然后,以黑盒和白盒作为安卓智能终端自动化测试技术的分类标准,详细讨论了自动化测试技术和工具的研究进展。最后,对安卓智能终端自动化测试技术所面临的挑战和未来潜在的发展方向进行了分析和展望。

1 安卓智能终端软件系统简介

1.1 安卓系统及应用结构

安卓[18]是智能终端设备上最受欢迎的平台之一,作为开源的智能终端操作系统,它拥有众多应用软件开发者和用户。如图1所示,安卓系统架构包括五个层次,从上往下分别为应用程序层、应用程序框架层、系统运行库层、硬件抽象层以及Linux内核层。

图1 安卓平台架构Fig.1 Architecture of Android system

应用程序层包括一些预装于安卓系统中的应用程序,例如短信、相册、地图以及视频播放器等。该层还包括开发者自身通过使用应用程序框架层提供的API(application programming interface)开发的应用程序。

应用程序框架层为应用程序层提供API接口,涵盖了应用程序开发过程中需要使用的各种功能。新的框架版本需要几个月的时间才能在安卓设备上占据主导地位,因此大多数设备都运行旧版本的框架。这意味着安卓开发人员必须花费大量精力使自己的应用程序与较旧的框架版本兼容,其引发的跨版本兼容问题也是造成安卓应用稳定性不足的重要原因。

系统运行库层包含了一系列可以供安卓系统各组件使用的C/C++静态库,这些库通过应用程序框架层为安卓应用开发者提供相应功能服务。安卓运行环境由Dalvik 虚拟机[19]和基础的Java 类库构成。由于Dalvik 每次执行都需要进行字节码到机器码的转换,导致应用程序运行速度较慢。同时Dalvik的垃圾回收机制效率不高,容易引起系统卡顿,使得系统的稳定性降低。从安卓5.0 开始,针对上面所提及的问题,谷歌在系统运行库层上进行了根本性的更改,引入了ART(Android runtime),这是一种新的运行时环境,可以显著提高应用程序性能[20],并最终取代Dalvik虚拟机。

硬件抽象层是位于操作系统内核与硬件电路之间的接口层,其目的在于将硬件抽象化。为了保护硬件厂商的知识产权,它隐藏了特定平台的硬件接口细节,为操作系统提供虚拟硬件平台,使其具有硬件无关性,可在多种平台上进行移植。

Linux 内核层包括了以Linux 内核为基础的安卓操作系统和各种驱动程序,是安卓系统将底层硬件和系统服务连接起来的核心与基础。

安卓应用程序主要是用Java 语言编写。Java 源代码首先被编译成Java 字节码,然后通过Dalvik 编译器将Java字节码转换成Dalvik字节码,并以.dex格式存储在机器可执行文件中。应用程序最终以apk文件的形式分发,其中包含了dex 文件、本机代码和其他应用程序资源的压缩文件夹。

除了原生的安卓系统,智能终端设备提供商为了提升用户体验和产品销量,通常会基于原生安卓系统开发自己的定制化操作系统,并将操作系统的升级速度作为卖点之一。然而,各厂商的定制化程度和质量不同,导致智能终端设备的可靠性和稳定性参差不齐。因此,对软件进行全面可靠的测试显得尤为重要。

1.2 安卓自动化测试简介

软件测试是保证软件系统质量的最重要的分析性措施之一。现有的软件测试方法基本上可以分为黑盒测试和白盒测试。在黑盒测试中,测试用例是根据被测程序的需求规范确定的,而在白盒测试中,测试用例是从内部结构派生的。无论是哪种方法,自动生成测试数据都很困难。

在过去的几年里,人们见证了移动应用业务的惊人增长,移动应用开发公司对自动测试移动应用工具的需求也与日俱增,这一领域的研究也随之增多。由于多种原因,大多数研究人员和开发人员将重点放在安卓平台上。首先,安卓目前在移动市场占据最大份额,使得该平台对业内从业者极具吸引力。其次,由于设备和操作系统版本的碎片化,安卓应用程序经常会遇到跨平台和跨版本的不兼容问题,手动测试这些应用程序的成本特别高,因此其自动化测试技术具有十分重要的意义。最后,安卓平台及其相关技术的开源特性,使其成为更适合学术研究人员的研究对象,可以更方便地访问应用程序和底层操作系统。

尽管安卓应用程序主要由Java 编写且基于用户图形界面(graphical user interface,GUI),但与Java 独立的GUI 应用程序相比,其存在很大的不同,并表现出不同种类的缺陷。因此,现有的大多数Java 测试用例生成工具并不能直接用于测试安卓应用程序。为此,研究人员在此方面进行了大量的研究,并提出了多种针对安卓应用的测试用例生成技术和工具。如图2所示,本文将从黑盒测试和白盒测试两个方面对安卓智能终端软件测试技术进行综述。

图2 安卓测试技术结构图Fig.2 Android testing technology structure

2 面向黑盒的安卓智能终端软件测试技术

黑盒测试,也称为功能测试。在测试中,程序被视为一个无法打开的黑盒子,测试员模拟真实用户对程序的使用场景,帮助发现可能存在的问题,确保程序的稳定性和可靠性。黑盒测试主要关注程序外部结构,不涉及内部的逻辑结构,主要针对软件界面和软件功能进行测试,以确保程序能够按照需求规格说明书的规定正常使用,并能够适当地接收输入数据并产生正确的输出信息。

2.1 用户界面测试

用户界面(user interface,UI)测试是安卓应用持续开发过程的重要组成部分。它的目的是检查UI是否符合设计要求,每个UI的布局是否显示正确,每个按钮的功能是否按预期执行。根据Alegroth 等人[21]提供的GUI测试工具分类,UI测试方法可以分为三代。

第一代UI测试技术使用在手动交互过程中记录的精确坐标点,并录制支持自动重放的测试用例来进行回归测试。然而,由于存在对软件自动化测试(automation testing,AUT)的UI 变化的鲁棒性不足、对屏幕分辨率依赖性大等缺陷,这种方法有着极高的维护成本,因此被逐渐放弃。

第二代UI 测试技术通过UI 控件属性和数值直接针对UI 模型进行操作。该方法对AUT 的UI 变化更具鲁棒性,测试执行性能高且稳定,支持测试记录和用例录制。但是,第二代技术对需要访问AUT 的底层GUI 库依赖性强,因此对使用不同GUI API、不同编程语言编写的AUT的适用性很差。同时对于动态UI,它的控件属性和值可能会随着时间的推移而发生变化,因此需要定期更新测试脚本,增加了测试维护成本。

第三代UI 测试技术使用图像识别技术对UI 模型进行操作,也称为可视化GUI 测试。该技术通过对用户显示器上呈现的图形GUI 进行交互和断言AUT的正确性,实现了高效、准确的UI测试。图像识别技术能够识别UI 控件的位置、大小、颜色、文本等属性,从而模拟用户对UI进行操作,并通过比对预期结果和实际结果来判断测试是否通过。虽然该技术存在一定的误差和测试维护成本,但其测试覆盖范围广,能够有效提高测试效率和测试质量。

2.1.1 基于系统控件属性的自动化测试技术

常用的基于系统控件属性的测试工具有Appium[22]、UI Automator[23]等,其中Appium是目前最为主流的框架和工具。如图3 所示,Appium 的核心是一个Web服务器,可以接受来自客户端的连接,监听命令并在移动设备上执行,最终通过HTTP 响应来描述执行结果。Appium在执行脚本前会在服务端默认开启两个网络端口,4723 端口接收Webdriver 请求,4724 端口则将执行命令发送到事先推送到安卓系统中的bootstrap.jar中,bootstrap.jar接收到命令请求后,调用底层的基础测试框架来完成测试人员要求的测试指令。Coppola等人[24]对混合移动应用程序的测试用例所需的维护以及相关的脆弱性原因进行了评估。他们使用Appium 和一个可视化的工具对一个不断版本迭代的应用程序进行测试,并观察自动化测试用例脚本所需的变化。研究发现,每次软件版本更新后,至少有20%的基于系统控件属性的测试用例需要进行修改。而造成这些测试用例脆弱性的原因主要有以下几点:控件属性更改,开发者没有为用户界面元素提供唯一标识符,定位器仅基于组件文本作判断,组件排列被更改,组件被替换等情况。

图3 Appium原理图Fig.3 Appium schematic diagram

2.1.2 基于图像识别的自动化测试技术

Airtest[25]是一个跨平台的、基于图像识别的UI自动化测试框架,适用于安卓智能终端的游戏和App的UI 测试工作。Airtest 使用图像识别技术在当前安卓智能终端画面中查找对应的图片,然而图像识别并不能达到人眼识别的准确度,它只能尽可能地寻找一个最符合预期的结果。这就导致了测试人员认为不存在的图片,Airtest 认为存在,或者测试人员认为在画面上一眼就能找到的内容,Airtest 认为不存在。因此图像识别不是万能的,它是有成功率的。假设一个脚本里有10 张图片,每张图片的识别成功率都能达到95%,但合算10 张图片全部都正确识别的概率也不超过60%。因此基于图像识别的自动化测试技术的核心在于提升图片识别算法的准确率。Li 等人[26]设计一个基于YOLOv3(you only look once v3)的轻量级卷积网络,用于识别手机截屏中的UI 页面和按钮等特征,并建立了一个有向图模型存储访问的UI 页面及切换关系。该方法可以快速检查UI 是否符合设计要求,模拟测试用户点击行为。研究结果显示,该方法的UI页面和按钮覆盖率超过85%。

表1 从代表工作、门槛、性能、失败风险、适用场景和研究方向几个方面对三代用户界面测试技术进行了概括总结。

表1 安卓UI测试工具比较Table 1 Comparison of Android UI testing tools

2.2 模糊测试

模糊测试通过向程序或系统输入随机、不合法或异常的数据,刻意造成输入错误,推动程序或系统进入不合理的状态,从而触发潜在的漏洞或错误,寻找漏洞并加以修复。模糊测试的主要流程如图4 所示。Monkey[27]是一款安卓自带的命令行测试工具,通过模拟用户点击滑动屏幕、输入文本、按键等操作,Monkey 能够快速有效地检测应用程序的稳定性和鲁棒性。Monkey支持对安装在模拟器或手机设备上的应用程序包进行测试,并可根据用户设置的包、注入事件等约束,限制测试范围。Monkey 还能够在程序崩溃、无法响应或出现异常时立即停止并报告错误。尽管Monkey 能够生成大量事件序列,但由于其随机性较强,无法执行自定义的特定事件序列,并且对如来电或地理位置变化等系统级事件的支持不够强。

图4 模糊测试的几个阶段Fig.4 Several stages of fuzz testing

Machiry 等人[28]提出了一个使用“观察-选择-执行”原理来高效地生成测试用例的系统Dynodroid。通过选择频率、随机或基于偏好三种策略,Dynodroid捕获应用程序当前的空间列表并映射产生一组UI事件。同时Dynodroid 通过插桩监听系统事件的注册和注销,并把被注册的事件加入可执行系统事件的集合中。然后,工具会选择一个事件来执行并检测应用的状态。最终,在满足策略指定条件的时候停止执行。与Monkey 相比,Dynodroid 是一种向导式随机测试工具,它可以生成用户界面事件和更多的系统级事件,并且支持策略性的停止条件而非固定注入次数。但Dynodroid 仅支持在比较老的安卓2.3版本模拟器上运行,这在现今主流版本中显得有些落后,因此在适用性方面不如安卓原生的Monkey工具。

Li 等人[29]提出了基于状态转换模型的UI 引导的测试输入生成工具Droidbot。Droidbot的模型会根据实际的程序运行信息动态变化,并基于该转换模型生成基于深度优先策略的测试用例。此外,用户还可以编写脚本来定制探索策略,或通过扩展事件生成模块来集成自己的测试用例。Droidbot 还提供了一种新的测试用例有效性评估方法,能够为每个测试用例生成调用堆栈跟踪,其中包含由测试用例触发的App方法和系统方法,以便使用调用堆栈作为一个近似度量来量化测试用例的有效性。Droidbot 具有与Monkey 类似的易用性和适用性,同时提供了包括基于模型的输入生成和可扩展脚本编写等高级特性,类似于DynoDroid等其他工具。

Jamrozik 等人[30]提出并开发了工具DroidMate。DroidMate 通过在运行时重复读取设备的页面控件信息并监视对安卓API 方法的调用来动态生成测试数据。与DroidBot 类似,DroidMate 也试图探索不同的UI元素,但前者采用的是深度优先策略,后者则采用偏随机游走策略。从实验结果看,DroidMate 有着更好的性能并且可以在短时间内达到更高的覆盖率。

进一步的Li 等人[31]提出了Humanoid。Humanoid是一个能够学习人类如何与移动应用程序交互,然后像人类测试人员一样使用所学的模型来指导测试生成的GUI 测试生成器。借助从人类与设备交互中学习到的知识,Humanoid 可对GUI 页面上可能的交互进行优先级排序,并生成能够导致重要状态的测试用例。该工具核心是深度神经网络模型,预测哪些UI 元素更容易与人类用户交互,并指导测试用例生成过程。与前面所提及的几种工具不同,Humanoid利用了GUI 的可视化信息,这是用户探索应用程序时的重要参考,也让测试执行过程更加贴近于用户操作。

针对应用存在部分特殊交互逻辑场景而导致测试效率低下和覆盖率不理想的问题,叶佳等人[32]提出了结合先验知识和测试路径约束的规则驱动测试输入生成工具RDTA(rule-driven testing platform for Android)。RDTA 内置驱动引擎,可根据实时界面元素来筛选出特定符合规则的子集。这些规则定义了遍历子集合的顺序、驱动事件的操作方式以及子集合在整个集合中的优先级。相比其他测试工具,RDTA 可以针对性地快速进入具有复杂前置操作步骤的页面,避免因其引起的状态爆炸问题。

Adamo 等人[33]提出了一种强化学习方法来实现安卓应用程序的GUI 自动化测试。在缺少预先定义的抽象模型前提下,他们采用一种基于Q_Learning的测试生成算法,通过探索被测应用程序的GUI,根据存储在Q-table 中的Q 值来选择可获得最大收益的动作并执行。此外,瑞典开发商King 使用人工智能技术训练人工智能测试工具,该工具结合了蒙特卡洛树搜索算法、自动启发式构建算法和增强拓扑的神经元演化算法来模拟人类交互并运用于自动化测试中。

虽然上述提及了许多新兴的模糊测试工具,但目前除了Monkey 以外,Dynodroid、Droidbot、DroidMate 及Humanoid 都并未广泛应用于智能终端的集成测试体系中。这是由于这些新兴的模糊测试技术都依赖于特定的安卓版本,无法支持新版本中出现的全新接口或修改后的接口。此外,安卓系统也在不断更新自身的接口权限,部分工具使用的动作事件注入技术在后续的安卓版本中被视为非法权限操作,这也使得这部分工具无法在新版本的安卓系统中正常使用。表2 对安卓模糊测试方法中常用的工具在原理、性能、适用性、准确性等方面进行了概括和总结。

表2 安卓模糊测试方法比较Table 2 Comparison of Android fuzz testing approaches

综上所述,UI 测试和模糊测试等面向黑盒的安卓智能终端软件测试技术在可靠性和稳定性方面都存在着不可避免的缺陷。UI测试由于自身对于控件或图片强关联,使其在测试执行的稳定性和复用率方面效率低下。模糊测试则因为无法快速支持新版本,被认为在可移植性方面无法提供可靠的测试执行。针对这些缺陷需要考虑引入其他新兴技术,如人工智能[34]、自适应识别[35]等。

3 面向白盒的安卓智能终端软件测试技术

白盒测试主要用于检测软件编码过程中的错误,而程序员的编程经验、对编程软件的掌握程度、工作状态等因素都会对编程质量造成影响,导致代码错误。虽然普通的语法错误在软件调试时很容易发现,但是逻辑顺序、执行路径方面的错误在调试时很难被走查覆盖。通过白盒测试,可以检测编程代码中的每条分支和路径,并找到隐藏在代码中的错误,对代码进行全面的测试,达到优化的目的。

安卓应用程序是基于Java 开发的,它们被编译成Dalvik字节码,也有多种框架可以将Dalvik字节码转换成更熟悉、更易于分析和检测的中间文件格式(例如Java字节码、Jimple和Smali等)。因此,人们对安卓应用程序的静态分析和白盒测试技术进行了大量的研究。本文将从面向对象的单元测试、污点分析、第三方库检测和安卓权限检测四个方面对白盒的安卓智能终端软件测试技术进行综述。虽然静态污点分析、第三方库检测和权限检测等白盒测试技术不是严格意义上的自动化测试技术,但它们是安卓安全测试的重要组成部分。同时这些技术可以与其他自动化测试技术相结合,如可以结合污点分析和模糊测试,在模拟测试输入的同时监控安全信息流,形成一个完整的包含可靠性、稳定性和安全性的安卓测试链。故本文将这三种技术视为自动化测试的一部分,并进行了简单的归纳总结,方便读者理解全面的安卓测试链并帮助应用到实际项目中。

3.1 面向对象的单元测试技术

随着软件迭代速度的加快,开发工程师在持续集成和敏捷开发的大背景下,需要快速发现软件缺陷,针对新的代码执行相应的单元测试。然而,自动化测试最大的挑战在于需求变化,需要修改、扩展、调试自动化脚本以适应新的功能。如果自动化测试的投入产出比太低,其价值也失去意义。因此,越来越多的学者和企业工程师投入到实现自动生成单元测试用例的方法开发研究当中。图5 展示了单元测试用例自动生成的四个主要研究方向。

图5 测试用例生成的各种技术Fig.5 Various techniques of test case generation

3.1.1 基于随机的测试用例自动生成

随机测试是最基本的单元测试生成技术之一。当定向测试所需的时间过长或问题的复杂性使得无法测试每个组合时,人们往往会优先考虑进行随机测试。基于随机的测试用例自动生成可以在短时间内达到较高的覆盖率,并且生成的测试用例可以快速应用于持续集成流程中进行回归测试。

Artho 等人[36]介绍了随机测试原理:在面向对象的单元测试中,测试用例由一系列方法调用组成,每个步骤调用一个对象object 的方法method,表示为o.m(T1v1,T2v2,…,Tnvn),其中调用方法传入的Tivi是对应参数类型的值。生成一个随机测试用例,首先是创建object 使它可以接受method 的调用,其次构建Tivi类型的值作为调用method 的参数,对method 的成功调用将返回一个result,该值可在后续测试中用作其他方法的参数,如果调用过程中出现异常,则认为method没有通过测试。

由于随机生成算法没有考虑测试用例之间的关系以及测试用例对受测系统的影响,从而导致测试用例的重复性和低效性。因此,基于随机的测试用例生成方法,需要在考虑测试用例的全面性和适度性的同时,结合模型驱动、覆盖分析、数据挖掘等相关技术增量式、智能化地生成测试用例,从而实现更高效率和准确率的测试。

Chen等人[37]介绍了一种增强形式的随机测试——自适应随机测试(adaptive random testing,ART),它寻求在输入空间内更均匀地分布测试用例。同时实验证明ART 相较于传统的随机测试可以提升50%的缺陷检测效率。Csallner 等人[38]提出了一种针对Java代码的无向随机测试工具JCrasher。相比其他ART工具,JCrasher 对被测软件的构造没有任何假设和限制,它能够自动测试多个方法并执行大量测试用例,从而提高软件测试的覆盖率和精度。但是,JCrasher也存在一些问题,例如忽略异常可能揭示的错误,以及创建冗余和非法输入,这些问题也导致其执行效率较低。Pacheco等人[39]提出了一种用于改进随机测试生成的技术。该技术可以通过测试用例执行过程中的反馈来增量地构建输入,在构建输入后,根据过滤器进行过滤从而抛弃冗余、非法或违反预设规则的输入。同时该技术被应用到基于反馈定向的单元测试用例工具Randoop上。Randoop相较于JCrasher,能在相同的被测库下实现更高的覆盖率,发现更多的有效问题并减少冗余非法输入。Yatoh等人[40]研究了反馈定向随机测试生成的特点,并提出了一种利用过度反馈限制测试多样性的方法。首先,证明了反馈定向生成算法的反馈回路是一个正反馈回路,会放大候选值池中出现的偏差,从而过度指导生成并限制生成测试的多样性。因此,限制反馈的数量可以提高生成测试的多样性和有效性。其次,提出了一种反馈控制的随机测试生成方法,通过对反馈的主动控制来提高生成测试的多样性。与原来的反馈导向算法相比,该方法至少提高了78%的分支覆盖率。

3.1.2 基于符号执行的测试用例自动生成

符号执行是一种功能强大的程序分析技术,其概念诞生于20 世纪70 年代,可以同时探索一个程序在不同输入下可能采取的多种程序路径。由于其计算需要大量的处理能力和系统内存,在最近几年才被实践运用于测试用例生成。

符号执行将程序的执行路径表示为对输入值的约束,如图6 所示[41]。其中动态符号执行是一种常见的符号执行方法,它通过系统化地遍历程序的各个路径来生成新的测试用例。在每次迭代中,它会否定路径约束中的一个分支条件,并使用约束求解器为该路径生成一个新的测试用例。这类方法主要的目标是生成特定的输入数据,需要手工构建相应的测试驱动程序。另一种符号执行方法是静态符号执行,它在每个分支节点上更新路径条件,然后使用约束求解器判断路径是否可行。如果路径不可行,就回溯到上一个节点,因此只执行可行路径。然而,由于安卓框架非常复杂,而且是用多种语言构建,很难将符号执行技术应用于面向框架的安卓应用。此外,安卓框架不能在安卓设备/模拟器之外执行,这也成为使用符号执行技术测试的一大难题。

图6 符号执行示例图Fig.6 Symbol execution example diagram

Mirzaei 等人[42]提出了一种适用于安卓应用程序的新符号执行方法。该方法扩展了JPF(Java Pathfinder),并结合安卓系统的调用图模型生成测试用例。该方法通过创建存根、编译和运行应用程序、创建模拟类来解决路径分歧,并自动生成模拟用户行为的驱动程序,从而有效地提高符号执行的效率。Luo 等人[43]提出了一种用于安卓框架符号执行的路径探索系统Centaur。为解决符号执行的状态空间爆炸问题,Centaur使用了分阶段符号执行的方法,在初始化阶段运行,并使用微小污染分析的方式获得来自恶意应用程序的变量识别作为符号输入。同时Centaur 完整分析了中间件的服务接口方法,为安卓符号执行提供了完整的上下文,极大地提高了探索安卓路径的准确率。Gao 等人[44]为安卓应用程序构建了一个动态符号执行引擎。引擎支持自动建模执行环境,自动推断库的表示,并通过多次运行相应的库动态优化相应表示,以提高行为覆盖率和缓解路径分歧问题。此外,引擎支持上下文,可以为给定的上下文生成更精确的表达式,从而提高合成效率。该符号执行引擎相比JPF 可以在相同执行时间内覆盖更多的分支目标。

综合来说,近年来研究人员提出的面向安卓的符号执行优化方向,主要集中于约束缩减、上下文理解、处理Android 特有的功能和特性等方法,这些方法可以缓解路径爆炸问题并一定程度地提高测试效率。目前,虽然面向安卓的基于符号执行的测试用例自动生成方法相关工作已经在安卓应用程序的测试领域得到了一定的应用,但依然受限于路径爆炸、安卓特性、跨应用程序路径等问题。

3.1.3 基于搜索的测试用例自动生成

基于搜索的软件测试(search-based software testing,SBST)是测试用例自动生成的一个子领域,最初由Harman 和Jones[45]于2001 年提出。SBST 的重点是元启发式搜索算法和进化算法的使用,如爬山算法(hill-climbing,HC)、模拟退火算法(simulated annealing,SA)、遗传算法(genetic algorithm,GA)等。这些基于搜索的算法每一个都强烈地依赖于所考虑问题的领域,并使用与问题领域相关的启发式知识,各有优缺点[46]。SBST可以定义不同的适应度函数来针对不同的测试目标,从而允许将相同的基于搜索的总体优化策略应用于不同的测试用例生成场景。因此,问题的表示和适应度函数的定义是应用基于搜索的优化技术的两个关键要素。在软件测试领域应用最广泛的算法如下所述。

爬山算法是一种局部贪心搜索算法,旨在目标函数的最大化。它从搜索空间随机选择的初始解开始,在每次迭代中研究当前解的邻域,一旦出现更好的临近解,就会取代当前的解决方案。然而,爬山方法可能会陷入搜索到局部最优解而不是全局最优解的问题。模拟退火算法基于退火的化学过程,允许在搜索空间周围的限制条件下概率移动到较差的临近解以避免局部极大值。然而,模拟退火算法也存在一些问题,如初始温度设置问题和计算时间问题。遗传算法是一种基于种群的搜索算法,由美国密执安大学的Holland 教授于1975 年提出,是一种通过模拟自然进化过程搜索最优解的方法。它创造并维持由染色体代表的个体群体,这些染色体按照选择、突变和繁殖的规则进行进化。每个个体都接受一个环境适应性的度量,高适应值的个体通过交叉和变异得到一个新的群体,其中的个体可以更好地适应环境。算法将不断迭代,直到群体进化形成问题的解决方案,或者迭代次数达到最大值。虽然爬山算法和模拟退火算法也可用于基于搜索的测试用例自动生成,但由于遗传算法搜索空间更大、更容易跳出局部最优解等特点,在寻找全局最优解方面更具优势。因此,遗传算法被更广泛地应用于基于搜索的测试用例自动生成中。

如图7所示,遗传算法在测试用例自动生成上的主要过程有以下几步:首先,对待测程序进行静态分析,获取生成用例时所需要的参数信息(类型、数量、范围等);其次,根据控制流程图确定要进行测试的目标分支路径;接着,根据测试要求构造适应度函数,利用插桩技术对被测代码进行插桩,生成对应桩程序;最后,通过遗传算法生成覆盖目标路径的测试用例。EvoSuite[47]是一个被广泛使用的基于搜索的单元测试用例生成工具,支持使用常规遗传算法、动态多目标排序算法(dynamic many-objective sorting algorithm,DynaMOSA)等,优化过程由一组个体适应度函数驱动,每个覆盖目标都对应一个适应度函数,测试用例的编码由可变长度的Java 语句序列组成,优化目标是找到一个最大化代码覆盖率的测试集[48]。EvoSuite具有高度的自动化、代码覆盖率高以及可解释性强等优点,但也存在着无法完全检测所有可能的执行路径、无法支持安卓原生语句、生成的测试用例质量不稳定等缺点,这些缺点需要在实际应用中加以注意和克服。

图7 SBST流程图Fig.7 SBST flow chart

单一的未经过优化的智能算法往往存在固有缺陷,遗传算法也不例外。在使用传统遗传算法生成单元测试用例时,常常会出现稳定性较差、计算量大、约束失效、早熟收敛等一系列问题。因此许多学者和机构都投入到了优化遗传算法的研究中。目前,改进遗传算法的应用大致可以分为四个方向:改进遗传算子,改善适应度函数,融合其他算法,遗传算法并行化。

改进遗传算子:遗传算法中有选择算子、交叉算子和变异算子三种主要的遗传算子控制着搜索过程。Zhu 等人[49]提出了三种基于约束的针对性改进SBST 遗传算子。首先,针对选择算子,使用符号执行技术来辅助选择具有更多有用启发式信息的测试用例。然后,基于约束的交叉算子对概率较大的测试用例进行重组,产生更好的后代个体。最后,利用基于约束的变异算子对测试用例进行改进,以满足特定的约束条件。Cruz-Salinas 等人[50]提出了一种自适应算子进化算法。该算法定义了一种惩罚-奖励机制,使个体根据算子的质量进化,再使用轮盘赌算法对算子进行重组,使其按质量成比例演化。这种方式可以加快收敛速度,丰富种群多样性,并且不会陷入早熟收敛。另外,Doerr 等人[51]提出了一种使用幂律分布选择的随机突变率策略,这种新的变异算子在测试集函数中有着最优的性能。

改善适应度函数:Kim 等人[52]提出了基于局部优化算法(local optimization procedure,LOP)评估适应度函数的遗传算法,用于解决进化过程中产生大量的候选解使得评估时间过长的问题。该方法在早期生成阶段只使用部分边缘子集计算解的近似适应度,并逐步增加边缘子集直到精确拟合,有效减少了运行时间。杨瑞等人[53]提出了一种新的测试用例生成方法。该方法利用开发的可执行模型动态获取运行时反馈信息,结合分散搜索技术自动生成测试数据,并创建预言信息。相较于传统方法,该方法中的适应度函数计算代价较低,可以忽略不同数据类型的差异性问题,使其更具通用性。该方法充分利用运行时信息计算适应度,适用于多种数据类型的测试用例生成,是一种高效通用的测试用例自动生成方法。Wang等人[54]提出了一种改进的用户偏好多目标遗传算法(user-preference multi-objective optimization algorithm,UPMOA),将用户偏好指标定义并集成到算法当中。该算法根据用户对各种目标的偏好来评估特定解决方案的质量,并将指标分为需要最大化的有效性目标和需要最小化的成本目标。在均匀分布权重策略下,UPMOA 可以在问题复杂性不断增加的情况下提高软件性能。Xu 等人[55]提出了一种基于分支硬度的自适应适应度函数,通过建模吸收离散时间马尔可夫链来度量程序中每个分支的预期访问次数,通过启发式地调整分支硬度参数,可以使生成测试用例的搜索硬度最小化。该方法比传统适应度函数更加灵活。后续他们又提出了一种动态的适应度函数[56]来提高自动生成测试用例的分支覆盖性能。

融合其他算法:Braione 等人[57]使用符号执行来生成描述程序路径和输入结构之间依赖关系的路径条件,并将路径条件转换为优化问题,再使用基于搜索的技术生成实例化这些输入的方法调用序列。该方法可以实例化从具有复杂数据结构的程序的符号执行派生的路径条件,从而为依赖于复杂输入的测试目标生成具体的测试用例。Kim 等人[58]提出了用深度神经网络训练一个双深度Q网络(double deep Qnetworks,DDQN)智能体,并代理学习SBST 的元启发式算法,将SBST 理解为强化学习问题,通过不断地迭代试错从适应度函数的反馈中找到最优算法。Ayari 等人[59]提出了一种基于蚁群算法的进化方法来降低自动生成单元测试中的成本,使用概率密度估计技术指导连续输入参数的搜索,并定义适应度函数用于衡量测试用例杀死突变体的程度。基于蚁群算法改进的遗传算法在迭代次数和搜索时间上,都优于标准的遗传算法。Ji[60]引入了模拟退火算法,将环境适应度作为可变参数进行处理,并建立环境适应度与迭代次数直接的拉伸关系。同时引入轮盘赌选择机制,保证产生的后代与环境适应度正相关,实现后代进化的可持续优化选择。实验结果表明,改进后的遗传算法可以解决优化过程中易陷于局部最优、搜索初值依赖性等问题。张大林等人[61]提出了一种基于主动学习和预测引导的自动化测试工具Auto-Unit。AutoUnit 引入了缺陷预测算法模型,对待测文件池中的所有文件进行缺陷预测,然后对最可疑的文件进行测试用例生成,之后将实际测试用例执行结果反馈给缺陷预测模型并更新该预测模型,最后根据召回率判断是否进入下一轮测试。与EvoSuite相比,AutoUnit能以更少的测试代价发现同等水平的代码缺陷,有效地提高了测试效率。

遗传算法并行化:遗传算法的长时间运行与问题维数很大、需要定制运算符、复杂目标函数需要几分钟计算、处理大型数据集、大量非线性限制等原因有关。由于遗传算法是基于种群的方法,所有候选解都可以并行处理,非常适合并行化。Paduraru等人[62]提出了一种分布式实现的遗传算法,并设计了基于特定“概率”的适应度函数,即某些分支条件以某种顺序出现,并使用它们指导测试走向尚未探索的领域。

3.1.4 其他测试用例自动生成

除了上文提到的方法,还有其他一些基于目标导向的方法来自动生成测试用例。Ferguson等人[63]提出了一种基于链式的自动生成软件测试用例的方法。链式方法使用数据相关性分析来指导搜索过程。数据相关性分析能自动识别影响代码执行的语句,链式方法则使用这些语句来准确生成测试用例。Korel等人[64]提出了一种基于断言自动测试用例生成方法。该方法是链式方法的扩展,将断言插入约束条件来识别违反断言的测试用例,并利用其揭示程序中的错误。最终将查找违反断言的程序输入的问题简化为查找执行选定语句的程序输入的问题。表3 展示了不同面向对象的单元测试技术对比。

表3 面向对象的单元测试技术对比Table 3 Comparison of object-oriented unit testing techniques

综上所述,目前已实现的自动生成单元测试用例技术在覆盖标准上,选择的都是条件覆盖、语句覆盖、分支覆盖这三种标准,而忽略了路径覆盖。这是由于路径覆盖的测试用例生成存在路径爆炸、循环控制流处理困难、分支语句嵌套复杂、动态路径无法探测等问题,使得路径覆盖用例生成技术无法满足正常的测试实践。但与其他覆盖标准相比,路径覆盖测试可以更有效地覆盖程序中的每个可能路径,包括所有的代码分支和语句,以确保所有的情况都被考虑到,测试用例的覆盖率也更高。且路径覆盖测试可以发现程序中的更多缺陷,包括隐藏的或难以发现的缺陷,因此路径覆盖可以更有效地提高程序的可靠性和稳定性。未来的自动生成单元测试用例技术需要更加重视路径覆盖标准的技术实现。

3.2 污点分析测试技术

安卓智能终端的安全问题一直是安卓测试技术研究的重点。在移动支付、电子商务和社交网络等活动中,大量的用户隐私数据容易在第三方移动应用程序中泄露,因此保护用户隐私已成为一项紧迫任务。污点分析技术是一种信息流分析方法,可通过标记系统中的敏感数据来跟踪它们在程序中的传播,进而自动检测系统中的安全问题。对于安卓应用的隐私泄露问题而言,污点分析是一种相对有效的解决方法。例如,当存在一段安卓应用程序代码,该程序运行会导致用户的密码数据通过发送短信的方式泄露时,污点分析技术首先识别引入敏感数据的接口,并进行相应的标记。如果被标记的变量又通过程序依赖关系传播到其他变量,那么根据相关传播规则继续标记对应的变量。当被标记的变量到达信息泄露的位置时,就可以根据预先设定的安全策略进行检测。这样,污点分析技术可以较为准确地检测出安卓应用程序中的隐私泄露问题,从而提高系统的安全性。污点分析又分为静态和动态的污点分析。

3.2.1 动态污点分析

动态污点分析是一种基于动态信息流分析的技术,其主要原理是在应用程序运行时标记相关数据,并通过跟踪其在内存中的显式传播过程来监控应用程序的行为,如图8 所示。要实现动态污点分析,需要解决三个主要问题:确定污点源,制定污点传播规则,以及选取污点检测点。通过这些步骤,可以对敏感数据进行有效的跟踪和分析,从而增强系统的安全性。

图8 动态污点分析流程图Fig.8 Dynamic taint analysis flow chart

Enck 等人[65]提出了一个支持实时监控第三方应用程序访问和操作用户个人数据的高效动态污点跟踪和分析系统TaintDroid。为了获取分析应用程序行为所需的上下文信息,TaintDroid 通过修改Dakvik虚拟机并对字节码执行过程进行动态插桩来给隐私敏感源的数据添加标签,并在敏感数据通过程序变量、文件和进程间消息传播时传递应用标签。当污染数据通过网络传输或以其他方式离开系统时,TaintDroid 会记录该标签所对应的应用程序以及隐私数据的发送链接,以此识别存在安全风险的应用程序。但由于需要修改虚拟机、弹性和透明度低等问题,TaintDroid 无法被广泛应用到各个版本的安卓系统中。

Xu 等人[66]提出了一个能够对安卓应用程序进行细粒度区分的动态污点策略分析工具Aurasium。相较于TaintDroid,Aurasium 不需要修改安卓操作系统或虚拟机,它通过重新打包将沙盒代码直接附加到三方应用程序本身,并通过上层的沙盒代码对应用程序进行监视和实施安全隐私策略。通过沙盒代码,Aurasium 能够在应用程序和操作系统之间插入各种功能的监视模块,执行比安卓内置权限系统更细粒度的安全隐私策略。但Aurasium 使用较为单一的沙盒程序,也使得其容易被恶意应用程序规避检测。

Tam等人[67]提出了一个基于虚拟手机设备(virtual mobile infrastructure,VMI)的自动动态污点分析系统CopperDroid。CopperDroid 通过在VMI 中运行应用程序,对执行过程进行跟踪和监视,收集应用程序的行为数据,并对这些数据进行可视化展示和分析。同时CopperDroid 还支持自定义规则和插件,可用于检测和分析应用程序中的各种攻击和漏洞类型,如隐私泄露、恶意软件、代码注入等。相较于其他工具,CopperDroid 基于VMI 的以系统调用为中心的分析,可以有效地防止应用程序规避检测,同时也使系统的内部信息变化更加直观和透明。但因为CopperDroid 是在模拟器环境中执行应用程序,所以分析结果并不完全可靠,可能存在误报或漏报等情况。

3.2.2 静态污点分析

静态污点分析是一种基于程序变量之间数据依赖关系的污点分析技术,在不运行代码的情况下对应用程序进行安全检测。相对于动态污点分析,静态污点分析具有一些明显的优势:首先,它可以在程序发布前对应用程序的安全性进行检测,避免发布后造成安全问题;其次,它具有较高的分析覆盖率,无需依赖测试集合;此外,它不需要程序插桩,避免了可能导致程序运行开销的问题。在进行静态污点分析时,通常会对程序的控制流图和数据流图进行分析,并根据变量之间的数据依赖关系来标记敏感数据的源头及其传播路径。通过这种方式可以快速识别可能存在的信息泄露风险,并提出有效的修复措施。

Arzt等人[68]提出了一个高精度、高性能静态污点分析系统FlowDroid。FlowDroid 利用反编译工具Dexpler 和Java 分析工具Soot[69]将apk 文件转化成Soot 中间表示Jimple,随后在Jimple 上进行静态的污点分析。FlowDroid 根据上下文精确地建模整个安卓生命周期信息,可以有效提高精确度和召回率,并减少漏检和错检。但FlowDroid 不支持组件间通信的检测,且不能准确地解析和跟踪部分高级操作的意图。王蕾等人[70]在FlowDroid的基础上优化并提出了一种多源污点分析系统MultiFlow。针对FlowDroid结果数量多但精度低的问题,MultiFlow利用多源绑定特性增强污点分析,使其可以判断多个污点源是否可在一次执行中绑定发生,从而显著提高安卓应用隐私泄露检测的精度。Wei 等人[71]提出了实现流和上下文敏感的组件内数据流污点分析工具AmAndroid。在过程间控制流图和数据流图的基础上,AmAndroid创新性地为每个组件构建一个数据依赖图,并生成一个汇总表,以记录可能的组件通信连接。相较于FlowDroid,AmAndroid 可以基于专有的组件间和应用程序间流分析来进行组件间通信和应用程序间通信的污点检测。然而,由于处理异常和反射的能力有限,AmAndroid无法检测并分析隐式污点流。Gordon 等人[72]提出了一个对象敏感和流不敏感的污点分析工具DroidSafe。DroidSafe专门为安卓构建了一个执行模型以精确地跟踪通过安卓API 的流。同时DroidSafe使用字符串分析将反射调用替换为对目标方法的直接调用,也使得污点分析流更加完整。但由于真实项目代码量大且复杂,DroidSafe分析及调试过程成本高等问题,DroidSafe 也未被广泛应用于实际的软件工程项目。

表4 展示了动静态污点分析在技术优势、局限性、性能、准确率这几个评价指标下的对比结果。污点分析技术虽然在安卓应用的识别和修复潜在的安全漏洞方面取得了一定的成果,但在可靠性和稳定性方面仍存在十分明显的缺陷和难点。首先,由于计算机程序的控制流和数据流非常复杂,污点分析往往会遇到路径爆炸问题。当程序中存在大量循环和分支语句时,污点分析的路径数会呈指数级增长,导致分析时间和空间成本极其不稳定。其次,在污点分析中,程序执行的上下文环境非常重要,例如程序的输入、输出和状态等,但是目前技术很难精确地获取和分析这些上下文信息,导致污点分析的准确性和可靠性受到影响。再次,已有的污点分析技术往往会产生大量的误报,即将正常的程序行为误认为是安全漏洞。这是由于程序中存在大量的复杂控制流和数据流,而污点分析很难准确地区分哪些行为是正常的,哪些行为是异常的。最后,污点分析技术的可扩展性比较差,即难以应对大规模、复杂的程序分析。这是由于污点分析需要对程序的控制流和数据流进行深入分析,而这些分析往往需要消耗大量的计算资源和存储空间。

表4 安卓污点分析技术方法比较Table 4 Comparison of Android taint analysis technique approaches

3.3 其他安卓白盒测试技术

除单元测试和污点分析外,还有其他安卓白盒测试技术可以通过了解和分析应用程序的内部实现和结构,以及程序运行时的行为情况,来发现软件中可能存在的问题和缺陷,如第三方库安全测试、安卓权限安全测试等。

3.3.1 第三方库安全测试

第三方库是软件开发的重要组成部分。在安卓生态系统中,开发人员可以借助第三方库的不同功能来提高应用程序的开发效率。然而,第三方库使用的普及也带来了新的挑战和威胁。恶意或易受攻击的代码可能会隐藏在第三方库中,这些代码可能会感染广泛使用的应用程序,对用户的信息安全构成威胁。

通常,检测第三方库有基于白名单和基于特征提取两种方式,如图9所示。最初的重打包检测和恶意软件检测大多采用基于白名单的方式,即过滤掉已知的恶意第三方库。例如,Chen 等人[73]使用了一份包含73 个经过筛选的第三方库的白名单。Lin 等人[74]以手动方式对接近400 个第三方库进行了标记,并对它们进行了功能分类。Zhou 等人[75]开发了应用程序相似性度量系统DroidMOSS,基于白名单并利用模糊哈希技术来检测应用程序重打包行为的变化。然而,这种方法很容易被包重命名所规避,并且随着混淆技术的兴起,基于白名单的方法的有效性也大大降低。因此,越来越多的研究者开始使用基于特征提取的方式,直接从第三方库中提取关键特征来识别恶意程序。Liu等人[76]针对安卓程序中的广告第三方库,使用基于字节码静态分析提取特征的机器分类器,提出了一种高效、准确、自动且抗混淆的方法PEDAL,用于识别嵌入在应用程序二进制文件中的广告库。Ishio 等人[77]提出了一种自动检测目标程序中包含类文件jar的方法。该方法使用贪婪算法检索可疑三方jar文件列表。报告的文件列表可帮助开发人员和用户评估由应用程序中的第三方库引起的潜在风险。Backes 等人[78]提出了LibScout,用于确定第三方库是否被混淆并准确判断库的版本。LibScout使用哈希特征进行检测,重点提取类之间的层次结构信息。黄思荣等人[79]提出了LibSeeker,它在LibScout基础上增加了对方法特征的提取,完善了LibScout 的不足。LibSeeker 利用置信区间上界算法和ROC 曲线简化参数自整定,提高了第三方库检测的效率。

图9 第三方库安全测试技术Fig.9 Third-party library testing technology

虽然现在已有成熟的商业产品广泛应用于安卓移动终端的第三方库检测,但仍存在一些不足。首先,应用程序中使用的第三方库通常具有复杂的依赖关系,如嵌套依赖、版本冲突等,使得已有检测工具需要考虑多个库之间的交互影响,增加了检测的难度,可靠性降低。其次,由于不同的应用程序使用的第三方库不同,检测工具需要具有一定的适配性。但是由于库的数量庞大,工具开发者需要花费大量时间来适配各种库,限制了工具的覆盖率和稳定性。因此,需要进一步地研究和改进,以提高第三方库检测技术的可靠性和稳定性。表5 展示了安卓第三方库检测不同代表工作的优劣势对比。

表5 安卓第三方库检测方法比较Table 5 Comparison of Android third-party library detection approaches

3.3.2 安卓权限安全测试

安卓因其开源性,长期以来一直是恶意软件攻击的主要目标。其中一个主要漏洞来源就是权限机制。为保障用户数据的安全,安卓要求应用程序在访问用户敏感数据(如联系人和短信)以及某些系统功能(如摄像头和网络访问)时请求相应的权限。安卓的安全性在很大程度上取决于这种权限机制的有效性。然而,恶意软件可能会偷偷地申请额外权限,以获取用户的敏感和私人数据,而这也是安卓系统的潜在危险之一。

为了应对这一风险,安卓权限检测技术被不断提升和完善。目前,安卓权限检测技术大致可以分为三种类型。第一种是基于描述的权限检测技术。该技术使用静态分析方法,解析应用程序相关的代码权限,并分析应用程序实际调用的权限,从而得到应用程序最小权限集。Xiao 等人[80]提出了一种超声明权限识别算法MPDroid。MPDroid 采用线性判别分析(linear discriminant analysis,LDA)技术和改进的协同过滤推荐算法来识别和删除应用程序过度声明的权限。徐尉等人[81]提出了基于应用功能类别分析的安卓应用权限泄露检测系统PACS(permission abuse checking system)。该系统通过分析应用评论数据和简介文本判断功能类别,反编译apk 文件获取权限信息,统计同类应用频繁申请的权限构建权限频繁项集,并根据类别下的频繁权限集判断应用是否存在异常权限申请,从而检测权限滥用行为,实现了基于应用功能对权限滥用情况进行有针对性检测的系统。第二种是基于接口的权限检测技术。该技术通过数据融合方法和基于挖掘的技术,根据应用程序使用的API和API描述,为给定的应用程序推荐权限。Liu等人[82]提出了一个新的安卓应用权限推荐系统PerRec,其中协作过滤组件和基于内容的推荐组件的结合使系统性能更佳。但由于安卓系统版本迭代速度不断加快,第三方库不断地被各应用所使用,API 的数量也不断地增加,功能和描述也随之变化,这就造成了该方法的适用性略显不足。第三种是基于隐私政策的权限检测技术。Yu 等人[83]提出利用应用程序的隐私策略及其字节码来增强基于描述和权限的恶意软件检测,自动分析隐私策略,并在隐私策略、字节码、描述和权限之间执行交叉验证。该模型描述了个人信息是如何被处理和传输的,并指导软件定义语义,包括数据聚合、完整性和安全性。但由于隐私政策是开发者自己撰写的,可能其声明的隐私权限未必是应用程序所需要的,部分使用到的权限也可能并未在隐私政策中提及。

除了上述内容,安卓权限检测技术还需要考虑用户态与内核态权限管理、安全性与用户体验的平衡、动态越权、设备多样性等问题,这些问题也导致了安卓权限检测技术在可靠性和稳定性方面无法达到最优的测试实践。

4 挑战与展望

测试技术是智能终端系统中至关重要的基础技术,它可以显著提高智能终端系统的可靠性和稳定性。尽管软件测试在过去几年中已经取得了重大进步,但仍存在一些重要的历史问题,如成本高、效率低、精度差等。而现在,随着新兴技术(如人工智能大模型)的出现,这些问题变得更加复杂和具有挑战性,同时也引出复杂性、异构性、不透明性等新问题。因此,本文将从历史技术和人工智能新技术两个角度探讨这些问题和挑战,并为其提供解决思路,如图10所示。

图10 安卓智能终端自动化测试技术挑战与展望Fig.10 Challenges and prospects of Android intelligent terminal automation testing

4.1 安卓自动化测试面临的历史挑战

在黑盒测试方面,随着新兴技术的涌现,应用程序变得更加复杂,交付速度也越来越快,这给软件测试带来了更多的挑战。对于安卓智能终端黑盒测试的可靠性和稳定性,存在以下几个关键问题:

第一,高维护成本。随着项目迭代速度的提高,黑盒自动化测试需要不断调试代码以适应新版本UI的更新,导致维护成本升高。

第二,非全自动化运行。尽管部分自动化执行步骤可以自动生成和运行,但某些步骤仍需要人工干预,例如设置环境和运行数据等。此外,自动化运行有时可能会误报结果,而误报排查往往也需要人工确认。

第三,长时间执行。黑盒自动化测试会随着用例数量的不断增加,导致执行时间越来越长,问题暴露得也越来越晚。为了跟上版本迭代速度,开发人员可能会选择直接发布最新版本,从而使自动化测试工作形同虚设。

在白盒测试方面,尽管单元测试用例自动生成技术已经在许多软件领域得到广泛应用,但对于安卓智能终端领域的系统测试仍然存在许多挑战。

对于符号执行,研究人员仍然面临提高可拓展性和可用性的双重挑战。可拓展性是指如何在有限的资源下提高符号执行的效率,以更快地达到最终目标。路径空间爆炸和约束求解就是可拓展性的两个主要难点。目前主要的研究有四个方面:(1)针对具体目标提供高效的搜索策略;(2)通过约束输入范围、削减或合并路径等方式来减少程序的路径空间;(3)在调用求解器之前对路径条件的查询进行优化,以减少求解器的调用次数或缩短求解时间;(4)支持覆盖程序特征的高效编码。在可行性方面,环境建模和多形态分析目标支持则是主要难点。主要的研究方向是在分析的精确性、可靠性、建模工作量之间进行权衡和折中,并不断探索更多的语言和应用领域。

对于遗传算法,研究人员则面临非数值行变量的处理和初始参数确定两个方面的挑战。对于初始参数,遗传算法中的种群大小和遗传算子概率等参数通常是随机设置的,如何进行智能设置以提高测试生成的效率和准确性是一个亟待解决的问题。在安卓智能终端领域,由于存在复杂的变量类型和类成员变量,如何选择合适的编码策略也是需要研究的问题。研究人员需要针对不同场景和应用,选择最佳的编码策略和参数配置,以实现更加准确和高效的遗传算法测试生成。

在新兴技术方面,越来越多的智能终端设备已经开始搭载了包括语音助手、图像识别和光学字符识别(optical character recognition,OCR)提取在内的各种深度学习模型。尽管这些模型增强了智能终端系统的功能性,但是同时也给系统中的测试带来了新的挑战。以目前广泛使用的人工智能大模型技术GPT(generative pre-trained transformer)为例,其在复杂性、异构性和不透明性方面都对测试提出了更高的要求。复杂性主要体现在人工智能系统内部组件之间的相互依存关系和交互作用上,这种交互作用使得测试人员很难预测系统在不同条件下的行为,从而增加了系统中缺陷识别的难度。异构性的挑战则来自于系统集成了多种可能具有不同特征和行为的组件,导致测试结果存在差异和错误。不透明性则指的是测试人员时常无法理解人工智能系统如何完成某些任务或产生特定输出。在深度学习模型中,模型通常被视为“黑盒”,这使得在发现缺陷时准确确定系统是如何作出特定响应变得十分困难。

4.2 安卓自动化测试最新研究方向

针对传统黑盒测试出现的高成本、低效率等问题,可以考虑优化历史算法模型,运用微搜索算法思想来解决。测试用例编码空间的多样性、大规模和复杂性会造成测试用例生成需要高计算代价,影响测试效率。借鉴微搜索算法思想,研究人员可以获取测试用例的编码空间,然后通过流形优化获取满足约束的测试用例[84]。笔者所在的课题组研究了一种交互式测试用例的自动生成方法[85],该方法通过遍历应用程序UI 界面中的可点击视图,自动生成与用户点击交互相关的测试用例。当应用程序的UI界面显示后,通过算法遍历应用程序UI 界面对应的视图树中的所有视图,并记录其中可点击视图在视图树中的路径,进行智能的出入栈操作,获得UI界面中所有可点击视图在视图树中的路径信息的集合。对该路径信息集合中的每一路径信息分别生成对应的测试用例,在测试用例中,根据待测试视图在视图树中的路径信息,在应用程序UI界面中查找到该视图,并触发其点击事件,即完成对该视图的点击交互测试,然后将操作对应的代码写入测试用例文件,生成该视图对应的测试用例。该方法还有待在主流的安卓应用上进行覆盖率、误报率等验证。

白盒测试方面,安卓系统需要在自己的Dalvik虚拟机上运行而非JVM(Java virtual machine),如何更好地自动生成安卓能执行的单元测试用例依旧是一个技术空白。目前课题组开始研究如何在JVM 上运行安卓测试,并自动化生成测试用例[86]。该研究通过演化算法生成随机且覆盖边界计算、断言以及测试数据多样化的测试用例,并直接基于JVM 的环境构建进行安卓单元测试执行的框架。框架可以分为两大模块,即测试用例生成模块和测试用例执行模块。测试用例生成模块是该测试框架的核心部分,主要负责生成可执行的测试用例集。在该模块中,首先需要对源测试文件进行解构分析,然后执行演化算法,根据不同的操作,如产生新的测试分支、对原值进行突变修改或直接随机插入新的测试片段语句,来构建一个独立的测试用例集,直到生成一个完整的测试用例集。同时,在安卓组件的构造中会涉及到一些特殊的语句,如new 语句等,因此在初始化种群的过程中需要进行安卓化语句替换,以满足安卓组件的构造要求。测试用例执行模块则是负责将测试用例集加载到指定的测试环境中进行测试执行,直到返回测试结果。在该模块中,使用JunitCore 作为测试运行器,查找到对应的运行器并采用该运行器执行测试用例。由于测试用例中可能包含需要依赖于安卓运行环境的代码片段,但预先设置的运行器本身就是具有该安卓测试环境的,即使在JVM 中,也可以正常通过该第三方测试框架执行用例。

另外,针对基于JVM 的单元测试执行对安卓文件编译的大量耗时问题,课题组提出了一种新的技术方案,通过目标信息插桩和预先设置的静态类初始化测试用例语句直接执行安卓语句,从而避免动态编译过程。这种方案本质上采用了hook 技术,通过测试容器的静态接口获取测试语句运行。与直接执行字节码形式的单元测试相比,该方法可以避免安卓文件编译的大量耗时,并且能够更快速地执行测试用例。课题组计划将用例生成算法和测试容器开发成可直接执行的Gradle 插件,并通过对几款主流开源应用进行逆向技术测试和验证优化,以证明该技术方案的效果。如果达到预期目标,还计划将该用例生成算法和测试容器应用到谷歌应用商店上的主流应用安装包,以进一步优化测试效率和准确性。

4.3 人工智能与自动化测试的结合

随着人工智能技术的持续发展,人们可以利用更多的数据和更先进的技术来训练更复杂的人工智能模型。这些模型通常使用数以亿计的参数,并依托于庞大的训练数据集,可以提供更高的准确率和泛化能力。该能力可以为自动化测试等需要处理大量数据和高复杂性任务的应用场景提供非常重要的帮助。同时,这些模型也可以通过训练数据的深度学习来形成更强的智能化和自适应性,能够更好地适应复杂的测试数据和编码场景。

对于黑盒测试,首先,针对传统的测试用例设计方法需要大量的人力和时间,并且难以保证覆盖所有功能点的痛点,人工智能大模型可以充当测试想法生成器,根据测试人员提供的信息,提供新的测试用例设计思路和建议,从而帮助测试人员更好地设计测试用例,并覆盖更多的功能点。如基于GPT-3模型的ChatGPT 已被应用到很多领域,其支持在用户的提示下,生成所需要的任何专业想法,可以有效帮助用户扩展或优化思路[87]。虽然ChatGPT 目前还没有被广泛应用到测试领域,但依旧是一个值得期待的研究方向。

其次,针对自动化测试用例的生成通常需要大量的时间和经验的痛点,人工智能大模型可以为测试人员提供有关自动化测试用例生成的应用程序和工具,以及最佳实践和建议,快速生成自动化测试用例,提高测试效率和测试质量。Mathur等人[88]结合了T5(transfer text-to-text transformer)模型的自然语言理解和GPT-3 的自然语言生成来自动生成用例。通过将微调的T5 会话上下文知识应用到GPT-3 模型,可以准确识别相关的测试关键字,在没有任何人为干预的情况下快速生成测试用例。不过由于训练集不足等原因,该模型并未覆盖所有软件测试场景。但该研究证明了从对话中生成测试用例的可行性,后续研究的关键是提高模型生成的测试用例的准确性和完整性。

最后,针对难以实现全自动化的痛点,人工智能大模型可以通过自注意力机制来处理输入的测试数据,更好地理解测试用例的自然语言描述,并帮助测试工具准确识别下一步采取的期望行动。此外,人工智能大模型可以被微调以识别特定领域的编程语言,从而更好地理解测试用例和被测软件的上下文。Zimmermann 等人[89]提出了使用GPT-3 来进行软件测试,并演示了Transformer 架构应用于解释自然语言测试用例和指导被测应用程序的全过程。由于模型训练的成本原因,他们选择较为简单的应用进行基础实验。结果表明GPT-3 能够以最小人工测试成本完成测试用例,这也侧面验证了使用GPT-3进行自动化测试以消除需要手动编写和适配测试用例成本的可行性。

与黑盒测试一样,如何利用人工智能大模型完善测试技术也是白盒测试需要关注的重点。针对程序代码语义理解难的问题,人工智能大模型可以通过学习程序代码的语义和结构,更好地理解代码的含义和功能,从而帮助测试人员在白盒测试中发现潜在的问题。Prenner 等人[90]研究了基于GPT-3 的编程语言预训练模型CodeX。实验结果表明CodeX 在自动程序修复方面相比于其他技术的历史工作(DeepDebug[91]、CoCoNuT[92]、CURE[93])有着最高的准确率。与符号执行类似,自动程序修复技术的可靠性和稳定性主要依赖于工具对程序代码语义的理解。人工智能大模型在自动程序修复上的成功也一定程度启发了符号执行相关的自动化测试工作。

针对深度模型或人工智能如何测试,如何提高人工智能测试的有效性问题,研究人员可以探索一种新的方法,即建立一种以人工智能为主导的测试框架,让人工智能测试人工智能。针对模型解释性问题,该框架应可以对其内部结构进行分析和解释。通过观察模型的输入、中间层和输出,了解模型是如何进行预测的,从而更好地理解其行为。针对特征选择问题,该框架应可以通过分析不同的输入和中间层特征来确定哪些特征对于预测最重要。这有助于优化测试集,提高测试覆盖率。对抗样本是指对模型输入作出微小但有意义的修改,以使模型产生误差。针对对抗样本检测问题,该框架应可以检测和识别对抗样本,从而增强模型的鲁棒性和健壮性。而对于问题定位难这个痛点,如果模型在某些测试用例上表现不佳,该框架应可以帮助定位问题所在。通过分析模型的输入和中间层状态,确定模型在哪些情况下会出现错误,并采取相应措施进行修复。

5 结束语

在智能终端软件开发过程中,软件测试是必不可少的环节。测试结果的准确度直接决定软件研发品质。本文全面概述了以安卓为代表的智能终端自动化测试技术和工具。黑盒与白盒是两种不同的软件测试技术,相互补充且缺一不可。测试过程中需要进行白盒测试验证逻辑结构是否正确,软件安全是否达标,也需要黑盒测试检验功能是否正确,系统是否稳定。目前,智能终端软件测试已经能够实现较为精准的质量控制。然而,随着智能终端软件和信息技术的不断进步,无论是黑盒测试还是白盒测试,都需要不断研究和创新来推动智能终端行业的发展。随着智能终端自动化测试技术的不断完善,未来将有越来越多的测试场景可以被自动化,并且自动化成本也将降低,自动化测试的精确性也将逐步提高,最终达到高可靠、强稳定的智能终端测试最佳实践。

猜你喜欢

污点测试用例安卓
iPhone不卡的秘密曝光:安卓也能享受
基于代码重写的动态污点分析
基于SmartUnit的安全通信系统单元测试用例自动生成
文物表情包
基于混合遗传算法的回归测试用例集最小化研究
使用Lightroom污点去除工具清理照片中的瑕疵
一种基于安卓系统的手机侧抓包分析方法
我国“污点证人”刑事责任豁免制度的构建
基于依赖结构的测试用例优先级技术
安卓L未至安卓M来了!安卓首泄漏M系统