CN103473171B - 一种基于函数调用路径的覆盖率动态跟踪方法及装置 - Google Patents
一种基于函数调用路径的覆盖率动态跟踪方法及装置 Download PDFInfo
- Publication number
- CN103473171B CN103473171B CN201310379892.6A CN201310379892A CN103473171B CN 103473171 B CN103473171 B CN 103473171B CN 201310379892 A CN201310379892 A CN 201310379892A CN 103473171 B CN103473171 B CN 103473171B
- Authority
- CN
- China
- Prior art keywords
- function
- path
- stake point
- calls
- dynamic
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Expired - Fee Related
Links
Landscapes
- Debugging And Monitoring (AREA)
- Data Exchanges In Wide-Area Networks (AREA)
Abstract
本发明涉及一种基于函数调用路径的覆盖率动态跟踪方法及装置,实现方案为:对被测源代码进行插桩预处理,得到函数对象列表和控制关键字对象列表;得到源代码的函数调用基本路径集;执行测试用例,并运行插桩后的源代码,获得由源代码的执行路径的桩点数据流组成的动态路径;对动态路径进行拆分,得到测试用例所覆盖的函数调用路径子集;将函数调用路径子集与函数调用基本路径集进行匹配;将所有函数调用路径子集作为一个动态路径集,优化该动态路径集;计算优化后的动态路径集占函数调用基本路径集的比率,得到覆盖率。本发明将路径覆盖粒度由语句扩展到函数级别,避免了传统路径覆盖路径集庞大而无法完全测试每条路径的问题。
Description
技术领域
本发明涉及软件测试的覆盖分析技术领域,特别是涉及一种基于函数调用路径的覆盖率动态跟踪方法及装置。
背景技术
以下是本领域中的一些名词解释,其使用范围仅限于本发明:
函数调用关系:函数调用关系是以函数为基本单位,通过分析源程序里函数之间的逻辑关系得来的。
函数调用基本路径集:是源代码按照函数调用关系进行分析得到的全部函数调用路径的集合,也就是函数调用关系图G中的所包含的所有函数调用路径,表示为B(S,C)={P1,P2,…,Pn},其中S是源代码,C是函数调用关系准则,Pi是函数调用路径。
插桩:是指在静态测试阶段,借助向被测程序中插入操作来实现测试目的的方法,其基本原理是被测程序在保持原有逻辑完整性基础上在程序中插入一些探针,这些探针的本质是进行信息采集的代码段,可以是赋值语句或采集覆盖信息的函数调用。插桩技术的应用是为了记录软件运行时代码的执行路径,从而了解代码的执行情况,利用插桩信息分析软件代码的覆盖率。
执行路径:源代码的执行路径是指输入参数后编译运行源代码所得到的函数之间的执行顺序。
动态路径:动态路径是指输入测试数据、编译运行经过预处理的源代码所获得的路径,其中包含了函数之间的执行顺序和控制关键字。动态路径是由一系列的桩点数据流组成的,包含函数的起始桩点、结束桩点和控制逻辑关键字的真假桩点值。
覆盖率:覆盖率是用来度量测试完整性的一个手段,通过覆盖率数据,可以知道测试工作是否充分,测试的弱点在哪些方面,进而指导设计能够增加覆盖率的测试用例,有效地提高测试质量。覆盖率中最常见的是代码覆盖率,而路径覆盖是代码覆盖方法里一种非常严格的覆盖准则。
在实际代码测试中,一个较为复杂的程序包含的路径数目是相当庞大的,要完全达到路径覆盖是不可行的,实现自动化路径覆盖也是困难的。传统路径覆盖方法涉及的路径集庞大,且其针对每条路径至少测试一次的测试方法只停留在理论阶段,存在很大缺陷,无法完全测试出每条路径的问题。
为解决上述问题,文档《基于函数调用的路径覆盖生成技术研究》(张志华,牟永敏.基于函数调用的路径覆盖生成技术研究[J].电子学报,2010,38(8):1808-1811)提出了基于函数调用路径思想,文中给出了静态、动态分析函数调用路径覆盖率的大体思路,但是并未对具体实现做详细的说明。本发明继承了函数调用路径思想,提出了一种适用于白盒回归测试的动态跟踪、分析测试用例覆盖率的方法及装置。
发明内容
本发明所要解决的技术问题是提供一种基于函数调用路径的覆盖率动态跟踪方法及装置,用于解决传统路径覆盖方法的路径集庞大且无法完全测试每条路径的问题。
本发明解决上述技术问题的技术方案如下:一种基于函数调用路径的覆盖率动态跟踪方法,包括:
步骤1,对被测源代码进行插桩预处理,得到函数对象列表和控制关键字对象列表;
步骤2,获取源代码的函数调用基本路径集;
步骤3,执行测试用例,并运行经步骤1插桩后的源代码,获得由源代码的执行路径的桩点数据流组成的动态路径;
步骤4,根据函数对象列表和控制关键字对象列表提供的信息,对步骤3获得的动态路径进行拆分,得到测试用例所覆盖的函数调用路径子集;
步骤5,将函数调用路径子集与函数调用基本路径集进行匹配,确保函数调用路径子集是属于函数调用基本路径集的子集;
步骤6,将所有函数调用路径子集作为一个动态路径集,优化该动态路径集;
步骤7,计算优化后的动态路径集占函数调用基本路径集的比率,得到覆盖率。
本发明的有益效果是:本发明提出了基于函数调用的路径覆盖生成技术,将路径覆盖粒度由语句扩展到函数级别,避免路径的爆炸式增长,在保证充分单元测试的前提下,避免了传统路径覆盖路径集庞大而无法完全测试每条路径的问题,有利于提高自动化测试的可行性。同时,本发明对动态路径集进行了优化,再得出测试用例基于函数调用路径的覆盖率,基于覆盖率分析出未被覆盖的函数调用路径集,有利于指导测试人员针对未被覆盖的函数调用路径设计测试用例。
在上述技术方案的基础上,本发明还可以做如下改进。
进一步,所述步骤1具体包括:
步骤11,选择插桩点;
步骤12,设计桩函数,并将桩函数插入到选择的插桩点中;
步骤13,存放插入桩函数后生成的插桩信息,包括函数对象列表信息和控制关键字对象列表信息。
采用上述进一步方案的有益效果是:根据函数调用路径的特点在完成插桩点的选择、桩函数的设计以及插桩信息存放后,完成了对源代码的插桩预处理,其只是在源代码内添加了桩函数,而桩函数并不会影响源代码原有的功能,插桩后的源代码仍然能够正常编译运行。上述方法易于实现,便于获得源代码在运行时的动态路径的相关信息。
进一步,所述步骤11具体包括:基于块结构划分源代码,以源代码所包括的每个函数作为一个块结构,再针对每个块结构,将函数起始点、控制逻辑关键字所在点和函数结束点作为插桩点。
采用上述进一步方案的有益效果是:通过函数的起始点和结束点可以唯一的标识一个函数及标识函数的当前状态。选择控制关键字作为插桩点表明了标识出函数之间的执行顺序是基于何种函数调用关系的。这样既能保证桩点的紧凑精干,又能保证收集的信息全面无冗余。
进一步,所述步骤4中对动态路径进行拆分具体包括:
步骤41,分别读入动态路径、函数对象列表及控制逻辑关键字对象列表;
步骤42,将动态路径包含的每个桩点值存放到ArrayList数组里,将函数对象列表和控制逻辑关键字对象列表的信息分别存放到哈希表中;
步骤43,将动态路径里的桩点值分别与函数对象列表和控制关键字对象列表进行比较,根据桩点值类型的不同对动态路径进行不同的拆分处理。
采用上述进一步方案的有益效果是:动态路径是无法直接与函数调用基本路径集进行匹配,因此需对动态路径进行拆分,上述拆分方法结合了函数调用路径和动态路径的特点,易于实现,且保证了拆分的准确性。
进一步,所述步骤5中将函数调用路径子集与函数调用基本路径集进行匹配具体包括:
步骤51,将函数调用基本路径集里的函数调用路径存放到ArrayList数组中;
步骤52,遍历ArrayList数组,将函数调用基本路径集里的函数调用路径构建成树形结构;
步骤53,在函数调用基本路径集的树形结构中查找是否存在函数调用路径子集的函数调用路径,当且仅当一个函数调用路径子集中的所有函数调用路径都存在于树形结构中时,该函数调用路径子集能成功匹配函数调用基本路径集,否则匹配不成功,需重新对动态路径进行拆分。
采用上述进一步方案的有益效果是:验证了拆分算法的正确性,保证了拆分后的函数调用路径子集是否是函数调用基本路径集的子集,且相比于低效的数组元素匹配方式,树形结构能提供更为高效的路径查找方式。
进一步,所述步骤6中优化动态路径集包括两个方面:一是基于动态路径集本身进行的优化,二是基于动态路径集中的各函数调用路径子集间的包含关系进行的优化;
所述基于动态路径集本身进行的优化具体包括:在将动态路径添加到动态路径集之前,判断动态路径集中是否已存在该条动态路径,若存在,则说明该条动态路径是重复的动态路径,将其舍弃,同时将对应的测试数据也一并舍弃;若不存在,则将该条动态路径添加到动态路径集中。
所述基于动态路径集中的各函数调用路径子集间的包含关系进行的优化具体包括:计算出函数调用基本路径集中的函数调用路径被动态路径覆盖的条数,记为Ti,以及每条动态路径覆盖函数调用路径的条数,记为Ri;挑选出所有必不可少的动态路径,然后从函数调用基本路径集中删除被动态路径所覆盖的函数调用路径,重新计算Ti,Ri的值,迭代执行;当没有必不可少的动态路径时,挑选覆盖函数调用路径最多的动态路径,然后从函数调用基本路径集中删除该条动态路径所覆盖的函数调用路径,重新计算Ti,Ri的值,并再次查看是否有必不可少的动态路径,迭代执行。
采用上述进一步方案的有益效果是:首先去除动态路径集中相同的路径然后使用启发算法对函数调用子集的包含关系进行优化,删除了重复和冗余的动态路径,易于实现,优化率高.优化后的动态路径集与函数调用基本路径集进行匹配,能同时获得已覆盖的函数调用路径和未覆盖的函数调用路径,便于对下一步测试进行指导。
本发明的技术方案还包括一种基于函数调用路径的覆盖率动态跟踪装置,其功能及有益效果均与上述覆盖率动态跟踪方法相对应。所述覆盖率动态跟踪装置包括:
插桩预处理模块,其用于对被测源代码进行插桩预处理,得到函数对象列表和控制关键字对象列表;
基本路径集获取模块,其用于获取源代码的函数调用基本路径集;
动态路径获取模块,其连接所述插桩预处理模块,用于执行测试用例,并运行经所述插桩预处理模块插桩后的源代码,获得由源代码的执行路径桩点数据流组成的动态路径;
动态路径拆分模块,其连接所述插桩预处理模块及所述动态路径获取模块,用于根据函数对象列表和控制关键字对象列表提供的信息,对获得的动态路径进行拆分,得到测试用例所覆盖的函数调用路径子集;
路径匹配模块,其连接所述基本路径集获取模块及所述动态路径拆分模块,用于将函数调用路径子集与函数调用基本路径集进行匹配,确保函数调用路径子集是属于函数调用基本路径集的子集;
路径集优化模块,其连接所述路径匹配模块,用于将经所述匹配模块处理过的所有函数调用路径子集作为一个动态路径集,并优化该动态路径集;
覆盖率计算模块,其连接所述路径集优化模块用于计算优化后的动态路径集占函数调用基本路径集的比率,得到覆盖率。
进一步,所述插桩预处理模块包括:
插桩点选择模块,其用于以源代码所包括的每个函数作为一个块结构,再针对每个块结构,将函数起始点、控制逻辑关键字所在点和函数结束点作为插桩点;
桩函数设计模块,其连接所述插桩点选择模块,用于设计桩函数,并将桩函数插入到选择的插桩点中;
插桩信息存放模块,其连接所述桩函数设计模块,用于存放插入桩函数后生成的插桩信息,包括函数对象列表信息和控制关键字对象列表信息。
进一步,所述动态路径拆分模块包括:
信息读入模块,其用于分别读入动态路径和函数对象列表及控制逻辑关键字对象列表;
信息存放模块,其连接所述信息读入模块,用于将动态路径包含的每个桩点值存放到ArrayList数组里,将函数对象列表和控制逻辑关键字对象列表的信息分别存放到哈希表中;
拆分执行模块,其连接所述信息存放模块,用于将动态路径里的桩点值分别与函数对象列表和控制关键字对象列表进行比较,根据桩点值类型的不同对动态路径进行不同的拆分处理。
进一步,所述路径匹配模块包括:
路径存放模块,其用于将函数调用基本路径集里的函数调用路径存放到ArrayList数组中;
树形结构建立模块,其连接所述路径存放模块,用于遍历ArrayList数组,将函数调用基本路径集里的函数调用路径构建成树形结构;
查找模块,其连接所述树形结构建立模块,用于在函数调用基本路径集的树形结构中查找是否存在函数调用路径子集的函数调用路径,当且仅当一个函数调用路径子集中的所有函数调用路径都存在于树形结构中时,该函数调用路径子集能成功匹配函数调用基本路径集,否则匹配不成功,并重新对动态路径进行拆分。
附图说明
图1为本发明所述基于函数调用路径的覆盖率动态跟踪方法的流程示意图;
图2为本发明实施例中进行动态拆分的原理图;
图3为本发明实施例中树形结构表示的函数调用路径示意图;
图4为本发明应用例中函数调用关系的示意图;
图5为本发明所述基于函数调用路径的覆盖率动态跟踪装置的结构示意图;
图6为本发明所述插桩预处理模块的结构示意图;
图7为本发明所述动态路径拆分模块的结构示意图;
图8为本发明所述路径匹配模块的结构示意图。
附图中,各标号所代表的部件列表如下:
1、插桩预处理模块,2、基本路径集获取模块,3、动态路径获取模块,4、动态路径拆分模块,5、路径匹配模块,6、路径集优化模块,7、覆盖率计算模块,11、插桩点选择模块,12、桩函数设计模块,13、插桩信息存放模块,41、信息读入模块,42、信息存放模块,43、拆分执行模块,51、路径存放模块,52、树形结构建立模块,53、查找模块。
具体实施方式
以下结合附图对本发明的原理和特征进行描述,所举实例只用于解释本发明,并非用于限定本发明的范围。
如图1所示,本实施例给出了一种基于函数调用路径的覆盖率动态跟踪方法,包括:
步骤1,对被测源代码进行插桩预处理,得到函数对象列表和控制关键字对象列表;
步骤2,获取源代码的函数调用基本路径集;
步骤3,执行测试用例,并运行经步骤1插桩后的源代码,获得由源代码的执行路径的桩点数据流组成的动态路径;
步骤4,根据函数对象列表和控制关键字对象列表提供的信息,对步骤3获得的动态路径进行拆分,得到测试用例所覆盖的函数调用路径子集;
步骤5,将函数调用路径子集与函数调用基本路径集进行匹配,确保函数调用路径子集是属于函数调用基本路径集的子集;
步骤6,将所有函数调用路径子集作为一个动态路径集,优化该动态路径集;
步骤7,计算优化后的动态路径集占函数调用基本路径集的比率,得到覆盖率。
步骤2中,函数调用基本路径集的获取是通过静态分析获得的函数调用路径得到,属于本领域公知技术,本发明中不再多述。
基于上述步骤,具体的实施过程包括以下几个部分。
一、插桩预处理。
插桩预处理实现具体包括:
步骤11,选择插桩点:基于块结构划分源代码,以源代码所包括的每个函数作为一个块结构,再针对每个块结构,将函数起始点、控制逻辑关键字所在点和函数结束点作为插桩点;
步骤12,设计桩函数,并将桩函数插入到选择的插桩点中;
步骤13,存放插入桩函数后生成的插桩信息,包括函数对象列表信息和控制关键字对象列表信息。
其中,选择函数的起始点和结束点作为插桩点是出于以下两个原因:1)通过该两点可以唯一的标识一个函数;2)通过该两点可以标识函数的当前状态。例如,在动态路径里记录了一个函数的入口点,但是紧跟着的不是该函数的出口点,而是另外一个函数的入口点,说明该函数调用了其他的函数,该函数本身还没有结束。选择控制关键字作为插桩点是为了标识出函数之间的执行顺序是基于何种函数调用关系的。例如,在动态路径里记录了函数f1的入口点,然后是if关键字的真桩点,紧跟着的是函数f2的入口点,说明函数f2包含在函数f1里,且f2的执行是通过选择分支条件为真的情况发生调用的。
设计的桩函数要满足两个要求:第一,保证桩函数能够记录动态路径所需的信息;第二,对桩函数作最大程度的简化,使插桩后的源代码具有尽可能低的膨胀率。因此所需的桩函数不需很复杂,仅仅能起到唯一标识且能够保证所有位置都能插入即可。基于上述考虑,本实施例给出一组桩函数实现方案:在需要插入桩点的位置插入8位16进制的标记,这些16进制的标记不能有重复的情况发生,8位16进制的个数足以保证插桩点个数的需求;为避免重复,可设计四类桩函数:函数的入口点插入CProbeS(tag)函数;函数的出口点插入CProbeE(tag);控制关键字为真时插入CProbeT(tag)函数,且以标记(CProbeT(tag),1)表示;控制关键字为假时插入CProbeF(tag)函数,且以标记(CProbeF(tag),0)表示。其中tag为8位16进制的数,每个桩函数的tag起始大小不一样,且固定。然后逐个加1,但是最大数不能超过其它函数的起始数,这样就可以避免重复情况发生。这些桩函数将在程序执行过程中向动态路径的桩点数据流文件中写入tag值。例如CProbeS(0x7540001)表示将函数入口点桩点值0x7540001写入动态路径的桩点数据流文件。
记录的插桩信息包括函数对象列表和控制关键字对象列表。函数对象列表的文件存储数据格式有五个字段,分别为:起始桩点、函数名、起始行、终止行、结束桩点。起始桩点字段里包含的内容为函数的入口桩点数据值;函数名字段里包含的内容为函数原型,有函数的返回类型、函数名、函数参数列表;起始行字段里包含的内容为函数的起始行行号;终止行字段里包含的内容为函数的结束行行号;结束桩点字段里包含的内容为函数的出口桩点数据值;函数起始桩点和结束桩点与函数名是一一对应关系。
控制逻辑关键字对象列表的文件存储数据格式有四个字段,分别为:假桩点、关键字、函数名、真桩点。假桩点字段里包含的内容为控制关键字为假的桩点数据值;关键字字段里包含的内容为控制关键字;函数名字段里包含的内容为控制关键字所在的函数原型里:有函数的返回类型、函数名、函数参数列表;真桩点字段里包含的内容为控制关键字为真的桩点数据值。
其中,对于控制关键字对象列表里的信息,只关注关键字的类型,允许出现多个同样的关键字。如在一个函数里可以出现多个if关键字,但是对每个if关键字都有唯一对应的判定真桩点和判定假桩点,其中判定真桩点和判定假桩点是一一对应的。
二、动态路径的拆分。
动态路径拆分主要包括以下步骤:
步骤41,分别读入动态路径、函数对象列表及控制逻辑关键字对象列表;
步骤42,将动态路径包含的每个桩点值存放到ArrayList数组里,将函数对象列表和控制逻辑关键字对象列表的信息分别存放到哈希表中;
步骤43,将动态路径里的桩点值分别与函数对象列表和控制关键字对象列表进行比较,根据桩点值类型的不同对动态路径进行不同的拆分处理。
动态路径拆分的主要原理是将动态路径结合函数对象列表和控制关键字对象列表进行分析,主要针对循环和递归进行拆分,获到函数调用路径集。原理图如图2所示。本实施例的拆分算法的实现需要使用以下数据结构:
1)ArrayList
ArrayList数组的优点是可以事先不定义数组的大小,其容量可根据需要动态地扩充。利用ArrayList的这一特性,可以用来存储动态路径的桩点值,也可以用来存放动态路径拆分后得到的函数调用路径子集。
2)HashTable
哈希表表示键(key)/值(value)对的集合,这些键/值对根据键的哈希代码进行组织。哈希表像一个字典,其中每个元素都是一个存储在字典实体对象中的键/值对,根据键可以查到相应的值。插桩后得到的函数对象列表里的起始桩点、函数名、结束桩点是一一对应的关系,且桩点值是唯一标识的。并且控制关键字对象列表里的判定真桩点、关键字名、判定假桩点也是一一对应关系,且桩点值是唯一标识的。所以利用哈希表的这个特性可以用来存储函数对象列表的信息和控制关键字对象列表的信息。创建两个哈希表,一个用来存放函数对象列表信息;一个用来存放控制关键字对象列表信息。用来存放函数对象列表信息的哈希表的键设为起始桩点,值为函数名和结束桩点;用来存放控制逻辑关键字对象列表信息的哈希表的键设为判定真桩点,值为关键字名和判定假桩点。
3)Stack
栈的特性是先进后出,可以用来记录函数的当前状态和关键字的当前状态。例如,一个函数中调用了其他的函数,虽然该函数是先于其他函数被执行的,但是仍需等到其他的函数执行完成后才能结束。也就是说该函数的结束桩点最后退栈。
可知,拆分算法是动态路径拆分的核心,在设计拆分算法的过程中,结合动态路径和函数调用路径的特点,拆分算法所要处理的代码结构可分为以下四种类型,所述步骤43中根据桩点值类型的不同对动态路径进行不同的拆分处理即是基于这种类型实现的:
1)函数桩点
遇到函数真桩点时,将其与函数假桩点栈中的栈顶元素进行比较,如果不相等,则将该桩点进行函数真桩点栈的入栈操作,并记录该函数真桩点所对应的函数名,同时将其对应的假桩点也进行函数假桩点栈的入栈操作;遇到函数假桩点,则对函数真桩点栈和函数假桩点栈进行出栈操作。
2)递归情况
遇到函数真桩点时,将其与函数假桩点栈中的栈顶元素进行比较,如果相等,则说明该函数发生了递归。对于函数递归的情况,应记录每次递归时的路径,并与递归数组里已有的路径进行比较。其中,递归数组是用来存放每次递归时的路径,初始时为空。如果发现该路径不存在于递归数组中,则将该路径添加到递归路径数组里,否则舍弃该条路径。
3)循环情况
遇到循环关键字判定真桩点,将其与循环真桩点栈的栈顶元素进行比较,如果相等,则说明是当前循环。记录每次循环时的路径,并与循环数组里已有的路径进行比较。其中,循环数组是用来存放每次循环时的路径,初始时为空。如果发现有不同的路径,则将该条路径添加到循环路径数组里,否则舍弃该条路径;如果发现该桩点与栈顶元素不相等,则说明进入下一个循环,递归调用循环模块函数。
4)选择情况
遇到选择关键字的时候,在一次实际执行时,只能执行一条分支。要么是真分支语句、要么是假分支语句。因此无需对该结构块进行拆分处理,直接处理下一个结构块即可。
三、动态路径的匹配
通过拆分算法将动态路径拆分成函数调用路径集后,还需和函数调用基本路径集进行匹配,以验证拆分结果是否正确。如果拆分后得到的函数调用路径集与函数调用基本路径集出现不匹配的情况,则说明当前采用的动态路径拆分算法不能较好的对动态路径进行拆分,需要根据匹配的结构分析拆分算法的缺陷,并做相应的修改。如果匹配成功,说明拆分后得到的函数调用路径集中的函数调用路径都包含于函数调用基本路径集,则该函数调用路径集为函数调用基本路径集的一个子集。关于将函数调用路径子集与函数调用基本路径集进行匹配,其涉及所述步骤5的技术方案,具体包括:
步骤51,将函数调用基本路径集里的函数调用路径存放到ArrayList数组中;
步骤52,遍历ArrayList数组,将函数调用基本路径集里的函数调用路径构建成树形结构;
步骤53,在函数调用基本路径集的树形结构中查找是否存在函数调用路径子集的函数调用路径,当且仅当一个函数调用路径子集中的所有函数调用路径都存在于树形结构中时,该函数调用路径子集能成功匹配函数调用基本路径集,否则匹配不成功,需重新对动态路径进行拆分。
本实施例中,针对上述步骤的匹配算法需要使用以下数据结构:
1)树
树形结构是一种重要的非线性数据结构,是以分支关系定义的层次结构。函数调用基本路径集中的函数调用路径之间是因为分支关系而造成彼此之间的不同的。根据函数调用基本路径集的特性,将集合中的函数调用路径构造成树的结构。每个结点代表一个函数,树中的每一条分支代表一条函数调用路径,如图3所示。从而,将动态路径的匹配过程转化成了在树中进行查找的过程。对树进行查找,效率将非常的高,它的时间复杂度为O(n*k*h),其中n为函数调用路径子集的个数,k为树中结点的最大度,h为树的深度。而对函数调用路径子集中的每条路径与函数调用基本路径集中的每个路径进行比较的算法复杂度为O(mn),其中m为函数调用基本路径集中的个数,n为函数调用路径子集的个数。可见,将函数调用基本路径集转化为树的结构,能够提高动态路径的匹配效率。
2)HashTable
数组在使用前,需先规定其大小。但是针对函数调用基本路径集,事先不知道每个结点会有多少个子节点。因此,数组并不能够满足以树形结构表示的函数调用基本路径集的存储需求。哈希表是一种集合结构,其容量可根据需要自动扩充。哈希表的键为函数名,值为类对象。
本实施例中,构造存储树结构的类为:
另外,根据上述内容,针对函数调用基本路径集的树形结构,进行匹配时主要涉及两个方面的技术:
(1)函数调用基本路径集的树形结构建立
进行函数调用基本路径的树形结构构建时,针对每个函数调用路径进行构建。构建时应注意,要随时跟踪当前节点的上一个节点,因为可能在一条分支上有相同的函数名。树形结构的建立过程与Trie树的建立过程相似,其本质上就是对树中元素的查找过程。每次从函数调用基本路径集中选取一条路径,从树的根节点开始搜索,在根节点的所有子节点中查找函数调用路径中的第一个被调用函数,若查找成功,则转入相应的子树,继续查找函数调用路径的下一个被调用函数;若查找失败,则将被调用函数的信息作为当前节点的子节点,添加到树中,并转入该子树继续查找。迭代上述过程,直至对函数调用路径的最后一个被调用函数成功查找或插入树中。对函数调用基本路径中的每一条路径循环上述操作,即可实现其树形结构的建立。
(2)函数调用路径集在树形结构中的查找
验证函数调用路径集中的函数调用路径是否包含于函数调用基本路径集中,实际上是在函数调用基本路径集的树形结构中进行查找函数调用路径的过程。若查找成功,则说明该条函数调用路径包含于函数调用基本路径集中;若查找失败,则说明该条函数调用路径不存在于函数调用基本路径集中。当且仅当一个函数调用路径子集中的所有路径都存在于函数调用基本路径集时,该函数调用路径子集能够成功匹配函数调用基本路径集,从而说明动态路径拆分算法是正确的。否则,该函数调用路径子集不能够与函数调用基本路径集成功匹配,说明动态路径拆分算法是不正确的,需对拆分算法进行修改。
四、动态路径集的优化
所述步骤6中优化动态路径集包括两个方面:一是基于动态路径集本身进行的优化,二是基于动态路径集中的各函数调用路径子集间的包含关系进行的优化;
所述基于动态路径集本身进行的优化具体包括:在将动态路径添加到动态路径集之前,判断动态路径集中是否已存在该条动态路径,若存在,则说明该条动态路径是重复的动态路径,将其舍弃,同时将对应的测试数据也一并舍弃;若不存在,则将该条动态路径添加到动态路径集中。
所述基于动态路径集中的各函数调用路径子集间的包含关系进行的优化具体包括:计算出函数调用基本路径集中的函数调用路径被动态路径覆盖的条数,记为Ti,以及每条动态路径覆盖函数调用路径的条数,记为Ri;挑选出所有必不可少的动态路径,然后从函数调用基本路径集中删除被动态路径所覆盖的函数调用路径,重新计算Ti,Ri的值,迭代执行;当没有必不可少的动态路径时,挑选覆盖函数调用路径最多的动态路径,然后从函数调用基本路径集中删除该条动态路径所覆盖的函数调用路径,重新计算Ti,Ri的值,并再次查看是否有必不可少的动态路径,迭代执行。
对动态路径集优化算法的实现需要使用以下数据结构:
1)ArrayList
ArrayList数组用来存放动态路径集中的所有动态路径、优化后的动态路径集。
2)HashTable
使用HashTable来存放每个测试需求被满足的所有测试用例Ti。键用来存放函数调用基本路径集中的函数调用路径,值用来存放所有满足该条测试需求的测试用例。每条测试用例所满足的测试需求Ri也用HashTable表示。键用来存放动态路径集中的每条动态路径,值用来存放每条测试用例所满足的测试需求集。
五、覆盖率计算
一般的覆盖率计算公式为:
本实施例中测试需求为函数调用基本路径B(S,C),测试用例覆盖的测试需求为动态路径集L(S,D)通过优化算法后得到的函数调用路径子集U,则
另外,当源代码中的函数发生修改时,会产生一些变更路径,即是包含了被修改函数的函数调用路径。在回归测试中需要对这些变更路径进行重点测试。假设测试人员A设计了的一组测试用例,通过上述覆盖率公式进行覆盖率计算,得到的覆盖率结果很高,但是这些测试用例没有覆盖变更路径。同时,测试人员B也设计了一组测试用例,也通过同样方法进行覆盖率计算,得到的覆盖率结果和测试人员A得到的覆盖率结果一样,但是测试人员B设计的测试用例覆盖了函数调用基本路径集中的所有变更路径。虽然两组测试用例所得到的函数调用路径的覆盖率相等,但是测试人员B所设计的测试用例较好的覆盖了变更路径,因此较之测试人员A所设计的测试用例有更高的质量。所以,针对有变更路径的函数调用基本路径集,仅仅通过上述覆盖率公式获得的函数调用路径的覆盖率并不能够较好的体现测试用例的质量。因此,在上述函数调用路径覆盖率计算公式的基础上,考虑了变更路径对测试
结果的影响,提出了针对变更路径的覆盖率计算公式。
测试用例覆盖的变更路径是从函数调用路径子集U中挑选出的,测试需求中的变更路径是从函数调用基本路径集中挑选出的。在获知所有被修改函数的基础上,遍历函数调用基本路径集的树形结构,当树中的结点和被修改的函数名相同时,则记录该条变更路径,迭代此操作,获得测试需求中的所有变更路径。同时构造函数调用路径子集U的树形结构,做同样的操作,获得测试用例覆盖的所有变更路径。在回归测试时,通过对变更路径的覆盖率分析,指导测试人员优先设计测试用例测试未被覆盖的变更路径,然后再设计测试用例覆盖剩下的未覆盖的函数调用路径。
针对上述五个部分的描述,下面以一个具体的应用例进行说明,首先给出一段原代码:
针对上述源代码,当输入参数i=1时,可以获得该源代码的执行路径:
E=(main→f1→f4→f2→f3→f3→f4)
按第一部分中设计的桩函数对其中的函数f1进过插桩后的实际效果,如下所示:
按第一部分中设计的桩函数对上述源代码进行插桩得到的函数对象列表和控制逻辑关键字对象列表如表1、表2所示:
表1:函数对象列表
起始桩点 | 函数名 | 起始行 | 终止行 | 结束桩点 |
00000001 | int f1(int i) | 5 | 12 | 000ffffd |
00000002 | int f2(int i) | 13 | 18 | 000ffffc |
00000003 | int f3(int i) | 19 | 24 | 000ffffb |
00000004 | int f4(int i) | 25 | 30 | 000ffffa |
00000005 | int f5(int i) | 31 | 36 | 000ffff9 |
00000006 | int main() | 37 | 66 | 000fffee |
表2:控制逻辑关键字对象列表
假桩点 | 关键字 | 函数名 | 真桩点 |
000ffffe | if | int f1(int i) | 000fffff |
000ffffc | case | int main() | |
000ffffd | case | int main() | |
000fffff | while | int main() | 000ffff0 |
000ffff1 | if | int main() | 000ffff2 |
000ffff3 | if | int main() | 000ffff4 |
000ffff5 | for | int main() | 000ffff6 |
000ffff7 | if | int main() | 000ffff8 |
}
按照函数调用路径的特点,该段代码函数调用路径基本集包含17条函数调用路径:
B(S,C)={main→f1→f4→f4→,main→f1→f1→f4→f4→,main→f1→f4→f5→,main→f1→f1→f4→f5→,main→f1→f4→,main→f1→f1→f4→,main→f2→f4→f4→,main→f2→f4→f5→,main→f2→f4→,main→f3→f4→f4→,main→f3→f4→f4→,main→f2→f4→f5→,main→f3→f4→,main→f4→f4→,main→f4→f5→,main→f4→,main→f5→,main→}。通过这些路径可获得如图4所示的函数调用关系。
为获取动态路径逐个输入测试数据库中的测试数据,测试数据库中有测试数据{i=1;i=2;i=4;i=5;i=10;i=16;i=6;i=18},得到的动态路径如以下(1)至(8)所示:
(1)
00000006->000ffff0->000ffff2->00000001->000fffff->000ffffd
->00000004->000ffffa->000ffff0->000ffff1->000ffff4->000ffff6
->000ffff8->00000002->000ffffc->000ffff6->000ffff7->00000003
->000ffffb->000ffff6->000ffff7->00000003->000ffffb->000ffff5
->00000004->000ffffa->000fffef->000fffee->
(2)
00000006->000ffff0->000ffff2->00000001->000ffffe->00000001
->000fffff->000ffffd->000ffffd->00000004->000ffffa->000ffff0
->000ffff1->000ffff4->000ffff6->000ffff8->00000002->000ffffc
->000ffff6->000ffff7->00000003->000ffffb->000ffff6->000ffff7
->00000003->000ffffb->000ffff5->00000004->000ffffa->000fffef
->000fffee->
(3)
00000006->000ffff0->000ffff1->000ffff4->000ffff6->000ffff8
->00000002->000ffffc->000ffff6->000ffff7->00000003->000ffffb
->000ffff6->000ffff7->00000003->000ffffb->000ffff5->00000004
->000ffffa->000fffef->000fffee->
(4)
00000006->000ffff0->000ffff1->000ffff4->000ffff6->000ffff8
->00000002->000ffffc->000ffff6->000ffff7->00000003->000ffffb
->000ffff6->000ffff7->00000003->000ffffb->000ffff5->00000004
->000ffffa->000fffef->000fffee->
(5)
00000006->000ffff0->000ffff1->000ffff3->00000004->000ffffa
->000ffff0->000ffff1->000ffff3->00000004->000ffffa->000fffef
->000fffec->00000004->000ffffa->000fffee->
(6)
00000006->000fffef->000fffee->00000004->000ffffa->000fffee->
(7)
00000006->000ffff0->000ffff1->000ffff4->000ffff6->000ffff8
->00000002->000ffffc->000ffff6->000ffff7->00000003->000ffffb
->000ffff6->000ffff7->00000003->000ffffb->000ffff5->00000004
->000ffffa->000fffef->000fffee->
(8)
00000006->000fffef->000fffed->00000005->000ffff9->000fffee->
根据本实施例中覆盖率的计算方法,该应用例中源代码经过测试数据库中的测试数据测试后,假设函数f5发生了修改,则其已覆盖的变量路径有1条(main->f5->),未覆盖的变更路径有5条:
1:main->f1->f4->f5->
2:main->f1->f1->f4->f5->
3:main->f2->f4->f5->
4:main->f3->f4->f5->
5:main->f4->f5->
与上述覆盖率动态跟踪方法相对应,本实施例还给出了一种基于函数调用路径的覆盖率动态跟踪装置,其具体的实施过程参考上述一至五中涉及的实施方式及相关应用例。如图5所示,该覆盖率动态跟踪装置包括插桩预处理模块1、基本路径集获取模块2、动态路径获取模块3、动态路径拆分模块4、路径匹配模块5、路径集优化模块6和覆盖率计算模块7,且所述动态路径获取模块3连接所述插桩预处理模块1,所述动态路径拆分模块4连接所述插桩预处理模块1及所述动态路径获取模块3,所述路径匹配模块5连接所述基本路径集获取模块2及所述动态路径拆分模块4,所述路径集优化模块6连接所述路径匹配模块5,所述覆盖率计算模块7连接所述路径集优化模块6。
所述插桩预处理模块1,其用于被测源代码进行插桩预处理,得到函数对象列表和控制关键字对象列表;
所述基本路径集获取模块2,其用于获取源代码的函数调用基本路径集;
所述动态路径获取模块3,其连接所述插桩预处理模块1,用于执行测试用例,并运行经所述插桩预处理模块插桩后的源代码,获得由源代码的执行路径桩点数据流组成的动态路径;
所述动态路径拆分模块4,其连接所述插桩预处理模块1及所述动态路径获取模块3,用于根据函数对象列表和控制关键字对象列表提供的信息,对获得的动态路径进行拆分,得到测试用例所覆盖的函数调用路径子集;
所述路径匹配模块5,其连接所述基本路径集获取模块2及所述动态路径拆分模块4,用于将函数调用路径子集与函数调用基本路径集进行匹配,确保函数调用路径子集是属于函数调用基本路径集的子集;
所述路径集优化模块6,其连接所述路径匹配模块5,用于将经所述匹配模块处理过的所有函数调用路径子集作为一个动态路径集,并优化该动态路径集;
所述覆盖率计算模块7,其连接所述路径集优化模块1,用于计算优化后的动态路径集占函数调用基本路径集的比率,得到覆盖率。
如图6所示,所述插桩预处理模块1包括依次连接的插桩点选择模块11、桩函数设计模块12和插桩信息存放模块13:
所述插桩点选择模块11,其用于以源代码所包括的每个函数作为一个块结构,再针对每个块结构,将函数起始点、控制逻辑关键字所在点和函数结束点作为插桩点;
所述桩函数设计模块12,其连接所述插桩点选择模块11,用于设计桩函数,并将桩函数插入到选择的插桩点中;
所述插桩信息存放模块13,其连接所述桩函数设计模块12,用于存放插入桩函数后生成的插桩信息,包括函数对象列表信息和控制关键字对象列表信息。
如图7,所述动态路径拆分模块4包括依次连接的信息读入模块41、信息存放模块42和拆分执行模块43:
所述信息读入模块41,其用于分别读入动态路径和函数对象列表及控制逻辑关键字对象列表;
所述信息存放模块42,其连接所述信息读入模块41,用于将动态路径包含的每个桩点值存放到ArrayList数组里,将函数对象列表和控制逻辑关键字对象列表的信息分别存放到哈希表中;
所述拆分执行模块43,其连接所述信息存放模块42,用于将动态路径里的桩点值分别与函数对象列表和控制关键字对象列表进行比较,根据桩点值类型的不同对动态路径进行不同的拆分处理。
如图8所示,所述路径匹配模块5包括依次连接的路径存放模块51、树形结构建立模块52和查找模块53:
所述路径存放模块51,其用于将函数调用基本路径集里的函数调用路径存放到ArrayList数组中;
所述树形结构建立模块52,其连接所述路径存放模块51,用于遍历ArrayList数组,将函数调用基本路径集里的函数调用路径构建成树形结构;
所述查找模块53,其连接所述树形结构建立模块52,用于在函数调用基本路径集的树形结构中查找是否存在函数调用路径子集的函数调用路径,当且仅当一个函数调用路径子集中的所有函数调用路径都存在于树形结构中时,该函数调用路径子集能成功匹配函数调用基本路径集,否则匹配不成功,并重新对动态路径进行拆分。
以上所述仅为本发明的较佳实施例,并不用以限制本发明,凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。
Claims (2)
1.一种基于函数调用路径的覆盖率动态跟踪方法,其特征在于,包括:
步骤1,对被测程序源代码进行插桩预处理,得到函数对象列表和控制关键字对象列表;
步骤2,获取源代码的函数调用基本路径集;
步骤3,执行测试用例,并运行经步骤1插桩后的源代码,获得由源代码的执行路径的桩点数据流组成的动态路径;
步骤4,根据函数对象列表和控制关键字对象列表提供的信息,对步骤3获得的动态路径进行拆分,得到测试用例所覆盖的函数调用路径子集;
步骤5,将函数调用路径子集与函数调用基本路径集进行匹配,确保函数调用路径子集是属于函数调用基本路径集的子集;
步骤6,将所有函数调用路径子集作为一个动态路径集,优化该动态路径集;
步骤7,计算优化后的动态路径集占函数调用基本路径集的比率,得到覆盖率;
所述步骤1具体包括:
步骤11,选择插桩点;
步骤12,设计桩函数,并将桩函数插入到选择的插桩点中;所述桩函数包括:函数的入口点插入CProbeS(tag)函数;函数的出口点插入CProbeE(tag);控制关键字为真时插入CProbeT(tag)函数,且以标记(CProbeT(tag),1)表示;控制关键字为假时插入CProbeF(tag)函数,且以标记(CProbeF(tag),0)表示;其中tag为8位16进制的数;
步骤13,存放插入桩函数后生成的插桩信息,包括函数对象列表信息和控制关键字对象列表信息;函数对象列表的文件存储数据格式有五个字段,分别为:起始桩点、函数名、起始行、终止行、结束桩点;起始桩点字段里包含的内容为函数的入口桩点数据值;函数名字段里包含的内容为函数原型,有函数的返回类型、函数名、函数参数列表;起始行字段里包含的内容为函数的起始行行号;终止行字段里包含的内容为函数的结束行行号;结束桩点字段里包含的内容为函数的出口桩点数据值;函数起始桩点和结束桩点与函数名是一一对应关系;控制逻辑关键字对象列表的文件存储数据格式有四个字段,分别为:假桩点、关键字、函数名、真桩点;假桩点字段里包含的内容为控制关键字为假的桩点数据值;关键字字段里包含的内容为控制关键字;函数名字段里包含的内容为控制关键字所在的函数原型里:有函数的返回类型、函数名、函数参数列表;真桩点字段里包含的内容为控制关键字为真的桩点数据值;
所述步骤11具体包括:基于块结构划分源代码,以源代码所包括的每个函数作为一个块结构,再针对每个块结构,将函数起始点、控制逻辑关键字所在点和函数结束点作为插桩点;所述步骤4中对动态路径进行拆分具体包括:
步骤41,分别读入动态路径、函数对象列表及控制逻辑关键字对象列表;
步骤42,将动态路径包含的每个桩点值存放到ArrayList数组里,将函数对象列表和控制逻辑关键字对象列表的信息分别存放到哈希表中;
步骤43,将动态路径里的桩点值分别与函数对象列表和控制关键字对象列表进行比较,根据桩点值类型的不同对动态路径进行不同的拆分处理;所述桩点值类型包括以下四种:1)函数桩点,遇到函数真桩点时,将其与函数假桩点栈中的栈顶元素进行比较,如果不相等,则将该桩点进行函数真桩点栈的入栈操作,并记录该函数真桩点所对应的函数名,同时将其对应的假桩点也进行函数假桩点栈的入栈操作;遇到函数假桩点,则对函数真桩点栈和函数假桩点栈进行出栈操作;2)递归情况,遇到函数真桩点时,将其与函数假桩点栈中的栈顶元素进行比较,如果相等,则说明该函数发生了递归;对于函数递归的情况,应记录每次递归时的路径,并与递归数组里已有的路径进行比较;其中,递归数组是用来存放每次递归时的路径,初始时为空;如果发现该路径不存在于递归数组中,则将该路径添加到递归路径数组里,否则舍弃该路径;3)循环情况,遇到循环关键字判定真桩点,将其与循环真桩点栈的栈顶元素进行比较,如果相等,则说明是当前循环;记录每次循环时的路径,并与循环数组里已有的路径进行比较;其中,循环数组是用来存放每次循环时的路径,初始时为空;如果发现有不同的路径,则将该路径添加到循环路径数组里,否则舍弃该路径;如果发现该桩点与栈顶元素不相等,则说明进入下一个循环,递归调用循环模块函数;4)选择情况,遇到选择关键字的时候,在一次实际执行时,只能执行一条分支;要么是真分支语句、要么是假分支语句;因此无需对该结构块进行拆分处理,直接处理下一个结构块即可;
所述步骤5中将函数调用路径子集与函数调用基本路径集进行匹配具体包括:
步骤51,将函数调用基本路径集里的函数调用路径存放到ArrayList数组中;
步骤52,遍历ArrayList数组,将函数调用基本路径集里的函数调用路径构建成树形结构;
步骤53,在函数调用基本路径集的树形结构中查找是否存在函数调用路径子集的函数调用路径,当且仅当一个函数调用路径子集中的所有函数调用路径都存在于树形结构中时,该函数调用路径子集能成功匹配函数调用基本路径集,否则匹配不成功,需重新对动态路径进行拆分;
所述步骤6中优化动态路径集包括两个方面:一是基于动态路径集本身进行的优化,二是基于动态路径集中的各函数调用路径子集间的包含关系进行的优化;
所述基于动态路径集本身进行的优化具体包括:在将动态路径添加到动态路径集之前,判断动态路径集中是否已存在该动态路径,若存在,则说明该条动态路径是重复的动态路径,将其舍弃,同时将对应的测试数据也一并舍弃;若不存在,则将该条动态路径添加到动态路径集中;
所述基于动态路径集中的各函数调用路径子集间的包含关系进行的优化具体包括:计算出函数调用基本路径集中的函数调用路径被动态路径覆盖的条数,记为Ti,以及每条动态路径覆盖函数调用路径的条数,记为Ri;挑选出所有必不可少的动态路径,然后从函数调用基本路径集中删除被动态路径所覆盖的函数调用路径,重新计算Ti,Ri的值,迭代执行;当没有必不可少的动态路径时,挑选覆盖函数调用路径最多的动态路径,然后从函数调用基本路径集中删除该条动态路径所覆盖的函数调用路径,重新计算Ti,Ri的值,并再次查看是否有必不可少的动态路径,迭代执行;
所述步骤7具体包括:
根据覆盖率计算公式进行计算:
其中,测试需求为函数调用基本路径B(S,C),测试用例覆盖的测试需求为动态路径集L(S,D)通过优化算法后得到的函数调用路径子集U,代入得到:
在回归测试中需要对这些变更路径进行重点测试,针对变更路径的覆盖率计算公式为:
测试用例覆盖的变更路径是从函数调用路径子集U中挑选出的,测试需求中的变更路径是从函数调用基本路径集中挑选出的;在获知所有被修改函数的基础上,遍历函数调用基本路径集的树形结构,当树中的结点和被修改的函数名相同时,则记录该变更路径,迭代此操作,获得测试需求中的所有变更路径;同时构造函数调用路径子集U的树形结构,做同样的操作,获得测试用例覆盖的所有变更路径。
2.一种基于函数调用路径的覆盖率动态跟踪装置,其特征在于,包括:
插桩预处理模块,其用于对被测程序源代码进行插桩预处理,得到函数对象列表和控制关键字对象列表;
基本路径集获取模块,其用于获取源代码的函数调用基本路径集;
动态路径获取模块,其连接所述插桩预处理模块,用于执行测试用例,并运行经所述插桩预处理模块插桩后的源代码,获得由源代码的执行路径桩点数据流组成的动态路径;
动态路径拆分模块,其连接所述插桩预处理模块及所述动态路径获取模块,用于根据函数对象列表和控制关键字对象列表提供的信息,对获得的动态路径进行拆分,得到测试用例所覆盖的函数调用路径子集;
路径匹配模块,其连接所述基本路径集获取模块及所述动态路径拆分模块,用于将函数调用路径子集与函数调用基本路径集进行匹配,确保函数调用路径子集是属于函数调用基本路径集的子集;
路径集优化模块,其连接所述路径匹配模块,用于将经所述匹配模块处理过的所有函数调用路径子集作为一个动态路径集,并优化该动态路径集;
覆盖率计算模块,其连接所述路径集优化模块用于计算优化后的动态路径集占函数调用基本路径集的比率,得到覆盖率;
所述插桩预处理模块包括:
插桩点选择模块,其用于以源代码所包括的每个函数作为一个块结构,再针对每个块结构,将函数起始点、控制逻辑关键字所在点和函数结束点作为插桩点;
桩函数设计模块,其连接所述插桩点选择模块,用于设计桩函数,并将桩函数插入到选择的插桩点中;所述桩函数包括:函数的入口点插入CProbeS(tag)函数;函数的出口点插入CProbeE(tag);控制关键字为真时插入CProbeT(tag)函数,且以标记(CProbeT(tag),1)表示;控制关键字为假时插入CProbeF(tag)函数,且以标记(CProbeF(tag),0)表示;其中tag为8位16进制的数;
插桩信息存放模块,其连接所述桩函数设计模块,用于存放插入桩函数后生成的插桩信息,包括函数对象列表信息和控制关键字对象列表信息;函数对象列表的文件存储数据格式有五个字段,分别为:起始桩点、函数名、起始行、终止行、结束桩点;起始桩点字段里包含的内容为函数的入口桩点数据值;函数名字段里包含的内容为函数原型,有函数的返回类型、函数名、函数参数列表;起始行字段里包含的内容为函数的起始行行号;终止行字段里包含的内容为函数的结束行行号;结束桩点字段里包含的内容为函数的出口桩点数据值;函数起始桩点和结束桩点与函数名是一一对应关系;控制逻辑关键字对象列表的文件存储数据格式有四个字段,分别为:假桩点、关键字、函数名、真桩点;假桩点字段里包含的内容为控制关键字为假的桩点数据值;关键字字段里包含的内容为控制关键字;函数名字段里包含的内容为控制关键字所在的函数原型里:有函数的返回类型、函数名、函数参数列表;真桩点字段里包含的内容为控制关键字为真的桩点数据值;
所述动态路径拆分模块包括:
信息读入模块,其用于分别读入动态路径和函数对象列表及控制逻辑关键字对象列表;
信息存放模块,其连接所述信息读入模块,用于将动态路径包含的每个桩点值存放到ArrayList数组里,将函数对象列表和控制逻辑关键字对象列表的信息分别存放到哈希表中;拆分执行模块,其连接所述信息存放模块,用于将动态路径里的桩点值分别与函数对象列表和控制关键字对象列表进行比较,根据桩点值类型的不同对动态路径进行不同的拆分处理;所述桩点值类型包括以下四种:1)函数桩点,遇到函数真桩点时,将其与函数假桩点栈中的栈顶元素进行比较,如果不相等,则将该桩点进行函数真桩点栈的入栈操作,并记录该函数真桩点所对应的函数名,同时将其对应的假桩点也进行函数假桩点栈的入栈操作;遇到函数假桩点,则对函数真桩点栈和函数假桩点栈进行出栈操作;2)递归情况,遇到函数真桩点时,将其与函数假桩点栈中的栈顶元素进行比较,如果相等,则说明该函数发生了递归;对于函数递归的情况,应记录每次递归时的路径,并与递归数组里已有的路径进行比较;其中,递归数组是用来存放每次递归时的路径,初始时为空;如果发现该路径不存在于递归数组中,则将该路径添加到递归路径数组里,否则舍弃该路径;3)循环情况,遇到循环关键字判定真桩点,将其与循环真桩点栈的栈顶元素进行比较,如果相等,则说明是当前循环;记录每次循环时的路径,并与循环数组里已有的路径进行比较;其中,循环数组是用来存放每次循环时的路径,初始时为空;如果发现有不同的路径,则将该路径添加到循环路径数组里,否则舍弃该路径;如果发现该桩点与栈顶元素不相等,则说明进入下一个循环,递归调用循环模块函数;4)选择情况,遇到选择关键字的时候,在一次实际执行时,只能执行一条分支;要么是真分支语句、要么是假分支语句;因此无需对该结构块进行拆分处理,直接处理下一个结构块即可;
所述路径匹配模块包括:
路径存放模块,其用于将函数调用基本路径集里的函数调用路径存放到ArrayList数组中;树形结构建立模块,其连接所述路径存放模块,用于遍历ArrayList数组,将函数调用基本路径集里的函数调用路径构建成树形结构;
查找模块,其连接所述树形结构建立模块,用于在函数调用基本路径集的树形结构中查找是否存在函数调用路径子集的函数调用路径,当且仅当一个函数调用路径子集中的所有函数调用路径都存在于树形结构中时,该函数调用路径子集能成功匹配函数调用基本路径集,否则匹配不成功,并重新对动态路径进行拆分;
覆盖率计算模块还包括:
根据覆盖率计算公式进行计算:
其中,测试需求为函数调用基本路径B(S,C),测试用例覆盖的测试需求为动态路径集L(S,D)通过优化算法后得到的函数调用路径子集U,代入得到:
在回归测试中需要对这些变更路径进行重点测试,针对变更路径的覆盖率计算公式为:
测试用例覆盖的变更路径是从函数调用路径子集U中挑选出的,测试需求中的变更路径是从函数调用基本路径集中挑选出的;在获知所有被修改函数的基础上,遍历函数调用基本路径集的树形结构,当树中的结点和被修改的函数名相同时,则记录该变更路径,迭代此操作,获得测试需求中的所有变更路径;同时构造函数调用路径子集U的树形结构,做同样的操作,获得测试用例覆盖的所有变更路径。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201310379892.6A CN103473171B (zh) | 2013-08-28 | 2013-08-28 | 一种基于函数调用路径的覆盖率动态跟踪方法及装置 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201310379892.6A CN103473171B (zh) | 2013-08-28 | 2013-08-28 | 一种基于函数调用路径的覆盖率动态跟踪方法及装置 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN103473171A CN103473171A (zh) | 2013-12-25 |
CN103473171B true CN103473171B (zh) | 2016-06-08 |
Family
ID=49798035
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201310379892.6A Expired - Fee Related CN103473171B (zh) | 2013-08-28 | 2013-08-28 | 一种基于函数调用路径的覆盖率动态跟踪方法及装置 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN103473171B (zh) |
Cited By (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN116302994B (zh) * | 2023-02-28 | 2023-10-10 | 浙江大学 | 一种程序路径的层次化匹配方法、装置、设备及存储介质 |
Families Citing this family (26)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN104077232B (zh) * | 2014-07-21 | 2017-02-22 | 上海零一拼装信息技术有限公司 | 一种基于用例与源码双向追溯的测试装置及方法 |
CN105607989A (zh) * | 2014-11-18 | 2016-05-25 | 阿里巴巴集团控股有限公司 | 一种软件测试数据抽样方法及系统 |
CN105740272B (zh) * | 2014-12-10 | 2019-05-31 | 博雅网络游戏开发(深圳)有限公司 | 资源文件搜索方法和系统 |
CN105786453B (zh) * | 2014-12-16 | 2018-11-13 | 中国科学院沈阳自动化研究所 | 一种大规模plc安全参数序列保护模块和方法 |
CN104536895B (zh) * | 2015-01-12 | 2017-06-09 | 牟永敏 | 一种面向Java函数调用路径的测试过程跟踪方法及系统 |
CN106155897B (zh) * | 2015-04-16 | 2020-12-08 | 腾讯科技(深圳)有限公司 | 一种业务处理方法及装置 |
CN107153608B (zh) * | 2016-03-02 | 2020-06-26 | 腾讯科技(深圳)有限公司 | 代码检测方法以及代码检测装置 |
CN106407126B (zh) * | 2016-11-30 | 2019-04-30 | 网易(杭州)网络有限公司 | 覆盖率数据的处理方法、装置和服务器 |
CN108304173B (zh) * | 2017-01-13 | 2021-11-16 | 南京邮电大学盐城大数据研究院有限公司 | 一种获取网页执行JavaScript函数调用路径的方法 |
CN106844219B (zh) * | 2017-02-15 | 2021-02-02 | 腾讯科技(深圳)有限公司 | 应用检测方法及应用检测装置 |
CN108664504B (zh) * | 2017-03-30 | 2021-11-09 | 富士施乐实业发展(中国)有限公司 | 一种对结构化数据进行简化的方法 |
CN107704382B (zh) * | 2017-09-07 | 2020-09-25 | 北京信息科技大学 | 面向Python的函数调用路径生成方法和系统 |
CN108563580B (zh) * | 2017-12-27 | 2024-02-23 | 贵阳忆芯科技有限公司 | 介质接口控制器微码执行路径提取方法 |
CN109976999B (zh) * | 2017-12-28 | 2022-09-06 | 北京京东尚科信息技术有限公司 | 测试用例覆盖率的度量方法和度量装置 |
CN108256322B (zh) * | 2018-01-26 | 2020-10-27 | 平安科技(深圳)有限公司 | 安全测试方法、装置、计算机设备和存储介质 |
CN108536585B (zh) * | 2018-03-19 | 2022-01-11 | 北京信息科技大学 | 数据变更影响域分析方法 |
CN108763054B (zh) * | 2018-04-17 | 2021-03-23 | 平安科技(深圳)有限公司 | 测试案例的测试效果展示方法、电子装置及存储介质 |
CN108628600B (zh) * | 2018-05-08 | 2020-12-15 | 北京理工大学 | 基于控制流分析的软件动态行为建模方法和装置 |
CN108694320B (zh) * | 2018-05-15 | 2020-09-15 | 中国科学院信息工程研究所 | 一种多安全环境下敏感应用动态度量的方法及系统 |
CN109977030B (zh) * | 2019-04-26 | 2022-04-19 | 北京信息科技大学 | 一种深度随机森林程序的测试方法及设备 |
CN110727597B (zh) * | 2019-10-15 | 2023-03-10 | 杭州安恒信息技术股份有限公司 | 一种基于日志排查无效代码补全用例的方法 |
CN112905443A (zh) * | 2019-12-04 | 2021-06-04 | 阿里巴巴集团控股有限公司 | 一种测试用例生成方法、设备及存储介质 |
CN111782266B (zh) * | 2020-06-28 | 2023-08-25 | 中国工商银行股份有限公司 | 软件性能基准确定方法及装置 |
CN112416794B (zh) * | 2020-12-03 | 2023-11-21 | 平安银行股份有限公司 | 代码覆盖率的处理方法、装置、设备及存储介质 |
CN113886250B (zh) * | 2021-09-30 | 2023-04-11 | 四川大学 | 函数调用动态热力图的绘制方法 |
CN117520191A (zh) * | 2023-11-27 | 2024-02-06 | 浙江大学 | 一种基于程序路径的测试完备性检查方法、设备及存储介质 |
-
2013
- 2013-08-28 CN CN201310379892.6A patent/CN103473171B/zh not_active Expired - Fee Related
Non-Patent Citations (3)
Title |
---|
Research of Optimization Algorithm for Path-Based Regression Testing Suit;Bing JIANG etc.;《2010 Second International Workshop on Education Technology and Computer Science》;20101231;正文第2页 * |
基于函数调用的路径覆盖生成技术研究;张志华,牟永敏;《电子学报》;20100831;第38卷(第8期);全文 * |
面向嵌入式系统函数动态调用路径拆分与匹配;李良杰等;《数据通信》;20120828;第2012年卷(第4期);正文第1-4页 * |
Cited By (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN116302994B (zh) * | 2023-02-28 | 2023-10-10 | 浙江大学 | 一种程序路径的层次化匹配方法、装置、设备及存储介质 |
Also Published As
Publication number | Publication date |
---|---|
CN103473171A (zh) | 2013-12-25 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN103473171B (zh) | 一种基于函数调用路径的覆盖率动态跟踪方法及装置 | |
CN104866426B (zh) | 软件测试综合控制方法及系统 | |
US8930919B2 (en) | Modernization of legacy software systems based on modeled dependencies | |
CN106227668B (zh) | 数据处理方法和装置 | |
CN103678110B (zh) | 提供修改相关信息的方法和装置 | |
CN109144882A (zh) | 一种基于程序不变量的软件故障定位方法及装置 | |
CN104699613B (zh) | 一种航天器测试需求自动生成系统及其方法 | |
CN105138601A (zh) | 一种支持模糊约束关系的图模式匹配方法 | |
CN103116540A (zh) | 基于全局超级块支配图的动态符号执行方法及其装置 | |
CN102523155B (zh) | 一种基于Boost库的K则最短路径搜索方法和系统 | |
CN107402745A (zh) | 数据流图的映射方法及装置 | |
CN104063314A (zh) | 一种测试数据自动生成装置及方法 | |
CN106503872A (zh) | 一种基于基础业务活动集的业务流程系统构建方法 | |
CN112364352A (zh) | 可解释性的软件漏洞检测与推荐方法及系统 | |
CN105654187A (zh) | 控制系统中点定位方法之网格二叉树法 | |
CN103678513B (zh) | 一种交互式的检索式生成方法及系统 | |
CN108647146A (zh) | 基于修正条件判定组合覆盖的测试用例生成方法 | |
CN107194468A (zh) | 面向情报大数据的决策树增量学习方法 | |
CN105183624B (zh) | 一种基于数据匹配的仿真回放方法 | |
CN104484478A (zh) | 一种关联聚类数据瘦身方法及系统 | |
CN102262580A (zh) | 一种改进的基于符号执行的软件静态测试方法及工具 | |
CN101894063B (zh) | 一种用于微处理器功能验证的测试程序生成方法及装置 | |
CN113220578A (zh) | 一种功能测试用例的生成方法 | |
CN102707938A (zh) | 表形式软件规格制作支援方法及装置 | |
CN105159931A (zh) | 用于生成同义词的方法和装置 |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
C06 | Publication | ||
PB01 | Publication | ||
C10 | Entry into substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
C14 | Grant of patent or utility model | ||
GR01 | Patent grant | ||
CF01 | Termination of patent right due to non-payment of annual fee | ||
CF01 | Termination of patent right due to non-payment of annual fee |
Granted publication date: 20160608 Termination date: 20170828 |