一种基于符号执行的带反馈测试用例生成方法

文档序号:6372288阅读:793来源:国知局
专利名称:一种基于符号执行的带反馈测试用例生成方法
技术领域
本发明涉及软件自动化测试中的测试用例生成,特别涉及在现有测试用例基础上,应用符号执行方法,通过设定覆盖目标和选择种子测试用例,限制约束求解的范围,以反馈和迭代的方式高效率生成测试用例。
背景技术
在软件测试过程中,测试用例生成是最重要的环节之一。有效的测试用例生成可以提高测试执行效果,同时降低测试成本和时间。目前测试用例生成基本靠人工来完成,耗时耗力,难以达到理想的程序覆盖率,因此需要有效的自动化测试用例生成方法。自动化测试用例生成的效果一般由程序覆盖率来度量,较高的覆盖率意味着更高的缺陷检测概率和软件质量保证能力。一个好的测试用例生成方法能够以较少的测试用例数量来达到较高的·程序覆盖率。现有的自动化测试用例生成方法包含三个类别随机测试、基于搜索的测试以及符合执行。其中随机测试方法采用随机的方式生成测试用例输入,常生成过多的测试用例,且难以完成对特定程序覆盖目标的处理;基于搜索的测试方法采用遗传算法等来达到指定程序路径的覆盖,常需要过多的时间来生成测试用例,且受到搜索空间的限制;符号执行方法采用符号变量来执行程序,通过求解约束表达式来达到程序覆盖目标;在面对较大规模程序时,常遇到约束条件爆炸问题,在现有约束求解技术下难以完成复杂约束表达式的求解。

发明内容
本发明的主要目的是针对传统自动化测试用例生成方法不能独立完成自动化测试用例生成任务的问题,提出一种基于符号执行的带反馈测试用例生成方法,以反馈和迭代的方式,通过收集程序覆盖信息,设定覆盖目标,限制符号执行中约束求解的范围,高效率生成测试用例。为实现本发明所述目的,本发明采用如下的步骤
1)执行已有的测试用例并收集测试用例覆盖信息;确定每个测试用例在执行时覆盖的被测程序中的语句块,一个语句块指在任何程序输入下,执行情况都相同的一组语句;汇总所有测试用例所覆盖的语句块,确定被测程序中尚未覆盖的语句块集合;
2)根据被测程序的控制流图确定符号执行的覆盖目标;覆盖目标是被测程序中尚未覆盖的某个语句块;
3)对被测程序插桩,植入引导符号执行的控制代码;控制代码包括标记语句和判定语
句;
4)从已有测试用例集中选择合适的种子测试用例,用于启动符号执行方法;5)针对覆盖目标应用符号执行方法生成新的测试用例;将新生成的多个测试用例补充到已有的测试用例集合中。上述5个步骤迭代执行,直至达到给定的测试用例生成目标。上述步骤2)中根据被测程序控制流图确定符号执行覆盖目标的处理过程是首先根据代码控制结构,将被测程序语句块组织成控制流图僅,图中的节点对应语句块,边代表语句块执行顺序;识别被测程序中每个函数/过程/方法中处于最高层次的子树,定义为上层子树;然后寻找覆盖率最低的函数/过程/方法(通过补充已有测试用例使其至少部分覆盖),在其对应的控制流图中确定第一个没有充分覆盖的上层子树;最后选择该上层子树中第一个没有被覆盖的语句块(对应非控制节点)作为本次符号执行的覆盖目标。上述步骤3)中被测程序插桩以植入引导符号执行的控制代码的处理过程是首先确定覆盖目标所在的函数/过程/方法,在其起始位置插入判定变量定义语句,判定变量 的初值置为“false”;然后在覆盖目标之前的位置插入判定变量赋值语句,将判定变量赋值为“true”;最后确定覆盖目标所处的上层子树,在上层子树之后的位置插入控制符号执行的判定语句;在符号执行中,判定语句根据判定变量的取值决定是否继续补充约束条件以求解更复杂的约束表达式。上述步骤4)中从已有测试用例集中选择种子测试用例的处理过程是首先从已有测试用例中筛选覆盖了步骤2中覆盖目标的父节点的所有测试用例;令控制流图CFG中覆盖目标所对应的节点为%,父节点是fTG中位于节点%之前且直接与%相连接的节点(按步骤2中的处理方式,父节点有且仅有一个);然后从这些测试用例中筛选对覆盖目标所处之上层子树的覆盖程度最高的测试用例;最后在剩余的测试用例中选择覆盖语句块总数最少的测试用例作为种子测试用例。上述步骤5)中针对覆盖目标应用符号执行方法生成测试用例的处理过程是首先根据覆盖目标确定符号执行的入口,包括对应函数/过程/方法的名称和参数列表;然后识别或选择符号执行需要处理的输入参数,即参数处理类型,符号执行无法处理的非数值参数必须作为常量,其他作为符号变量;根据种子测试用例为输入参数赋初值并设置符号执行的配置信息;配置信息的具体内容取决于所采用的符号执行方法,其中的关键是符号执行入口和参数处理类型;最后以插桩程序为基础驱动符号执行方法生成新的测试用例。本发明利用人工、随机生成、或者历史积累的初始测试用例集,以迭代和反馈的方式,通过收集程序覆盖信息,设定覆盖目标,有效限制符号执行中约束求解的范围,从而降低约束表达式的复杂度,减少符号执行的规模和数量,高效率生成测试用例。为达到同等的程序覆盖率,同随机测试方法相比较,本发明方法无论在测试用例生成时间上,还是在测试用例生成数量上,都远小于随机测试方法;同单纯符号执行方法相比较,除生成的测试用例数量略多以外,本发明只需要更少的测试用例生成时间,就可以处理更大规模和复杂度的软件程序,可以灵活处理不需要或者不能够进行符号执行的输入参数。归纳起来,本发明的优点主要是可用于各个测试阶段的自动化测试生成工作;可用于各种类型软件程序测试,不依赖于编程语言和测试环境;可充分利用被测程序已有的测试用例集;在自动化测试生成过程中,便于人工干预或引入其他的测试用例生成方法,具有较好的灵活性、可扩展性和适应性。


图I是基于符号执行的带反馈测试用例生成方法的结构 图2是根据控制流图确定符号执行覆盖目标的工作流程 图3是一个程序代码示例及其对应的控制流 图4是被测程序插桩并植入符号执行控制代码的工作流程 图5是程序代码示例和基于JPF工具的控制代码插桩示意 图6是从已有测试用例集中选择种子测试用例的工作流程 图7是应用符号执行方法生成新测试用例的工作流程图; 图8是针对程序代码示例的部分JPF工具配置信息示意图。
具体实施例方式下面结合附图进行详细说明。如图I所示,本发明方法由五个步骤组成其一,收集已有测试用例的程序覆盖信息;其二,根据被测程序的控制流图确定符号执行的覆盖目标;其三,对被测程序插桩,植入引导符号执行的控制代码;其四,从已有测试用例集中选择合适的种子测试用例;其五,针对覆盖目标应用符号执行方法生成新的测试用例。新生成的测试用例补充入现有的测试用例集;其六,重复上述步骤,直至达到给定的测试用例生成目标,如100%语句覆盖率。本发明方法的输入包括被测程序、以及由人工或随机测试等方法生成的测试用例集;输出是达到了指定程序覆盖率的测试用例集。步骤一是收集已有测试用例的程序覆盖信息。确定每个测试用例在执行时覆盖的程序语句块,一个语句块(或代码块)指在任何程序输入下,执行情况都相同的一组语句。汇总所有测试用例所覆盖的语句块,可以确定被测程序中尚未覆盖的语句块集合。步骤二是根据被测程序的控制流图确定符号执行的覆盖目标,过程如图2所示。根据代码控制结构,被测程序的语句块可以组织成为控制流图CFG =其中JV为控制流图的节点集合,每个节点对应一个语句块为控制流图的边集。对于任意两个语句块&;和%,有向边< >€ 表示W和\之间存在顺序关系,即\可能在\之后执行。有向边关联的节点为父子关系,即&是b的父节点,而b是K的子节点。图3所示为一个程序代码示例及其对应的控制流图。一个软件程序通常包含多个函数/过程/方法,控制流图一般以函数/过程/方法为单位组织。图3显示了函数“func(x,y) ”的语句块组成、及其所对应的一个控制流图。图3中在代码的左侧标识了每个语句块的编号,对应控制流图中相应节点的编号。控制流图中的节点一般分为控制节点(如节点I和4)和非控制节点(如节点2和5),控制节点对应程序中的控制语句。图中节点Γ3组成一个分支(或选择)结构,本身构成一颗子树;节点4、组成一个循环结构,如果不考虑逆向边< !U >,则也构成了一颗子树;在这颗子树中,节点6 8又组成了一个分支结构,构成低一层次的子树。有向边关联的节点对为父子节点,例如对有向边< 5.6 >,节点5是节点6的父节点,而节点6是节点5的子节点。在组织被测程序的控制流图时,识别每个函数/过程/方法中最高层次的所有子树,定义为上层子树。图3所示的函数代码中包含3个上层子树,分别由节点f 3、节点Γ9、以及节点l(Tll构成。
接下来确定符号执行的覆盖目标寻找覆盖率最低的函数/过程/方法,如果其覆盖率为0,则需采用人工或随机测试方法补充现有测试用例;这里假设该函数/过程/方法已部分覆盖;然后在其对应的控制流图中确定第一个没有充分覆盖的上层子树;再选择该上层子树中第一个没有被覆盖的语句块(要求对应非控制节点)作为本次符号执行的覆盖目标。按上述策略设定覆盖目标的目的是使得本次迭代中新生成的测试用例能够覆盖更多的未覆盖语句块。步骤三是插桩并植入引导符号执行的控制代码,过程如图4所示。控制代码的作用是保证随后的符号执行仅会搜索和求解该子树中覆盖目标所处路径上的约束表达式。所插桩的控制代码包含两个部分其一是标记语句,标记语句的功能有两个,第一是定义一个布尔型的判定变量;第二是为该变量设置布尔值。判定变量的定义位置可以根据编程语言的特性来确定,一般作为局部变量定义在对应函数/过程/方法的起始位置;在布尔值设定方面,其初始值设置为“false”,然后在覆盖目标(语句块)的起始位置将布尔值设置为
“true”。其二是判定语句,判定语句的功能是限制约束求解的范围和复杂度;判定语句置于覆盖目标所处的上层子树之后,要求是该子树执行之后、对应函数/过程/方法返回之前执行的第一条语句。判定语句的语法结构取决于所基于的符号执行方法,目标是根据判定变量的取值决定是否继续补充约束条件以求解更复杂的约束表达式。图5所示是根据图3的示例插桩后的程序代码。其中假设编程语言是Java,所采用的符号执行工具是JPF (Java Path Finder)。令函数“func (x, y) ”中尚未覆盖的第一个语句块编号是7。插桩后新增加了 3条语句,语句I和语句2是标记语句,分别定义布尔型判定变量“—flag_”并对其设置合适的布尔值。语句3是判定语句,置于循环结构(节点Γ9)之后,根据变量“—flag_”的取值决定是否继续添加后续的约束条件,图中若变量值为“false”则不再继续求解约束表达式。步骤四是从已有测试用例集中选择合适的种子测试用例,用于启动符号执行方法。图6所示为选择种子测试用例的工作流程。对于符号执行,种子测试用例的作用主要有两个方面一是提供确定的输入参数值,引导符号执行覆盖既定的程序覆盖目标;二是符号执行方法目前只能处理数值参数,对于非数值参数,种子测试用例能够提供合适的固定值(符号执行过程中将这些参数值视为常量)。基于上述,选择种子测试用例时遵循以下基本原则
1)种子测试用例必须覆盖既定覆盖目标的父节点。按步骤2,覆盖目标是上层子树中第一个未覆盖的语句块(对应控制流图中的非控制节点),其父节点必然被某一个测试用例覆盖。控制流图中存在多个父节点的节点必然是控制节点,如图3中的节点3、4、8和9等,覆盖目标对应非控制节点,有且仅有一个父节点;
2)种子测试用例对覆盖目标所处的上层子树覆盖尽可能多;
3)种子测试用例所覆盖的语句块总数尽可能少。按照原则I和2,种子测试用例可以有效减少符号执行的规模和范围,提高符号执行的效率;按照原则3,种子测试用例尽量简单,可以减少符号执行的运行时间,能够在较短的时间里生成更多的测试用例。如图6所示,按照上述原则,首先从已有测试用例集中筛选覆盖了既定覆盖目标的父节点的所有测试用例;然后从这些测试用例中筛选对覆盖目标所处之上层子树的覆盖程度最高的测试用例;最后在剩余测试用例中选择覆盖语句块总数最少的测试用例作为种子测试用例。步骤五是针对覆盖目标应用符号执行方法生成新的测试用例,过程如图7所示。首先根据覆盖目标确定符号执行的入口,需要获取两个方面信息第一是进行符号执行的函数/过程/方法名称,如图3中的“func () ”,其中包含既定的覆盖目标;第二是析取该函数/过程/方法的参数列表,包括各参数的类型和名称,图3中为两个整型参数“X,y”、以及一个字符串参数“z”。然后根据参数类型确定可以采用符号执行处理的参数,目前符号执行方法尚不能处理非数值参数和结构类型参数,在图3中整型参数“X,y”可以作为符号变量由符号执行来处理,而字符串参数“z”只能作为常量来处理。再后根据种子测试用例为输入参数赋初值,并设置符号执行方法的配置信息。图8所示为符号执行方法配置信息的一个实例,所采用的符号执行工具是JPF,运行对 象是图3中的示例函数,其中函数定义“func (int x, int y, String z)”被转换为^func(SymSsymScon) ”,确定了可以采用符号执行处理的输入参数。最后采用插桩后的程序,驱动符号执行方法,生成新的测试用例。新生成的多个测试用例补充到已有的测试用例
^ 由
: 口卞 O上述五个步骤以迭代方式重复执行,直至达到给定的测试用例生成目标(如100%语句覆盖率)。应用符号执行需要考虑程序中存在不可达路径的问题,本发明方法在迭代过程中允许人工介入,可以采用限制符号执行时间、限制方法的迭代次数、以及插桩时人为修改控制代码等方式更灵活地解决不可达路径问题。实证研究中我们采用十余个样本程序应用本发明方法生成测试用例,并同随机测试和单纯符号执行方法进行比对。实验结果表明,同随机测试方法相比较,为达到同等的程序覆盖率,本发明方法无论在测试用例生成时间上,还是在测试用例生成数量上,都远小于随机测试方法;同单纯符号执行方法相比较,本发明方法需要更少的测试用例生成时间,可以处理更大规模和复杂度的软件程序,可以灵活处理不需要或者不能够进行符号执行的输入参数;但由于初始测试用例集的存在,测试用例生成数量略多于单纯符号执行方法。
权利要求
1.一种基于符号执行的带反馈测试用例生成方法,其特征在于包括以下步骤 1)执行已有的测试用例并收集测试用例覆盖信息;确定每个测试用例在执行时覆盖的被测程序中的语句块;汇总所有测试用例所覆盖的语句块,确定被测程序中尚未覆盖的语句块集合; 2)根据被测程序的控制流图确定符号执行的覆盖目标;覆盖目标是被测程序中尚未覆盖的某个语句块; 3)对被测程序插桩,植入引导符号执行的控制代码;控制代码包括标记语句和判定语句; 4)从已有测试用例集中选择合适的种子测试用例,用于启动符号执行方法; 5)针对覆盖目标应用符号执行方法生成新的测试用例;将新生成的多个测试用例补充到已有的测试用例集合中; 6)上述5个步骤迭代执行,直至达到给定的测试用例生成目标。
2.根据权利要求I所述的基于符号执行的带反馈测试用例生成方法,其特征在于,上述步骤2)中根据被测程序控制流图确定符号执行覆盖目标的处理过程是首先根据代码控制结构,将被测程序语句块组织成控制流图CTC7,图中的节点对应语句块,边代表语句块执行顺序;识别被测程序中每个函数/过程/方法中处于最高层次的子树,定义为上层子树;然后寻找覆盖率最低的函数/过程/方法,在其对应的控制流图中确定第一个没有充分覆盖的上层子树;最后选择该上层子树中第一个没有被覆盖的语句块,对应非控制节点作为本次符号执行的覆盖目标。
3.根据权利要求I或2所述的基于符号执行的带反馈测试用例生成方法,其特征在于,上述步骤3)中被测程序插桩以植入引导符号执行的控制代码的处理过程是首先确定覆盖目标所在的函数/过程/方法,在其起始位置插入判定变量定义语句,判定变量的初值置为“false”;然后在覆盖目标之前的位置插入判定变量赋值语句,将判定变量赋值为“true”;最后确定覆盖目标所处的上层子树,在上层子树之后的位置插入控制符号执行的判定语句;在符号执行中,判定语句根据判定变量的取值决定是否继续补充约束条件以求解更复杂的约束表达式。
4.根据权利要求2所述的基于符号执行的带反馈测试用例生成方法,其特征在于,上述步骤4)中从已有测试用例集中选择种子测试用例的处理过程是首先从已有测试用例中筛选覆盖了步骤2)中覆盖目标的父节点的所有测试用例;令控制流图CTG中覆盖目标所对应的节点为~,父节点是CFG中位于节点nr之前且直接与nf相连接的节点,父节点有且仅有一个;然后从这些测试用例中筛选对覆盖目标所处之上层子树的覆盖程度最高的测试用例;最后在剰余的测试用例中选择覆盖语句块总数最少的测试用例作为种子测试用例。
5.根据权利要求I或2所述的基于符号执行的带反馈测试用例生成方法,其特征在干,上述步骤5)中针对覆盖目标应用符号执行方法生成测试用例的处理过程是首先根据覆盖目标确定符号执行的入ロ,包括对应函数/过程/方法的名称和參数列表;然后识别或选择符号执行需要处理的输入參数,即參数处理类型,符号执行无法处理的非数值參数必须作为常量,其他作为符号变量;根据种子测试用例为输入參数赋初值并设置符号执行的配置信息;配置信息的具体内容取决于所采用的符号执行方法,其中的关键是符号执行入口和參数处理类型; 后以插桩程序为基础驱动符号执行方法生成新的测试用例。
全文摘要
本发明公开了一种基于符号执行的带反馈测试用例生成方法,其步骤为(1)执行已有的测试用例并收集测试用例覆盖信息;(2)根据被测程序的控制流图确定符号执行的覆盖目标;(3)对被测试程序插桩,植入符号执行的控制代码;(4)从已有测试用例集中选择合适的种子测试用例;(5)针对覆盖目标应用符号执行方法生成新的测试用例,新生成的测试用例补充入测试用例集;(6)重复上述步骤,直至达到给定的测试用例生成目标。本发明可广泛应用于软件开发过程中的自动化测试,自动化生成测试用例,避免单纯符号执行的约束条件爆炸问题,提高效率;同时能够结合其他生成方法,缓解符号执行方法不能处理复杂数据结构的问题。
文档编号G06F11/36GK102736979SQ20121021928
公开日2012年10月17日 申请日期2012年6月29日 优先权日2012年6月29日
发明者庄元 , 汤九斌, 陈道蓄, 顾庆 申请人:南京大学
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1