界面更新崩溃风险检测方法、装置、电子设备及存储介质
文献发布时间:2023-06-19 11:11:32
技术领域
本申请涉及软件测试技术领域,特别涉及一种界面更新崩溃风险检测方法、界面更新崩溃风险检测装置、电子设备及计算机可读存储介质。
背景技术
界面更新奔溃也可以称为UI(User Interface,用户界面)更新crash(即崩溃),是一种由子线程对UI进行更新导致的软件错误。更新UI的线程是否为主线程往往会随着程序的运行而改变,不确定性高,为了防止出现UI更新crash,通常在程序测试过程进行界面更新崩溃风险测试。相关技术通常采用monkey等测试工具生成并发送伪随机的用户事件流,进行动态测试,以便发现UI更新crash。然而,相关技术无法完全覆盖各种检测场景,检测效果较差;且需要的检测时间较长,检测效率较低。
发明内容
有鉴于此,本申请的目的在于提供一种界面更新崩溃风险检测方法、界面更新崩溃风险检测装置、电子设备及计算机可读存储介质,通过构建函数链并检测函数链的起始函数是否为非主线程函数,可以准确且全面地检测待测项目代码是否存在UI更新crash风险,检测能力和效率较高。
为解决上述技术问题,第一方面,本申请提供了一种界面更新崩溃风险检测方法,包括:
获取待测项目代码,并对所述待测项目代码进行界面更新函数检测,得到目标界面更新函数;
生成所述待测项目代码对应的函数调用关系信息;
将各个所述目标界面更新函数作为第一端函数,利用所述函数调用关系信息构建多个函数链,并识别各个所述函数链对应的第二端函数;
若任一所述第二端函数为非主线程函数,则确定所述非主线程函数所属的目标函数链具有界面更新崩溃风险。
在一种可行的实施方式中,所述将各个所述目标界面更新函数作为第一端函数,利用所述函数调用关系信息构建多个函数链,并识别各个所述函数链对应的第二端函数,包括:
利用所述函数调用关系信息确定各个所述目标界面更新函数对应的直接调用函数;
将所述直接调用函数确定为被调函数,并利用所述函数调用关系信息判断是否存在所述被调函数对应的上级函数;
若存在所述上级函数,则将所述上级函数确定为所述被调函数;
若不存在所述上级函数,则确定所述函数链构建完毕,并将所述被调函数确定为所述第二端函数。
在一种可行的实施方式中,所述若不存在所述上级函数,则确定所述函数链构建完毕,包括:
若不存在所述上级函数,则利用所述函数调用关系信息判断所述被调函数是否存在对应的目标父类函数或目标接口函数;
若存在所述目标父类函数或所述目标接口函数,则将所述目标父类函数或所述目标接口函数确定为所述被调函数;
若不存在所述目标父类函数或所述目标接口函数,则确定所述函数链构建完毕。
在一种可行的实施方式中,在对所述待测项目代码进行界面更新函数检测之前,还包括:
利用界面更新基础函数筛选各个函数,并将调用了所述界面更新基础函数的所述函数确定为界面更新函数;
利用所述界面更新函数对应的函数名生成界面更新函数检测数据;
相应的,所述对所述待测项目代码进行界面更新函数检测,得到目标界面更新函数,包括:
利用所述界面更新函数检测数据对所述待测项目代码中的各个待测函数进行函数名匹配;
将通过函数名匹配的待测函数确定为所述目标界面更新函数。
在一种可行的实施方式中,所述生成所述待测项目代码对应的函数调用关系信息,包括:
获取检测插件和对应的检测插件信息;
将所述检测插件信息添加到所述待测项目代码中并编译,在编译过程中调用所述检测插件,得到所述函数调用关系信息。
在一种可行的实施方式中,还包括:
利用所述目标函数链生成检测结果;
获取所述待测项目代码对应的执行人信息,并利用所述执行人信息反馈所述检测结果。
在一种可行的实施方式中,还包括:
获取无调用函数信息,并将所述待测项目代码中所述无调用函数信息对应的函数标记为无调用函数;
相应的,所述若任一所述第二端函数为非主线程函数,则确定所述非主线程函数所属的目标函数链具有界面更新崩溃风险,包括:
若任一所述第二端函数为非主线程函数,则判断所述非主线程函数是否为所述无调用函数;
若任一所述非主线程函数不为所述无调用函数,则确定所述目标函数链具有所述界面更新崩溃风险。
第二方面,本申请还提供了一种界面更新崩溃风险检测装置,包括:
更新函数检测模块,用于获取待测项目代码,并对所述待测项目代码进行界面更新函数检测,得到目标界面更新函数;
函数调用关系信息生成模块,用于生成所述待测项目代码对应的函数调用关系信息;
函数链构建模块,用于将各个所述目标界面更新函数作为第一端函数,利用所述函数调用关系信息构建多个函数链,并识别各个所述函数链对应的第二端函数;
风险检出模块,用于若任一所述第二端函数为非主线程函数,则确定所述非主线程函数所属的目标函数链具有界面更新崩溃风险。
第三方面,本申请还提供了一种电子设备,包括存储器和处理器,其中:
所述存储器,用于保存计算机程序;
所述处理器,用于执行所述计算机程序,以实现上述的界面更新崩溃风险检测方法。
第四方面,本申请还提供了一种计算机可读存储介质,用于保存计算机程序,其中,所述计算机程序被处理器执行时实现上述的界面更新崩溃风险检测方法。
本申请提供的界面更新崩溃风险检测方法,获取待测项目代码,并对待测项目代码进行界面更新函数检测,得到目标界面更新函数;基于目标界面更新函数,生成待测项目代码对应的函数调用关系信息;将各个目标界面更新函数作为第一端函数,利用函数调用关系信息构建多个函数链,并识别各个函数链对应的第二端函数;若任一第二端函数为非主线程函数,则确定非主线程函数所属的目标函数链具有界面更新崩溃风险。
可见,该方法在对待测项目代码进行测试时,先识别其中的目标界面更新函数,目标界面更新函数为待测项目代码中会引起UI更新的函数。在得到目标界面更新函数后,基于其生成函数调用关系信息。函数调用关系信息记录了待测项目代码中所有函数之间存在的调用关系,因此其可以用于筛选得到待测项目代码中与目标界面更新函数相关的各个函数之间的调用关系。将目标界面更新函数作为第一端函数,则函数链另一端对应的函数即为第二端函数。若第二端函数为非主线程函数,则说明第二端函数并不是仅能由主线程调用的函数,其可能由子线程调用,而子线程调用该第二端函数则会导致子线程对UI进行更新,因此存在UI更新crash风险,即确定其所属的目标函数链具有界面更新崩溃风险。该方法采用静态测试的方式,可以准确且全面地识别待测项目代码存在的UI更新crash,可以覆盖全部检测场景,检测效果较好。且不需要进行随机检测,因此检测时长较短,检测效率较高,解决了相关技术存在的测试效果较差、测试效率较低的问题。
此外,本申请还提供了一种界面更新崩溃风险检测装置、电子设备及计算机可读存储介质,同样具有上述有益效果。
附图说明
为了更清楚地说明本申请实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本申请的实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据提供的附图获得其他的附图。
图1为本申请实施例提供的一种界面更新崩溃风险检测方法所适用的硬件组成框架示意图;
图2为本申请实施例提供的另一种界面更新崩溃风险检测方法所适用的硬件组成框架示意图;
图3为本申请实施例提供的一种界面更新崩溃风险检测方法的一种流程示意图;
图4为本申请实施例提供的一种界面更新基础函数调用关系图;
图5为本申请实施例提供的一种界面更新崩溃风险检测装置的一种结构示意图。
具体实施方式
为使本申请实施例的目的、技术方案和优点更加清楚,下面将结合本申请实施例中的附图,对本申请实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本申请一部分实施例,而不是全部的实施例。基于本申请中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本申请保护的范围。
界面更新崩溃,即UI更新crash,是一种由子线程更新UI界面导致的软件错误,由于软件项目代码较复杂,且随着软件的运行,更新UI的线程是否为主线程会随之改变,因此是否会出现UI更新crash的不确定性较高。为了对该类crash进行检测,相关技术通常采用如monkey测试工具等包含线程干扰的自动测试工具,在软件运行时生成随机事件流,进而进行随机性测试,并在测试过程中捕获出现的UI更新crash。然而,随机测试的耗时较长,效率较低。且无法覆盖所有可以更新UI的操作,即无法覆盖全部的检测场景,同时,采用线程干扰的方式无法保证更新UI的线程必然是子线程,无法保证检测可靠性,因此检测效果较差。为了解决上述问题,本申请生成待测项目代码对应的函数调用关系信息,并利用其构建函数链,通过判断函数链中的第二端函数是否为非主线程函数,即可判断该函数链是否可能被子线程调用,而子线程调用该函数链则会导致UI更新,进而出现UI更新crash。因此当第二端函数为非主线程函数时,则说明可能出现UI更新crash,因此确定检测到了界面更新崩溃风险。该方法将问题发现的阶段由软件运行阶段提前至软件编译阶段,同时通过对待测项目代码的全部函数链进行构建,实现了对UI更新crash风险的全面检测,提高了检测准确率,使得检测效果较好。同时不需要进行随机检测,因此检测时长较短,检测效率较高。
为了便于理解,先对本申请实施例提供的界面更新崩溃风险检测方法对应的方案所使用的硬件组成框架进行介绍。请参考图1,图1为本申请实施例提供的一种界面更新崩溃风险检测方法所适用的硬件组成框架示意图。其中电子设备100可以包括处理器101和存储器102,还可以进一步包括多媒体组件103、信息输入/信息输出(I/O)接口104以及通信组件105中的一种或多种。
其中,处理器101用于控制电子设备100的整体操作,以完成界面更新崩溃风险检测方法中的全部或部分步骤;存储器102用于存储各种类型的数据以支持在电子设备100的操作,这些数据例如可以包括用于在该电子设备100上操作的任何应用程序或方法的指令,以及应用程序相关的数据。该存储器102可以由任何类型的易失性或非易失性存储设备或者它们的组合实现,例如静态随机存取存储器(Static Random Access Memory,SRAM)、电可擦除可编程只读存储器(Electrically Erasable Programmable Read-Only Memory,EEPROM)、可擦除可编程只读存储器(Erasable Programmable Read-Only Memory,EPROM)、可编程只读存储器(Programmable Read-Only Memory,PROM)、只读存储器(Read-OnlyMemory,ROM)、磁存储器、快闪存储器、磁盘或光盘中的一种或多种。在本实施例中,存储器102中至少存储有用于实现以下功能的程序和/或数据:
获取待测项目代码,并对待测项目代码进行界面更新函数检测,得到目标界面更新函数;
基于目标界面更新函数,生成待测项目代码对应的函数调用关系信息;
将各个目标界面更新函数作为第一端函数,利用函数调用关系信息构建多个函数链,并识别各个函数链对应的第二端函数;
若任一第二端函数为非主线程函数,则确定非主线程函数所属的目标函数链具有界面更新崩溃风险。
多媒体组件103可以包括屏幕和音频组件。其中屏幕例如可以是触摸屏,音频组件用于输出和/或输入音频信号。例如,音频组件可以包括一个麦克风,麦克风用于接收外部音频信号。所接收的音频信号可以被进一步存储在存储器102或通过通信组件105发送。音频组件还包括至少一个扬声器,用于输出音频信号。I/O接口104为处理器101和其他接口模块之间提供接口,上述其他接口模块可以是键盘,鼠标,按钮等。这些按钮可以是虚拟按钮或者实体按钮。通信组件105用于电子设备100与其他设备之间进行有线或无线通信。无线通信,例如Wi-Fi,蓝牙,近场通信(Near Field Communication,简称NFC),2G、3G或4G,或它们中的一种或几种的组合,因此相应的该通信组件105可以包括:Wi-Fi部件,蓝牙部件,NFC部件。
电子设备100可以被一个或多个应用专用集成电路(Application SpecificIntegrated Circuit,简称ASIC)、数字信号处理器(Digital Signal Processor,简称DSP)、数字信号处理设备(Digital Signal Processing Device,简称DSPD)、可编程逻辑器件(Programmable Logic Device,简称PLD)、现场可编程门阵列(Field ProgrammableGate Array,简称FPGA)、控制器、微控制器、微处理器或其他电子元件实现,用于执行界面更新崩溃风险检测方法。
当然,图1所示的电子设备100的结构并不构成对本申请实施例中电子设备的限定,在实际应用中电子设备100可以包括比图1所示的更多或更少的部件,或者组合某些部件。
可以理解的是,本申请实施例中并不对电子设备的数量进行限定,其可以是多个电子设备共同协作完成界面更新崩溃风险检测方法。在一种可能的实施方式中,请参考图2,图2为本申请实施例提供的另一种界面更新崩溃风险检测方法所适用的硬件组成框架示意图。由图2可知,该硬件组成框架可以包括:第一电子设备11和第二电子设备12,二者之间通过网络13连接。
在本申请实施例中,第一电子设备11与第二电子设备12的硬件结构可以参考图1中电子设备100。即可以理解为本实施例中具有两个电子设备100,两者进行数据交互。进一步,本申请实施例中并不对网络13的形式进行限定,即,网络13可以是无线网络(如WIFI、蓝牙等),也可以是有线网络。
其中,第一电子设备11和第二电子设备12可以是同一种电子设备,如第一电子设备11和第二电子设备12均为服务器;也可以是不同类型的电子设备,例如,第一电子设备11可以是计算机,第二电子设备12可以是服务器。在一种可能的实施方式中,可以利用计算能力强的服务器作为第二电子设备12来提高数据处理效率及可靠性,进而提高界面更新崩溃风险检测的处理效率。同时利用成本低,应用范围广的计算机作为第一电子设备11,用于实现第二电子设备12与用户之间的交互。可以理解的是,该交互过程可以为:计算机获取待测项目代码,并对其进行界面更新函数检测,得到目标界面更新函数。计算机将待测项目代码和目标界面更新函数发送至服务器,由服务器执行后续步骤,直至完成对待测查项目代码的界面更新崩溃风险检测。
基于上述说明,请参考图3,图3为本申请实施例提供的一种界面更新崩溃风险检测方法的一种流程示意图。该实施例中的方法包括:
S101:获取待测项目代码,并对待测项目代码进行界面更新函数检测,得到目标界面更新函数。
待测项目代码为需要进行UI更新crash风险检测的代码,其具体内容不做限定。本实施例并不限定待测项目代码的具体获取方式,例如在一种实施方式中,可以在指定路径下获取待测项目代码,指定路径可以预先设置,或者可以由用户输入,或者可以由其他电子设备发送。在另一种实施方式中,可以监测与某些电子设备之间的通信接口,并将通信接口传输的数据确定为待测项目代码。本实施例并不限定待测项目代码的具体类型、应用场景、具体数量等,例如可以一次获取多个应用于智能手机的安卓APP对应的待测项目代码。在获取到待测项目代码后,对其中的界面更新函数进行检测,得到对应的检测结果,即目标界面更新函数,因此目标界面更新函数即为待测代码中的界面更新函数。需要说明的是,本实施例中的界面更新函数为会引起界面发生更新的函数,其可以包括直接对界面进行更新的函数,或者可以包括直接调用函数,直接调用函数为直接调用了会对界面进行更新的函数的函数。
本实施例并不限定对待测项目代码进行界面更新函数检测的具体检测方式,例如在一种可行的实施方式中,可以利用界面更新函数的函数内容对待测项目代码进行匹配,并在匹配成功时确定检测到目标界面更新函数。在另一种实施方式中,由于代码中通常采用调用函数的方式对函数进行使用,不会重写其内容,因此可以利用其函数名对待测项目代码进行匹配,并在匹配成功时确定检测到目标界面更新函数。
S102:基于目标界面更新函数,生成待测项目代码对应的函数调用关系信息。
在检测到目标界面更新函数后,可以确定待测项目代码在执行过程中会进行UI更新,为了判断UI更新的函数是否由主线程调用,即UI更新的操作是否由主线程执行,还需要确定函数之间的调用关系,进而构建函数链。目标界面更新函数可能经过多层调用,即调用目标界面更新函数的函数也有其他函数调用,例如当A函数为目标界面更新函数时,A函数被B函数调用,且B函数被C函数和D函数调用。因此函数链可能由多个单链路组成,每个单线路用于表示一个函数与调用该函数的上级函数或下级函数之间的调用关系。因此生成的函数调用关系信息可以为单链路函数关系,即函数调用关系信息中每个信息项都记录了某一个函数和对应的上级函数之间的关系,或者记录了某一个函数和被该函数调用的下级函数之间的关系。函数调用关系信息记录了待测项目代码中所有函数之间存在的调用关系,其中必然记录了直接调用了目标界面更新函数的上级函数,因此可以用于生成与目标界面更新函数对应的函数链。本实施例并不限定函数调用关系信息的具体形式,例如其可以包括多个子信息,每个子信息记录有多个信息项,不同子信息记录的信息项不同。例如在一种实施方式中,其可以包括method和viewmethod两个子信息,其中viewmethod中的信息项记录了各个目标界面更新函数与直接调用目标界面更新函数的直接调用函数之间的关系,method记录了待测项目代码中所有函数之间存在的对应关系。
本实施例并不限定生成函数调用关系信息的具体方式,例如在一种可行的实施方式中,可以采用AST(Abstract Syntax Tree,抽象语法树)方案获取函数调用关系信息;在另一种实施方式中,可以采用AOP(Aspect Oriented Programming,面向切面编程)方案获取函数调用关系信息;在另一种实施方式中,可以采用静态逆向反汇编方案获取函数调用关系信息;在另一种实施方式中,可以采用ASM(一种Java字节码操控框架,可用于动态生成类或增强既有类的功能)方案获取函数调用关系信息。根据采用方式的不同,具体的函数调用关系信息的获取过程也不同,具体可以参考相关技术,本实施例在此不做赘述。
S103:将各个目标界面更新函数作为第一端函数,利用函数调用关系信息构建多个函数链,并识别各个函数链对应的第二端函数。
在得到函数调用关系信息后,将各个目标界面更新函数作为第一端函数,即作为函数链的第一个端点,根据函数调用关系信息确定待测项目代码中各个函数之间的调用关系,并根据该调用关系构建函数链。在函数链构建完毕后,将其另外一个端点上的函数确定为第二端函数,该第二端函数即为调用目标界面更新函数的最根本函数,也是引起UI发生更新的最根本函数。
本实施例并不限定函数链的具体构建方式,例如可以确定目标界面更新函数对应的直接调用函数,并利用函数调用关系判断该直接调用函数是否被调用,若被调用,则确定直接调用函数对应的上级函数,并进一步判断该上级函数是否被调用,直至检测到没有被调用的函数,则该函数即为第二端函数。
S104:若任一第二端函数为非主线程函数,则确定非主线程函数所属的目标函数链具有界面更新崩溃风险。
需要说明的是,主线程函数为只能被主线程进行调用的函数,因此非主线程函数即为可以由非主线程(即子线程)进行调用的函数,其具体数量和内容不做限定。在函数链构建完毕后,每个函数链均具有一个对应的第二端函数,若存在任意一个第二端函数为非主线程函数,则说明该函数可以被子线程调用,而调用该函数必然会导致UI更新,若该第二端函数被子线程调用,则会导致UI更新crash。因此当任意一个第二端函数为非主线程函数,则说明存在UI更新crash的风险,确定其所属的目标函数链具有界面更新崩溃风险,即UI更新crash风险。
应用本申请实施例提供的界面更新崩溃风险检测方法,在对待测项目代码进行测试时,先识别其中的目标界面更新函数,目标界面更新函数为待测项目代码中会引起UI更新的函数。在得到目标界面更新函数后,基于其生成函数调用关系信息。函数调用关系信息记录了待测项目代码中所有函数之间存在的调用关系,因此其可以用于筛选得到待测项目代码中与目标界面更新函数相关的各个函数之间的调用关系。将目标界面更新函数作为第一端函数,则函数链另一端对应的函数即为第二端函数。若第二端函数为非主线程函数,则说明第二端函数并不是仅能由主线程调用的函数,其可能由子线程调用,而子线程调用该第二端函数则会导致子线程对UI进行更新,因此存在UI更新crash风险,即确定其所属的目标函数链具有界面更新崩溃风险。该方法采用静态测试的方式,可以准确且全面地识别待测项目代码存在的UI更新crash,可以覆盖全部检测场景,检测效果较好。且不需要进行随机检测,因此检测时长较短,检测效率较高,解决了相关技术存在的测试效果较差、测试效率较低的问题。
基于上述实施例,本实施例对上述实施例中的部分步骤进行具体说明。在一种具体的实施方式中,在检测待测项目代码中的目标界面更新函数之前,需要确定哪些函数为界面更新函数。因此在对所述待测项目代码进行界面更新函数检测之前,还可以包括如下步骤:
步骤11:利用界面更新基础函数筛选各个函数,并将调用了界面更新基础函数的函数确定为界面更新函数。
界面更新基础函数为进行页面更新的函数,即直接对界面进行更新的函数,为最低层次函数。根据待测项目代码对应的代码类型的不同,界面更新基础函数的内容可以不同,每个代码类型对应的页面更新基础函数的数量可以为一个或多个。在其他实施方式中,页面更新基础函数可以直接作为界面更新函数。而在本实施例中,由于待测项目代码通常会以某一固定层级的函数作为基础函数构建得到,而这些基础函数通常不是最低层级的函数,而是通过调用比其层级更低的函数构成,其中必然包括最低层级的函数。因此无法直接将界面更新基础函数最为界面更新函数,因为待测项目代码中并不存在界面更新基础函数。在这种情况下,需要利用界面更新基础函数筛选各个基础函数,具体为筛选各个基础函数的函数内容,并将具有界面更新函数的基础函数确定为界面更新函数。
以Java编程语言为例,请参考图4,图4为本申请实施例提供的一种界面更新基础函数调用关系图。在更新UI时,必须必调用底层ViewRootImpl.java中的checkThread函数,而checkThread被ViewRootImpl.java中的requestLayout函数和incalidateChildInParent函数调用,而ViewRootImpl.java中的requestLayout函数被View.java中的requestLayout函数调用,incalidateChildInParent函数被View.java中的invalidate函数调用。在实际使用中,用户通常会使用View类(包括View.java、ImageView.java、TextView.java、ViewGroup.java等)函数作为基础函数构建项目代码,因此,在确定界面更新函数时,需在View类中扫描出使用了requestLayout和invalidate的函数作为界面更新函数。例如setText函数、setVisibility函数等。
步骤12:利用界面更新函数对应的函数名生成界面更新函数检测数据。
由于界面更新函数在使用时会被直接调用,调用的方式为输入其函数名,因此可以利用各个界面更新函数的函数名生成界面更新函数检测数据,以便在后续利用其进行目标界面更新函数的检测。相应的,对待测项目代码进行界面更新函数检测,得到目标界面更新函数的步骤可以包括:
步骤13:利用界面更新函数检测数据对待测项目代码中的各个待测函数进行函数名匹配。
步骤14:将通过函数名匹配的待测函数确定为目标界面更新函数。
在进行界面更新函数检测时,可以以界面更新函数检测数据作为匹配标准,对待测项目代码中的各个待测函数进行函数名匹配,待测函数可以为待测项目代码中任意一个函数。若待测函数的函数名与待测项目代码中的某个函数名匹配,则说明通过函数名匹配,且通过匹配的待测函数即为目标界面更新函数。
基于上述实施例,在一种具体的实施方式中,为了提高通用性,实现在需要时,灵活选择计算设备并快速使其具有界面更新崩溃风险检测能力的效果,可以采用检测插件的方式获取函数调用关系信息。具体的,生成待测项目代码对应的函数调用关系信息的过程具体可以包括如下步骤:
步骤21:获取检测插件和对应的检测插件信息;
可以理解的是,根据函数调用关系信息采用的获取方案的不同,检测插件的具体类别也可以不同。例如当采用ASM方案获取函数调用关系信息时,检测插件可以为ASM插桩插件。检测插件信息用于与待测项目代码沟通生成检测脚本,其具体内容不做限定,例如可以为运行方式等。检测插件可以预先生成,其具体生成方式可以参考相关技术,在此不再赘述。需要说明的是,根据电子设备的具体类型的不同,检测插件也可以不同。
步骤22:将检测插件信息添加到待测项目代码中并编译,在编译过程中调用检测插件,得到函数调用关系信息
将检测插件信息与待测项目代码相结合后编译,具体的,可以将检测插件信息配置到待测项目代码的build.gradle文件中,然后编译待测项目代码。在编译时,可以基于上述配置调用检测插件,,并利用检测插件,按照其内部逻辑生成函数调用关系信息。通过设置检测插件编译的方式,可以在需要时在任意与检测插件相匹配的电子设备(例如安卓设备)上进行函数调用关系信息的生成,进而完成UI更新crash风险检测,提高了通用性。
基于上述实施例,在一种实施方式中,由于目标界面更新函数可能经过多次调用,而不同的目标界面更新函数的调用次数可能不同,因此为了准确地构建函数链,进而准确地识别第二端函数,将各个目标界面更新函数作为第一端函数,利用函数调用关系信息构建多个函数链,并识别各个函数链对应的第二端函数的过程可以包括如下步骤:
步骤31:利用函数调用关系信息确定各个目标界面更新函数对应的直接调用函数。
在本实施例中,为了快速构建函数链,函数调用关系信息中可以包括直接调用信息,直接调用信息记录了各个目标界面更新函数和直接调用了目标界面更新函数的直接调用函数。通过直接调用信息,可以直接得到直接调用函数,不需要根据目标界面更新函数筛选待测项目代码对应的所有函数之间存在的调用关系,因此可以提高函数链的构建速度。直接调用信息可以被称为ViewMethod信息,其形式可以为txt形式,具体的,其内容格式可以为:
A类名--函数A--A参数--A父类--A接口列表{B类名-被调用的目标界面更新函数B--B参数};
在一种实施方式中,一个A函数可能会调用多个目标界面更新函数,在这种情况下,可以将A函数调用的第一个目标界面更新函数确定为B函数。因此在生成直接调用信息时,在检测到目标界面更新函数以及对应的直接调用函数时,可以判断该目标界面更新函数是否为直接调用函数调用的第一个界面更新函数,若是,则将其对应关系写入直接调用信息,若不是则不执行任何操作。
步骤32:将直接调用函数确定为被调函数,并利用函数调用关系信息判断是否存在被调函数对应的上级函数。
在本实施例中,函数调用关系信息中可以包括函数关系信息,函数关系信息即为记录待测项目代码对应的所有函数之间存在的调用关系的信息。由于可能存在多层调用的情况,因此在确定直接调用函数后还可以利用函数关系信息判断被调函数是否被其他函数调用,即判断是否存在与被调函数对应的上级函数。函数关系信息可以被称为Method信息,其形式可以为txt形式,具体的,其内容格式可以为:
A类名--函数A--A参数--A父类--A接口列表{B类名--被调函数B--B参数,C类名--被调函数C--C参数,...};
可以理解的是,该格式即为A函数调用了B函数、C函数以及其他函数。
步骤33:若存在上级函数,则将上级函数确定为被调函数。
若存在上级函数,则说明当前的被调函数仍被其他函数调用,因此可以将该上级函数确定为新的被调函数,以便再次执行利用函数调用关系信息判断是否存在被调函数对应的上级函数的步骤,判断是否仍然存在上级函数。
步骤34:若不存在上级函数,则确定函数链构建完毕,并将被调函数确定为第二端函数。
若被调函数不存在上级函数,说明该被调函数没有被任何函数调用,其为该函数链的发起端。在这种情况下,可以确定函数链构建完毕,并将被调函数确定为第二端函数。
进一步的,在一种具体的实施方式中,待测项目代码中可能存在重写函数。重写函数为对父类函数或接口函数进行函数重写处理后得到的函数。函数重写其实就是函数覆盖,当在派生类中声明了一个与基类函数完全相同的成员函数时,就实现了对基类函数的覆盖,在调用基类函数时实际上调用的是经过重写的派生类函数,即重写函数。而重写函数时可能会修改函数类名,因此若被调函数为重写函数时,其函数类名与其对应的父类函数或接口函数的函数类名可能不同,因此可能错认为其没有上级函数,造成函数链断裂,使得生成的函数链为错误的函数链。为了解决这个问题,若不存在上级函数,则确定函数链构建完毕的过程可以包括如下步骤:
步骤41:若不存在上级函数,则利用函数调用关系信息判断被调函数是否存在对应的目标父类函数或目标接口函数。
在本实施例中,函数调用关系信息中还可以存在重写函数信息,重写函数信息用于记录各个重写函数与其对应的父类函数或接口函数之间的对应关系。若某一被调函数不存在上级函数,则说明其可能为重写函数,在这种情况下,可以利用其筛选重写函数信息,进而判断是否存在与其对应的目标父类函数或目标接口函数。重写函数信息可以被称为Super_Inter_Method信息,其形式可以为txt形式,具体的,其内容格式可以为:
A类名--父类或接口函数A--A参数--A父类--A接口列表{B类名-重写函数B--B参数,C类名-重写函数C--C参数,...};
需要说明的是,被调函数和目标父类函数或目标接口函数之间,仅有函数类名不同,其他内容均相同。以上述内容格式为例,其中A类名与B类名不同,A参数与B参数相同,父类或接口函数A(即A函数的函数名)与重写函数B(即B函数的函数名)相同。因此在判断是否存在目标父类函数或目标接口函数时,可以依据是否存在与被调函数类名不同而函数名和函数参数相同的函数。
步骤42:若存在目标父类函数或目标接口函数,则将目标父类函数或目标接口函数确定为被调函数。
若存在,则可以确定当前的被调函数为重写函数,因此为了避免函数链断裂,可以将目标父类函数或目标接口函数确定为新的被调函数,以便利用新的被调函数重新执行利用函数调用关系信息判断是否存在被调函数对应的上级函数的步骤,继续构建函数链,以便得到准确的函数链。
步骤43:若不存在目标父类函数或目标接口函数,则确定函数链构建完毕。
若不存在目标父类函数或目标接口函数,则说明被调函数为第二端口函数,确定函数链构建完毕。具体的,函数链的格式可以为:
{
A类名--函数A--A参数(第一端)
B类名--函数B--B参数
C类名--函数C--C参数
...
X类名--函数X--X参数(第二端)
}
因此该函数链表示A函数被B函数调用,B函数被C函数调用,依次类推,最终得到的第二端函数为X函数。
基于上述实施例,在一种实施方式中,待测项目代码中可能存在未被调用的函数,例如待测项目代码经过多次修改后,修改前调用而修改后未调用的函数。这些函数虽然存在,但是其本身没有被待测项目代码调用,即并不会执行,因此即便其最终调用了目的界面更新函数,待测项目代码运行时也不会引起UI更新,故而不存在UI更新crash风险。因此为了提高风险检测的准确性,本实施例还可以包括:
步骤51:获取无调用函数信息,并将待测项目代码中无调用函数信息对应的函数标记为无调用函数。
在本实施例中,无调用函数信息可以由函数名、函数参数和函数类名三者组成,或者可以为函数编号等。在获取无调用函数信息后,可以将其对应的函数标记为无调用函数,即这些函数虽然在待测项目代码中存在,但是并未真实调用,即并未被执行。
相应的,若任一第二端函数为非主线程函数,则确定非主线程函数所属的目标函数链具有界面更新崩溃风险的过程可以包括如下步骤:
步骤52:若任一第二端函数为非主线程函数,则判断非主线程函数是否为无调用函数。
当检测到存在非主线程函数后,可以进一步判断其是否为无调用函数,防止对UI更新crash风险进行错误检测。本实施例并不限定具体的判断方式,例如可以利用非主线程函数的函数名、函数参数和函数类名与无调用函数的函数名、函数参数和函数类名分别进行匹配,若函数名、函数类名和函数参数三者均相同,则确定匹配成功,匹配成功则确定其为无调用函数;或者可以利用非主线程函数的函数内容与无调用函数的函数内容进行匹配,若匹配成功则确定其为无调用函数。
步骤53:若任一非主线程函数不为无调用函数,则确定目标函数链具有界面更新崩溃风险。
若非主线程函数不为无调用函数,则说明该非主线程函数确实被调用,即确实被执行,且其为非主线程函数,说明其有可能被子线程调用,因此确定其所属的目标函数链具有UI更新crash风险,即界面更新崩溃风险。通过判断非主线程函数是否为无调用函数,可以避免进行风险误报,提高检测准确性。
进一步的,为了使得用户准确得知UI更新crash风险的具体位置,以便用户对风险进行高效地修复。具体的,还可以包括如下步骤:
步骤61:利用目标函数链生成检测结果。
通过利用目标函数链生成检测结果,可以在检测结果中准确说明引起界面更新崩溃风险的具体函数和函数链,以便用户针对其进行风险修复。
步骤62:获取待测项目代码对应的执行人信息,并利用执行人信息反馈检测结果。
由于每个待测项目代码的检测需要一定的时长,因此可以预设与待测项目代码对应的执行人信息,执行人信息可以表示待测项目代码对应的用户,通过利用执行人信息反馈检测结果,可以使用户在检测完毕后第一时间得知检测结果。
下面对本申请实施例提供的界面更新崩溃风险检测装置进行介绍,下文描述的界面更新崩溃风险检测装置与上文描述的界面更新崩溃风险检测方法可相互对应参照。
请参考图5,图5为本申请实施例提供的一种界面更新崩溃风险检测装置的一种结构示意图,包括:
更新函数检测模块110,用于获取待测项目代码,并对待测项目代码进行界面更新函数检测,得到目标界面更新函数;
函数调用关系信息生成模块120,用于生成待测项目代码对应的函数调用关系信息;
函数链构建模块130,用于将各个目标界面更新函数作为第一端函数,利用函数调用关系信息构建多个函数链,并识别各个函数链对应的第二端函数;
风险检出模块140,用于若任一第二端函数为非主线程函数,则确定非主线程函数所属的目标函数链具有界面更新崩溃风险。
应用本申请实施例提供的界面更新崩溃风险检测装置,在对待测项目代码进行测试时,先识别其中的目标界面更新函数,目标界面更新函数为待测项目代码中会引起UI更新的函数。在得到目标界面更新函数后,基于其生成函数调用关系信息。函数调用关系信息记录了待测项目代码中所有函数之间存在的调用关系,因此其可以用于筛选得到待测项目代码中与目标界面更新函数相关的各个函数之间的调用关系。将目标界面更新函数作为第一端函数,则函数链另一端对应的函数即为第二端函数。若第二端函数为非主线程函数,则说明第二端函数并不是仅能由主线程调用的函数,其可能由子线程调用,而子线程调用该第二端函数则会导致子线程对UI进行更新,因此存在UI更新crash风险,即确定其所属的目标函数链具有界面更新崩溃风险。该装置采用静态测试的方式,可以准确且全面地识别待测项目代码存在的UI更新crash,可以覆盖全部检测场景,检测效果较好。且不需要进行随机检测,因此检测时长较短,检测效率较高,解决了相关技术存在的测试效果较差、测试效率较低的问题。
可选地,函数链构建模块130,包括:
直接调用函数确定单元,用于利用函数调用关系信息确定各个目标界面更新函数对应的直接调用函数;
上级函数判断单元,用于将直接调用函数确定为被调函数,并利用函数调用关系信息判断是否存在被调函数对应的上级函数;
被调函数确定单元,用于若存在上级函数,则将上级函数确定为被调函数;
第二端函数确定单元,用于若不存在上级函数,则确定函数链构建完毕,并将被调函数确定为第二端函数。
可选地,第二端函数确定单元,包括:
重写判断子单元,用于若不存在上级函数,则利用函数调用关系信息判断被调函数是否存在对应的目标父类函数或目标接口函数;
被调函数确定子单元,用于若存在目标父类函数或目标接口函数,则将目标父类函数或目标接口函数确定为被调函数;
构建完毕确定子单元,用于若不存在目标父类函数或目标接口函数,则确定函数链构建完毕。
可选地,还包括:
界面更新函数确定模块,用于利用界面更新基础函数筛选各个函数,并将调用了界面更新基础函数的函数确定为界面更新函数;
检测数据生成模块,用于利用界面更新函数对应的函数名生成界面更新函数检测数据;
相应的,更新函数检测模块,包括:
函数名匹配单元,用于利用界面更新函数检测数据对待测项目代码中的各个待测函数进行函数名匹配;
目标界面更新函数确定单元,用于将通过函数名匹配的待测函数确定为目标界面更新函数。
可选地,函数调用关系信息生成模块,包括:
插件获取单元,用于获取检测插件和对应的检测插件信息;
检测脚本生成单元,用于将检测插件信息添加到待测项目代码中并编译,在编译过程中调用检测插件,得到函数调用关系信息。
可选地,还包括:
检测结果生成模块,用于利用目标函数链生成检测结果;
结果反馈模块,用于获取待测项目代码对应的执行人信息,并利用执行人信息反馈检测结果。
可选地,还包括:
无调用函数标记模块,用于获取无调用函数信息,并将待测项目代码中无调用函数信息对应的函数标记为无调用函数;
相应的,风险检出模块,包括:
无调用函数判断单元,用于若任一第二端函数为非主线程函数,则判断非主线程函数是否为无调用函数;
风险确定单元,用于若任一非主线程函数不为无调用函数,则确定目标函数链具有界面更新崩溃风险。
下面对本申请实施例提供的计算机可读存储介质进行介绍,下文描述的计算机可读存储介质与上文描述的界面更新崩溃风险检测方法可相互对应参照。
本申请还提供一种计算机可读存储介质,计算机可读存储介质上存储有计算机程序,计算机程序被处理器执行时实现上述的界面更新崩溃风险检测方法的步骤。
该计算机可读存储介质可以包括:U盘、移动硬盘、只读存储器(Read-OnlyMemory,ROM)、随机存取存储器(Random Access Memory,RAM)、磁碟或者光盘等各种可以存储程序代码的介质。
本说明书中各个实施例采用递进的方式描述,每个实施例重点说明的都是与其它实施例的不同之处,各个实施例之间相同或相似部分互相参见即可。对于实施例公开的装置而言,由于其与实施例公开的方法相对应,所以描述的比较简单,相关之处参见方法部分说明即可。
本领域技术人员还可以进一步意识到,结合本文中所公开的实施例描述的各示例的单元及算法步骤,能够以电子硬件、计算机软件或者二者的结合来实现,为了清楚地说明硬件和软件的可互换性,在上述说明中已经按照功能一般性地描述了各示例的组成及步骤。这些功能究竟以硬件还是软件的方式来执行,取决于技术方案的特定应用和设计约束条件。本领域技术人员可以对每个特定的应用来使用不同方法来实现所描述的功能,但是这种实现不应该认为超出本申请的范围。
结合本文中所公开的实施例描述的方法或算法的步骤可以直接用硬件、处理器执行的软件模块,或者二者的结合来实施。软件模块可以置于随机存储器(RAM)、内存、只读存储器(ROM)、电可编程ROM、电可擦除可编程ROM、寄存器、硬盘、可移动磁盘、CD-ROM、或技术领域内所公知的任意其它形式的存储介质中。
最后,还需要说明的是,在本文中,诸如第一和第二等之类的关系属于仅仅用来将一个实体或者操作与另一个实体或者操作区分开来,而不一定要求或者暗示这些实体或操作之间存在任何这种实际的关系或者顺序。而且,术语包括、包含或者其他任何变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、物品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、物品或者设备所固有的要素。
本文中应用了具体个例对本申请的原理及实施方式进行了阐述,以上实施例的说明只是用于帮助理解本申请的方法及其核心思想;同时,对于本领域的一般技术人员,依据本申请的思想,在具体实施方式及应用范围上均会有改变之处,综上所述,本说明书内容不应理解为对本申请的限制。
- 界面更新崩溃风险检测方法、装置、电子设备及存储介质
- 应用界面更新方法、装置、电子设备及可读存储介质