首页> 中国专利> 程序路径中确定函数调用的上下文环境影响的方法

程序路径中确定函数调用的上下文环境影响的方法

摘要

本发明公开了一种程序路径中确定函数调用的上下文环境影响的方法,该方法将返回值、被调用函数重定义的全局变量、指针或引用类型参数作为被调用函数的输出型变量,并采用路径敏感和上下文敏感的符号化区间运算技术,计算被调用函数在路径上各调用点输出型变量必需满足的上下文条件,最后根据该条件生成模拟替换函数,模拟替换函数根据各调用点的条件动态调整输出型变量的取值,保证程序按照目标路径执行。该方法可以用于自动化单元测试中面向路径的测试,包括面向全路径测试、面向子路径测试和面向目标测试等,实验证明,采用本发明所述方法,能够保证被测程序按照目标路径执行,并提高单元测试效率。

著录项

  • 公开/公告号CN102708053A

    专利类型发明专利

  • 公开/公告日2012-10-03

    原文格式PDF

  • 申请/专利权人 北京邮电大学;

    申请/专利号CN201210127864.0

  • 申请日2012-04-27

  • 分类号G06F11/36(20060101);

  • 代理机构11228 北京汇泽知识产权代理有限公司;

  • 代理人刘淑敏

  • 地址 100876 北京市海淀区西土城路10号

  • 入库时间 2023-12-18 06:42:37

法律信息

  • 法律状态公告日

    法律状态信息

    法律状态

  • 2017-10-20

    授权

    授权

  • 2015-05-20

    实质审查的生效 IPC(主分类):G06F11/36 申请日:20120427

    实质审查的生效

  • 2012-10-03

    公开

    公开

说明书

技术领域

本发明涉及软件单元自动测试技术,尤其涉及一种程序路径中确定函数调用的上下文环境影响的方法。

背景技术

在对软件进行单元测试时,对于被测函数中的被调用的函数,通常不直接调用原函数,而是生成逻辑简单的替换函数,用替换函数模拟原函数的行为,主要原因有:1)可以将被测程序与执行代价较大的实际程序隔离,提高单元测试的效率;2)将被测函数与不可控制的执行环境隔离,让测试过程顺利进行;3)单元测试中,被调用函数可能尚未实现。自动化单元测试中,替换函数的生成会遇到新问题。传统的替换函数生成方法中,替换函数的输出值为随机值。自动化单元测试通常选择一条目标覆盖路径,然后生成满足该路径的测试用例,最后动态执行被测函数,判断沿该路径执行时,程序的行为是否正确。由于路径上被调用函数会修改调用点各变量的取值,被调用函数的随机输出值可能导致各变量的取值不能满足路径条件,导致被测函数不能按照目标覆盖路径执行,影响测试的覆盖率。因此,需要计算被调用函数在路径上每个调用点必须满足的路径上下文条件,替换函数根据各调用点必须满足的上下文条件修改输出型变量的取值,让被测函数按照目标覆盖路径执行。

发明内容

有鉴于此,本发明的主要目的在于提供一种程序路径中确定函数调用的上下文环境影响的方法,以计算给定路径中各函数调用点对上下文环境所产生的影响,通过采用路径敏感的符号化区间运算技术确定被调用函数在路径上各调用点必须满足的上下文条件,最后根据该条件生成被调用函数的模拟替换函数,保证被测程序按照目标覆盖路径执行,从而提高单元测试的效率和覆盖率。

为达到上述目的,本发明的技术方案是这样实现的:

一种程序路径中确定函数调用的上下文环境影响的方法,该方法包括:

A、获取被测函数的目标覆盖路径和满足该路径的测试用例;

B、提取被测函数使用的全局变量;

C、采用路径敏感的符号化区间运算技术,计算被调用函数在路径上各调用点必需满足的路径上下文条件;

D、基于上下文条件,生成模拟替换代码;对于同一函数可能在路径上被多次调用,使用F表示被调用函数、 fi为被调用函数在路径上的一个调用点。

其中:所述步骤A包括:

A1、获取目标覆盖路径和让待测函数沿该路径执行的测试用例;

A2、对于控制流图G = (Node,Edge,start,end),路径P表示待测函数的一条执行序列<start,n1,…nend>,其中:所述start∈ Node为函数入口, n∈ Node,如果nend== endP为一条完整路径,否则P为一条子路径;

A3、如果同一控制流图节点在路径上出现多次,视为不同的路径节点。

其中:所述步骤B包括:

B1、将路径的首节点设置为当前节点,沿路径进行数据流迭代;

B2、判断当前节点是否存在全局变量,如果是,执行步骤B3,如果否,执行步骤B4;

B3、将当前节点使用的全局变量添加到被测函数的全局变量集合中;

B4、判断当前节点是否为路径的尾节点,如果是,退出计算;如果否,将当前节点的后继节点设置为当前节点,然后返回步骤B2。

其中:所述步骤C包括:

C1、为待测函数的输入变量生成对应的符号,符号对应的初始取值区间的上限和下限都设置为测试用例中该变量的取值;

C2、将路径的头节点设置为当前节点,沿路径进行数据流迭代;

C3、根据当前节点对应的语句更新数据流信息;

C4、判定当前节点是否为尾节点,如果是,退出计算;如果否,执行步骤C5;

C5、将当前节点的后继节点设置为当前节点,然后返回步骤C3。

其中:所述步骤C3包括:

C31、将当前所有符号以及符号对应的取值区间备份为前置信息pre-info;

C32、如果当前节点存在函数调用点f,为函数调用点生成对应的ID,所述ID包括该调用点对应的抽象语法树节点信息和控制流图节点信息;为有效输出型变量生成对应的符号,有效输出型变量包括返回值、指针或引用类型的参数、被测函数使用、且被f重定义的全局变量,将各有效输出型变量及初始符号< var, symbol>记录到f的初始符号集合中,将符号对应的初始取值区间下限设置为负无穷,将初始取值区间的上限设置为正无穷;

C33、如果当前节点存在尚未符号化的变量,为该变量生成对应的符号;

C34、如果当前节点对应的语句是赋值语句,计算赋值表达式的右端表达式对应的符号表达式,将赋值表达式的左端变量对应的符号表达式替换为计算结果;

C35、如果当前结点为分支结点,根据分支结点中的条件表达式计算各符号的分支限定区间;

C36、清除无效符号。

其中:所述步骤C36包括:

C361、获取当前所有的符号放入集合中;

C362、如果符号集合不为空,从集合中选择一个符号symbol,将符号从集合中移除,执行步骤C363,否则退出当前步骤;

C363、查找是否有变量对应的符号表达式中包含symbol,如果是,执行步骤C362;如果否,则步骤C364;

C364、判断symbol是否为某函数调用点f的输出型变量var的初始符号,如果是,执行步骤C365;如果否,执行步骤C366;

C365、从pre-info中取出symbol对应的取值区间domain,将<var,domain>保存到函数调用点f的必需满足的上下文条件中;

C366、清除symbol及对应的取值区间。

其中:所述步骤D包括:

D1、将路径上所有被调用函数放入被调用函数集合;

D2、判断被调用函数的集合是否为空,如果是,退出当前步骤;如果否,从集合中选择一个被调用函数F,将F从集合中移除,执行步骤D3;

D3、将F在路径上所有调用点的ID及各调用点必需满足的上下文条件放入集合set中,将该set中的上下文条件根据ID进行排序,形成被调用函数的路径条件链表;

D4、根据路径条件链表,生成模拟替换函数代码,然后返回步骤D2。

其中:所述步骤D3进一步包括:

D31、初始路径条件链表list,判断set是否为空,如果是,将list保存为F的路径条件,退出计算;如果否,执行步骤D32;

D32、新建链表节点n,从set中选取尚未处理的上下文条件存入链表节点中,并将该条件从set中移除,判定当前链表是否为空,如果是,执行步骤D33,如果否,执行步骤D34;

D33、将n设置为链表头节点,执行步骤D32;

D34、将链表头节点设置为当前节点;

D35、将n与当前节点的ID进行比较,判定其ID是否比当前节点的ID小,如果是,执行步骤D36;如果否,执行步骤D37;

D36、将n插入到当前节点之前,执行步骤D32;

D37、将当前节点的后继节点设置为当前节点,执行步骤D35;其中,所述步骤D35对ID进行比较排序时,对于对应的控制流图节点不同的调用点,按照节点在路径上的顺序进行排序;对于控制流图节点相同的调用点,根据其抽象语法树节点上保存的位置信息进行排序,起始行号交小的排在前面,起始行号相同的起始列号较小的排在前面。

其中:所述步骤D4进一步包括:

D41、生成模拟替换函数,所述模拟替换函数包含链表生成代码和变量处理代码;

D42、链表生成代码根据步骤D3计算的结果创建链表,其中链表的头节点代表模拟替换函数在路径上第一次被调用时必须满足的路径上下文条件,链表的尾节点代表模拟替换函数在目标路径上最后一次被调用时必须满足的路径上下文条件;

D43、变量处理代码根据D42创建的链表,调整有效输出型变量的取值区间,当目标覆盖路径为子路径时,由于被测程序动态执行时会执行一条完整路径,对于不在子路径上的调用点,模拟替换函数将有效输出型变量的值赋为最大取值范围内的随机值;

D44、当替换函数被调用,判定链表是否为空,如果否,执行步骤D45,如果是,执行步骤D48;

D45、替换函数获取链表的头结点中的上下文条件,将有效输出型变量的值赋为的上下文条件中该变量取值区间内的随机值;

D46、将当前头节点从链表中移除;

D47、将当前结点的后继节点设置为头结点;

D48、将有效输出型变量的值赋为最大取值范围内的随机值。

本发明所提供的程序路径中确定函数调用的上下文环境影响的方法,具有以下优点:

该方法采用路径敏感和上下文敏感的符号化区间运算技术计算被调用函数在路径上各调用点必需满足的上下文条件,最后根据上下文条件生成被调用函数的替换函数,保证程序按照目标路径执行,提高单元测试的效率和覆盖率。

附图说明

图1为本发明所述程序路径中确定函数调用的上下文环境影响的方法的流程示意图;

图2为本发明被测函数使用的全局变量提取实现流程示意图;

图3为计算被调用函数在路径上各调用点必须满足上下文条件实现流程示意图;

图4 为模拟替换函数生成的流程示意图;

图5 为模拟替换代码的执行流程示意图; 

图6 为源程序test.c中函数f1的控制流图;

图7 为源程序test.c中函数f1的一条目标覆盖路径示意图。

具体实施方式

下面结合附图及本发明的实施例对本发明的方法作进一步详细的说明。

本发明的基本思想:通过计算对给定路径中各函数调用点对上下文环境所产生的影响,采用路径敏感的符号化区间运算技术确定被调用函数在路径上各调用点必需满足的上下文条件,最后根据该条件生成被调用函数的模拟替换函数,保证了被测程序按照目标路径执行,从而达到提高单元测试的效率和覆盖率的目的。

图1为本发明所述程序路径中确定函数调用的上下文环境影响的方法的流程示意图,该方法将返回值、被调用函数重定义的全局变量、指针或引用类型参数作为被调用函数的输出型变量,并采用路径敏感和上下文敏感的符号化区间运算技术,计算被调用函数在路径上各调用点输出型变量必需满足的上下文条件,最后根据该条件生成模拟替换函数,模拟替换函数根据各调用点的条件动态调整输出型变量的取值,保证程序按照目标路径执行。该方法能够用于自动化单元测试中面向路径的测试,包括面向全路径测试、面向子路径测试和面向目标测试等。如图1所示,该方法的详细过程包括如下步骤:

步骤11:获取被测函数的目标覆盖路径和满足该路径的测试用例。具体包括:

步骤111:获取目标覆盖路径和让待测函数沿该路径执行的测试用例;

步骤112:对于控制流图G = (Node,Edge,start,end),路径P表示待测函数的一条执行序列<start,n1,…nend>,其中start∈ Node代表函数入口, n∈ Node,如果nend== endP代表一条完整路径,否则P代表一条子路径;

步骤113:如果同一控制流图节点在路径上出现多次,视为不同的路径节点。

步骤12:提取被测函数使用的全局变量。详细过程如图2所示。

步骤13:采用路径敏感的符号化区间运算技术,计算被调用函数在路径上各调用点必需满足的路径上下文条件。详细过程如图3所示。

步骤14:基于上下文条件,生成模拟替换代码;进一步地,对于同一函数可能在路径上被多次调用,使用F代表被调用函数、 fi代表被调用函数在路径上的一个调用点。详细过程如图4、图5所示。

图2为本发明被测函数使用的全局变量提取流程示意图,如图2所示该方法包括以下步骤:

步骤121:将路径的首节点设置为当前节点,沿路径进行数据流迭代;

步骤122:判断当前节点是否存在全局变量,如果是,执行步骤123;如果否,执行步骤124;

步骤123:将当前节点使用的全局变量添加到被测函数的全局变量集合中;

步骤124:判断当前节点是否为路径的尾节点,如果是,退出计算;如果否,则执行步骤125;

步骤125:将当前节点的后继节点设置为当前节点,返回步骤122。

图3为本发明计算被调用函数在路径上各调用点必须满足上下文条件实现流程示意图,如图3所示该方法包括以下步骤:

步骤131:为待测函数的输入变量生成对应的符号,符号的初始区间的上下限都设置为测试用例中输入变量的取值;

步骤132:将路径的头节点设置为当前节点,沿路径进行数据流迭代;

步骤133:根据当前节点对应的语句更新数据流信息;所述更新数据流信息的过程,具体包括如下步骤:

步骤1331:将当前所有符号以及符号对应的取值区间备份为前置信息pre-info

步骤1332:如果当前节点存在函数调用点f,为函数调用点生成对应的ID,ID包括该调用点对应的抽象语法树节点信息和控制流图信息。为有效输出型变量生成对应的符号,有效输出型变量包括返回值、指针或引用类型的参数、被测函数使用、且被f重定义的全局变量,将变量及符号< var, symbol>记录到f的初始符号集合中,将符号对应的初始取值区间下限设置为负无穷,将初始取值区间的上限设置为正无穷;

步骤1333:如果当前节点存在尚未符号化的变量,为该变量生成对应的符号;

步骤1334:如果当前节点对应的语句是赋值语句,计算赋值表达式的右端表达式对应的符号表达式,将赋值表达式的左端变量对应的符号表达式替换为计算结果;

步骤1335:如果当前结点为分支结点,根据分支结点中的条件表达式计算各符号的分支限定区间;

步骤1336:清除无效符号。该过程进一步包括:

步骤13361:获取当前所有的符号并放入集合中;

步骤13362:如果符号集合不为空,从集合中选择一个符号symbol,将符号从集合中移除,执行步骤13363,否则退出当前步骤;

步骤13363:查找是否有变量对应的符号表达式中包含symbol,如果是,执行步骤13362;如果否,执行步骤13364;

步骤13364:判断symbol是否为某函数调用点f的某输出型变量var的初始符号,如果是,执行步骤13365;如果否,执行步骤13366;

步骤13365:从前置信息中取出symbol对应的取值区间domain,将<var,domain>保存到函数调用点f必须满足的上下文条件中;

步骤13366:清除symbol及对应的取值区间。

步骤134:判断当前节点是否为路径的尾节点,如果是,退出计算,如果否,将当前节点的后继节点设置为当前节点,执行步骤133。

图4为本发明被调用函数的模拟替换函数生成流程示意图,如图4所示该方法包括以下步骤:

步骤141:将路径上所有被调用函数放入被调用函数集合set。如,将该函数所有调用点的ID及其必须满足的上下文条件放入集合set中,初始化链表。

步骤142:判断被调用函数的集合是否为空,如果是,退出当前步骤;如果否,从集合中选择一个被调用函数F,将F从集合中移除,执行下一步骤;

例如,判断该set是否为空,如果是,退出当前步骤;如果否,则执行步骤143。

步骤143:将F在路径上所有调用点的ID及各调用点必需满足的上下文条件放入集合set中,将set中的上下文条件根据ID进行排序,形成被调用函数的路径条件链表。具体如下:

步骤1431:初始路径条件链表list,判断set是否为空,如果是,将list保存为F的路径条件,退出计算;如果否,执行步骤1432;

步骤1432:新建链表节点n,从set中选取尚未处理的上下文条件存入链表节点中,并将该条件从set中移除,判定当前链表是否为空,如果是,执行步骤1433;如果否,执行步骤1434;

步骤1433:将n设置为链表头节点,执行步骤1432;

步骤1434:将链表头节点设置为当前节点;

步骤1435:将n与当前节点的ID进行比较,判定其ID是否比当前节点的ID小,如果是,执行步骤1436;如果否,则执行步骤1437;

步骤1436:将n插入到当前节点之前,执行步骤步骤1432;

步骤1437:将当前节点的后继节点设置为当前节点,执行步骤1435。

上述步骤1435对ID进行比较排序时,对于对应的控制流图节点不同的调用点,按照节点在路径上的顺序进行排序;对于控制流图节点相同的调用点,根据其抽象语法树节点上保存的位置信息进行排序,起始行号交小的排在前面,起始行号相同的起始列号较小的排在前面。

步骤144:根据路径条件链表,生成模拟替换函数代码,返回步骤142。

图5为模拟替换代码的执行流程示意图,取链表的头节点为当前节点,根据当前节点保存的信息,修改有效输出型变量的取值;将当前头节点的后继节点设置为链表的头节点;将当前节点从链表中移除。如图5所示,所述根据路径条件链表,生成模拟替换函数代码的详细过程如下:

步骤1441:生成模拟替换函数,模拟替换函数包含链表生成代码和变量处理代码;

步骤1442:链表生成代码根据上述步骤143计算的结果创建链表,其中链表的头节点代表模拟替换函数在路径上第一次被调用时必须满足的路径上下文条件,链表的尾节点代表模拟替换函数在目标路径上最后一次被调用时必须满足的路径上下文条件;

步骤1443:变量处理代码根据步骤1442创建的链表,调整有效输出型变量的取值区间,当目标覆盖路径为子路径时,由于被测程序动态执行时会执行一条完整路径,对于不在子路径上的调用点,模拟替换函数将有效输出型变量的值赋为最大取值范围内的随机值;

步骤1444:当替换函数被调用,判断当前链表是否为空,如果否,执行步骤1445;如果是,执行步骤1448;

步骤1445:替换函数获取链表的头结点中的上下文条件,将有效输出型变量的值赋为的上下文条件中该变量取值区间内的随机值;

步骤1446:将当前头节点从链表中移除;

步骤1447:将当前结点的后继节点设置为头结点;

步骤1448:将有效输出型变量的值赋为最大取值范围内的随机值。

下面为test.c的源代码,图6为被测函数f1的控制流图,目标覆盖路径为图7所示,为一条完整路径,其对应的语句如表2所示。为覆盖目标路径生成的测试用例为[x= -5,y = 1.5]。f2通过修改整型指针参数指向对象的值对待测函数调用点的上下文信息带来影响。通过本发明所述方法可以得出,为了执行第14行的语句,f2在12行的调用点必需将参数变量isErr的值赋为区间[41,∞]内的随机值。为了执行第21行的语句,f2在18行的调用点必需将参数变量isErr的值赋为区间[40,40]内的随机值。被测函数的目标覆盖路径上,f2被调用两次。根据计算结果生成的替换模拟函数第一次被调用时将参数指向对象的值赋为[41,∞]内的随机值,第二次被调用时将参数指向对象的值赋为[40,40]内的随机值,被测函数即可按照目标路径执行。

1: static int LEVEL = 40;

2: 

3: double f2(int*);

4: 

5:double f1(double x, double y)

6:{

7:   double a,b;

8:   int isErr = 10;

9:   a = y + 1.0;

10:  if(x < 0.0 )

11:  {

12:     b = f2(&isErr );

13:     if(isErr > LEVEL)

14:        goto on;

15:     goto ok;

16:  }

17:  on:

18:     b = f2(&isErr);

19:  if(isErr == LEVEL)

20:  {

21:     return b;

22:  }

23:  ok:

24:     return a;

25:} 

表1:控制流图节点和源程序对应表。

                                                

利用本发明对开源工程进行分支覆盖测试,被测函数的信息以及测试结果如表2所示。第六列为采用对输出变量随机赋值的策略导致不能正确执行的路径数目,第七列为采用本发明所述方法增加的正确执行路径数目。对比可发现,使用本发明所述方法,能让被测函数按照目标覆盖路径执行,自动化生成方式提高了单元测试的效率。

表2:测试结果。

经反复实验证明,采用本发明所述方法,能够保证被测程序按照目标路径执行,并提高单元测试效率。

以上所述,仅为本发明的较佳实施例而已,并非用于限定本发明的保护范围。

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号