单元自动化测试中类的抽象内存模型研究

单元自动化测试中类的抽象内存模型研究

2023年6月29日发(作者:)

 · 84·计算机测量与控制.2022.30(2) 犆狅犿狌狋犲狉犕犲犪狊狌狉犲犿犲狀狋牔犆狅狀狋狉狅犾 狆测试与故障诊断文献标识码:A文章编号:()://16714598202202008411  DOI10.16526t.2022.02.013  中图分类号:TP3.cnki.11-4762pj单元自动化测试中类的抽象内存模型研究杜婉莹,王雅文(北京邮电大学网络与交换技术国家重点实验室,北京 1)00876摘要:由于面向对象程序具有多态性等复杂特性,在软件单元测试中仅凭静态分析难以判断指针和引用指向对象的具体类型,为了解决这一问题,对类的抽象内存模型进行研究,并提出类的操作语义模拟算法;在路径分析时,通过构建和更新抽象内存模型,从而对变量所属类的范围进行限定;对于单元测试,对基于输入域的随机测试进行优化,提出基于路径的随机测试方法,得到输入变量的类型集合;实验表明,类的抽象内存模型结合操作语义模拟算法能够有效提取出路径中类相关的约束,基于路径的随机测试方法比起基于输入域的随机测试方法能够明显提高测试效率。关键词:面向对象;单元测试;抽象内存模型;符号表;静态分析;测试用例犚犲狊犲犪狉犮犺狅狀犃犫狊狋狉犪犮狋犕犲犿狅狉狅犱犲犾狅犳犆犾犪狊狊犲狊犻狀犃狌狋狅犿犪狋犲犱犝狀犻狋犜犲狊狋犻狀狔犕犵,WANGYDUWaninawenyg(,BStateKeaboratorfNetworkinndSwitchinechnoloeiinniversitfyLyogagTgyjgUyo,B)eiin00876,ChinaPostsandTelecommunications 1jg:D,犃犫狊狋狉犪犮狋uetothepolmorhismandothercomlexcharacteristicsofobect-orientedproramsitisdifficultyppjgtoudethesecifictesofobectspointedbointersandreferencesonltaticanalsisinsoftwareunittestin.jgpypjypybysyg,Inordertosolvethisproblem,theabstractmemorodelofclassesisstudiedandanoerationsemanticsimulationymp,alorithmofclassesisproosed.Durinathanalsistheclassscoetowhichthevariablebelonsislimitedbongpgpypgyc,structinndudatinheabstractmemorodel.Forunittestintherandomtestinasedontheinutdomainisgapgtymggbp,otimizedandapathbasedrandomtestinethodisproosedtoobtainthetesetofinutvariables.Exerimentspgmpypppshowthattheabstractmemorodelofclassescombinedwiththeoerationsemanticsimulationalorithmcaneffecympgtivelxtracttheconstraintsrelatedtoclassesinthepath,andthepathbasedonrandomtestmethodcansinificantlyegyimrovetheefficiencftestinomaredwiththeinutdomainbasedonrandomtestmethod.pyogcpp:o;;;;;犓犲狑狅狉犱狊bect-orientedunittestinabstractmemorodelsmboltablestaticanalsistestcasejgymyy狔0 引言如今,信息产业的蓬勃发展离不开信息技术的发展,涉及到了通信设备、计算机、软件等一系列领域。随着市场对软件质量要求和软件自身复杂度的不断提高,软件测试的重要性和软件测试在软件工程中]1所占的比例越来越大[。据统计,随着对软件可靠性]2发时间[,其中,单元测试作为软件测试的重要环节,其目的是检测各个单元模块的故障缺陷,会占用60%左右的测试工作所花费的时间。与手工测试相比,自动化测试能降低系统测试和维护等阶段的成本、有效提高测试的效率和质量,同时能够显著提高3],自动化测试工具测试覆盖率、大大扩展测试深度[的研发正逐渐受到重视。目前已有的自动化测试工具有L、PoiscoeRQA、gp要求的提高,软件测试会占用40%乃至60%的总开收稿日期:;2021112320211221。 修回日期:基金项目:国家自然科学基金项目()。U1736110作者简介:杜婉莹(,女,湖北鄂州人,硕士,主要从事软件自动化测试和程序静态分析相关领域方向的研究。1997)通讯作者:王雅文(,女,陕西凤翔人,博士,副教授,博士生导师,主要从事软件自动化测试和程序静态分析相关领1983)域方向的研究。引用格式:杜婉莹,王雅文.单元自动化测试中类的抽象内存模型研究[]计算机测量与控制,():J.2022,3028494.投稿网址:www.sclkz.comjjy Copyright©博看网 . All Rights Reserved.[4]、D、P节对提出的模型和算法进行实验并分析实验结果;第MacabeevPartnerurify等,这些测试工具要么分析代码的语法漏洞、要么统计程序执行时的数据,又或者是对功能的可行性和效率进行检测等。在这之中,单元测试工具有C、C++T、UnitestppVectorCAST、VisualUnit等,它们能对程序进行静态分析、也能生成测试框架代码,然而大部分都不支持测试用例自动生成功能,需要依赖人工来完成测试用例生成操作,因此,对测试用例生成方法的研究具有重要的理论和实践价值[5]第2期杜婉莹,等:单元自动化测试中类的抽象内存模型研究· 85·6节总结全文。1 类的抽象内存表示模型为了明晰函数中类对象的可取类型,以便确认单元测试的输入变量类型集合以及在函数调用点的函数13],可以在路径生成后,通过构建类摘要提取操作[的抽象内存模型并配合符号执行技术提取出路径上与类对象有关的约束,缩小类对象实际类型的可选范围,在精简测试用例集合的同时保证覆盖率,提高单元测试的效率。抽象内存模型是存储变量语义和约束的静态存储14]介质,用于记录变量在符号执行中的动态变化[。。面向对象程序具有封装、继承、多态三大特性。其中,继承使子类可以直接拥有父类定义的属性和操作,减少代码冗余,增强代码的复用性和可扩展性;多态能使同一操作在不同子类中有不同的具体实现,6]让对象以适合自己的方式响应事件[。当子类重写父对程序执行自动测试,需要先通过静态分析得到测试所需的代码信息,为此需要构建符号表,它也是类的抽象内存模型的基础。类函数,并让父类的指针或引用指向子类对象时触发。多态的存在令程序的编写仅需指明要执行的操作,在实际执行时编译器会根据对象所属的具体类型来调用相应的方法,从而表现出不同的行为,灵活性更高[7]11 类的符号表在静态建模中,抽象语法树是最重要的中间结构,它是源程序的一种抽象表现,也是提取程序信息的入手点。源程序的每行代码以及每个关键字都有对15]应的抽象语法树节点[。。对于包含存在于继承体系中的类对象的源程[]8序,仅凭静态分析,编译器无法判断程序中类型转换语句的结果以及被调用函数所属的类。在测试用例生成时,如果需要对类对象进行实例化,对象类型的选取是用例生成效率和有效性的一个影响因素。静态生成测试用例开销更小,也具有一定的挑战性,而面向路径的测试用例生成在白盒测试中非常常见。其中,符号执行使用符号来表示程序的输入数据,模拟执行被分析程序,用符号表达式操作代替程序中对变量和参数的操作,是路径分析的一种常用手段。在这一方面,国内外都有不少研究人员参与了研发工作,例如,Euclide定义了内存动态管理的9]操作语义模型[,许中兴等人提出了虚拟数组建模内1011]存[,赵云山等人设计实现了针对数值型变量的]12符号执行系统[。在单元测试中,当被测函数的输对面向对象程序执行单元测试需要先通过静态分析得到被测函数模块的输入变量。这就需要遍历程序的抽象语法树,正确并完整地识别出程序中各个类、函数和变量的信息以及它们之间的关联关系,将其记录于符号表中,在随后生成测试用例时便能快速获取所需信息。本课题的研究重点是类,由类在组成结构方面的特点可以归纳出其基本信息,由此可得类对应符号表的结构如表1所示。表1 类对应符号表的属性属性classNamearentspchildrenmemVarsmemMethodsisAbstractscoep说明类名类的父类情况类的子类情况类的成员变量类的成员函数是否为抽象类类对应作用域入变量中含有父类引用时,如何选择类进行实例化,当被调用函数是某个基类的成员函数时,应该选择哪个类中的该函数进行摘要提取,通过静态分析来解决这些问题是本课题研究的重点。本文第1节对类的抽象内存表示模型进行概述;第2节介绍类的操作语义模拟算法;第3节介绍基于抽象内存模型的单元测试用例生成方法;第4节通过一个实例演示路径分析中抽象内存的变化过程;第5 面向对象程序中不同的类可能存在于不同的继承体系中,同一继承体系中类的属性也存在差异。如果该类存在于继承体系中,就将它的父类和子类对应的投稿网址:www.sclkz.comjjyCopyright©博看网 . All Rights Reserved.16]性提取出来,这部分属性与类本身相对应,构成类类符号表项和继承类型存储起来[,由于面向对象程序的继承特性,子类无需声明便可拥有父类的成员,在记录了类的继承情况后,就可以通过符号表快速获取从父类继承下来的属性和特征。C++支持多继承;Java中的类虽然只能单继承,但是可以实现多[7]。个接口,因此parents是一个列表1· 86·  计算机测量与控制 第30卷型的抽象内存模型;剩下的属性则与具体对象有关,构成类对象的抽象内存模型。类类型的抽象内存模型与类对象的抽象内存模型之间的关系如图1所示。在类的成员变量中,静态变量需要单独标注,因为它们为该类的所有实例所共享,在抽象内存模型的构建和测试用例生成中都需要单独处理。不论是通过哪个实例对静态变量进行访问,实际效果和通过类名]18。调用是相同的,影响的都是同一个成员[在类的成员函数中,构造函数、静态函数、没有函数体的函数(例如Java的抽象方法和C++的纯虚函数)、有函数体但可以重写的函数(例如Java中除构造方法、静态方法、final和private修饰的方法以外的其他方法以及C++的虚函数)以及其他函数需要分开记录,可以通过这些列表的存储情况来判断类是否为抽象类。isAbstract用于说明该类对象能否直接实例化。因为抽象类和接口不能直接实例化,需要通过实例化子类并向上转型的方式来间接完成,所以这里需要被区分。本课题将接口与抽象类同等处理。在C++中,抽象类的子类只要没有重写父类的全部纯虚函数,就仍为抽象类;在Java中,抽象类通过abstract显示声明。图1 类的两种抽象内存模型之间的关系13 类类型的抽象内存模型以Java为例,在使用某个类时,首先要将该类加载到内存中,通过类加载器创建相应的Class对象。类的静态变量在内存中仅有一份,随着类的加载在方法区中分配内存,所以类的每个静态变量的抽象内存模型也应该只有一份。在路径分析中,即使是通过不同的类实例来访问和修改静态成员,影响的也只是同一个变量。因此,为每个初次遇见的类的Class对象构建类类型的抽象内存模型,其结构如表2所示,随着路径分析建立类类型的抽象内存模型与静态变量之间的关联关系。虽然C++的这一过程与Java不同,但是在符号执行中可以同等处理。表2 类类型的抽象内存模型属性属性smbolyvirtualAddrnameDeclarationnameteypmembers说明代表Class对象的符号类类型的抽象内存单元地址类对应符号表项类名Class对象的数据类型类的静态变量名和各个静态变量对应抽象内存模型的映射关系12 抽象内存模型分类在面向对象程序中,针对不同的数据类型,可以将抽象内存模型分为基本抽象内存模型、数组抽象内存模型、指针抽象内存模型和类的抽象内存模型,其中类的抽象内存模型也适用于记录结构体变量的内存情况。不同类别的抽象内存模型存在一些公共属性,如符号值、抽象内存单元地址、符号表项等。除了公共属性以外,不同的数据类型还有不同的语言特性,比如数组类型需要记录数组长度、指针类型指向的是]19内存单元地址、类的成员在内存中离散存放[。每不同类别的抽象内存模型放在对应的抽象内存区中,并通过地址来定位。针对不同的抽象内存区,地址使用不同的前缀,基本抽象内存模型所在区的前缀为犕狀,数组抽象内存模型所在区的前缀为犕犪,指针抽象内存模型所在区的前缀为犕狆,类的抽象内存模型所在区的前缀为犕犮。 个变量都对应一个抽象内存模型,类对象也是如此,但是同一个类的多个对象之间共享一部分属性,即静态变量,任意对象都可以对这部分属性进行访问和修改。本课题将类的抽象内存模型中与类结构相关的属投稿网址:www.sclkz.comjjyCopyright©博看网 . All Rights Reserved.关,不会受实际所属类影响。例如,类A符号表项和抽象内存模型是一一对应的,被测函le继承pp数中的每个类、变量以及复杂变量的成员变量都有这两项信息。为了提高运行效率,members初始为空,只有在初次遇到静态变量时,才为其创建抽象内存模型,并将映射关系添加进去,下一节中类对象的抽象内存模型同理。了类F,定义变量A,将其向上转型为ruitleapp,此时它的引用所属类为F,实际所属类为Fruitruit,可以访问FAleruit的静态成员,而无法访问ppAle的特有属性。然而,类对象的实际所属类在对pp路径的语义模拟和可达性分析、以及作为后续测试用例生成的参考中有很大作用。第2期杜婉莹,等:单元自动化测试中类的抽象内存模型研究· 87·14 类对象的抽象内存模型在路径分析中,对于首次遇到的类对象,要为其构建类对象的抽象内存模型。类对象离不开它所属的类,每个类对象都可以访问所属类的静态成员,这就需要指向对应的类类型的抽象内存模型的指针。由于面向对象程序的多态性,类对象的所属类需要进一步分为引用所属类和实际所属类,以便对类型转换语句和函数调用点进行分析,两者的意义不同,引用所属类从指向对象的指针或引用处获取,实际所属类记录于类对象的抽象内存模型中。类对象的抽象内存模型的结构如表3所示。表3 类对象的抽象内存模型属性属性smbolyvirtualAddrnameDeclarationnamesourcerealCTeypmembers说明代表当前变量的符号类对象的抽象内存单元地址变量对应符号表项变量名变量来源类对象的实际所属类类对象的非静态变量名和各个非静态变量对应抽象内存模型的映射关系2 类的操作语义模拟算法类对象作为非数值类型变量,在符号执行中仅仅20]使用一个符号[对其进行表示是不够的,也不利于21]对其求解,需要在路径分析中通使用约束求解器[过动态地抽象内存建模来描述它的语义和约束。使用抽象内存模型对非数值型变量的约束进行处理,从中提取出数值型约束,并将剩余部分转化为抽象内存中的存储结构。操作语义模拟算法能够在符号执行时根据某个程序点之前各个变量的语义和约束信息,以及当前语句的语义信息来更新相关变量的抽象内存模型,模拟出抽象内存中的状态变化。在符号执行中,当被测函数含有类对象时,构建类的抽象内存模型,配合操作语义模拟算法,提取出路径中的约束,对类对象的具体类型进行限定,从而生成满足路径条件的测试用例或者得到函数调用点处调用方法所属的类。与类有关的操作有对象创建、成员访问和类型转换,接下来以C++语言为例,分析每种操作对应的操作语义模拟算法,并用形式化语言进行描述。21 对象创建如表4所示,在C++中,创建对象有两种方式———直接定义(见①)和通过指针创建(见②)。前者与基本数据类型变量的定义格式类似,对象在栈上分配内存,不会体现面向对象程序的多态性;后者定义一个指向对象的指针,后续可以使用指针访问对象的成员变量和成员函数,对象本身是匿名的,在堆上分配内存,可能存在父类指针指向子类对象的情况,22]此时会出现多态[。使用new创建的对象需要配合name要么为变量声明时的名字,要么为复杂变量的成员变量名,如数组变量array的第一个成员变量的变量名为a]。rra0y[source指明该变量是输入参数、局部变量、全局变量还是类成员变量,又或者是上述某个复杂变量的成员变量。其中,输入参数、全局变量、类成员变量均是测试用例的组成部分,局部变量则不需要放在测试用例中。realCTe是类对象的抽象内存模型中最重要的yp属性,这是提取类型约束的关键,每个类对象的抽象内存模型都有指向所属类对应的类类型的抽象内存模型的指针。即使存在父类引用指向子类对象的情况,类对象能访问的静态成员也只与当前引用所属类有delete及时删除,以防止无用内存堆积。表4 对象创建的两种方式序号①②代码;ClassNamevar);ClassNamep(=newClassName投稿网址:www.sclkz.comjjy Copyright©博看网 . All Rights Reserved.抽象内存模型,则判断是否需要建立对象和成员之间对形如①的语句,直接为变量var创建类的抽象内存模型,首先判断是否已经创建了类ClassName对应的类类型的抽象内存模型,如果没有就进行构建;随后为变量var本身创建类对象的抽象内存模型,指定变量来源,变量的实际所属类为Class。无论是初次创建类类型的抽象内存模型还是Name初次创建类对象的抽象内存模型,都需要为其指定一个符号,在类的抽象内存区中新建一块抽象内存单元,并与对应的符号表项进行关联,且members初始均为空。对形如②的语句,先为指针p创建指针抽象内存模型,指定指针来源,定义指针状态为非空,再按上述步骤为指针p指向的类对象创建类的抽象内存模型,建立两者之间的联系。综上所述,对象创建的操作语义模拟算法的形式化语言描述如表5所示。如果,没有对其赋值,那只是声明ClassName类的指针p么它的初始状态为不确定,此时暂不需要创建类的抽象内存模型;如果约束指针状态为非空,但指针指向对象的类型尚不确定,那么类对象的实际所属类为空;如果类对象的引用所属类和实际所属类不同,还要判断两者是否存在继承关系。表5 对象创建的操作语义模拟算法序号算法((()))ifmodel=getClassModelClassName==null();model=createClassModelClassName()createObectModelvarj()();.setSourcesource.setRealCTemodelyp()createModelp()(.setSourcesource.setPTStateNOT_NULL)());.setPT(createModelp序号· 88·  计算机测量与控制 第30卷的关联关系,并根据成员类型和语义信息提取约束即可,否则为其构建抽象内存模型。对形如③的语句,构建var和var.mem之间的关联关系;对形如④的语句,构建p和p->mem之间的关联关系。如果mem是静态变量,关联关系建立在类类型的抽象内存模型中;如果mem是非静态变量,关联关系建立在类对象的抽象内存模型中。综上所述,以形如③的语句为例,成员访问的操作语义模拟算法的形式化语言描述如表7所示。表7 成员访问的操作语义模拟算法算法(()==n)if(model=getModelvar.mem)ull(;model=createModelvar.mem)!()if(isStaticvar.mem)()((),);etModelvar.utMembermodel.etNamemodel③gpg()if(isStaticvar.mem)()()etModelvar.etRealCTe.utMemberggypp((),m);model.etNameodelg值得注意的是,如果子类Ale继承了父类pp,在抽象内存中同时存在类Fruit的静态成员colorFruit的抽象内存单元和类Ale的抽象内存单元,pp且两个类类型的抽象内存模型的members都包含,那么它们存储的ccolorolor理应指向同一个抽象内存模型,为便于查找,类的静态成员的完整变量名统一为定义所在类的类名+变量名,比如,在这个例子中,类成员color在抽象内存模型中存储的变量名为“::c”。Fruitolor①②23 类型转换22 成员访问如表6所示,在C++中,根据创建对象方式的不同,访问成员的方式也有两种———直接访问(见见④)。③)和通过指针访问(表6 成员访问的两种方式序号③④代码var.mememp->m类型转换是类的操作语义模拟算法关注的重点,只有当路径中存在对类对象的类型判断或者类型转换语句时,才能根据不同分支或是能使程序继续执行所需的转换条件对类对象的类型进行约束。对象的向上转型会自动完成,因为向上转型一定是安全的,但是一旦转型为父类对象,就无法再调用子类原本特有的方法;对象的向下转型需要进行强制类型转换,且必须先发生过向上转型、才能成功向下转型,否则会报错。在编译时,编译器无法判断对象实例化时传递的是什么数据类型,因此不会对强制类型转换进行 访问对象的mem成员时,如果已经为其构建了投稿网址:www.sclkz.comjjyCopyright©博看网 . All Rights Reserved.检查。基于抽象内存模型的测试用例生成C++有4种强制类型转换函数,分别为const_、s、dcasttatic_castnamic_cast和reinterret_yp。其中,caststatic_cast和dnamic_cast均可以用y于类层次结构中基类和派生类之间指针或引用的转换。static_cast类似C语言中的强制转型,不提供运行时类型检查,因此在进行类的向下转型时具有一定的安全隐患;而dnamic_cast会在运行时对类型y信息进行检查,对于无法强制转型的变量会返回,从而保证类型转换的安全性。由于这两个函nulltrp数的特点,C++中的所有隐式类型转换都会调用;而在编码时,对于显式类型转换则常常static_cast通过dnamic_cast来实现y对象。如果出现类型判断语句或者类型转换语句,判断类对象是否已经确定实际所属类,如果没有且待转换类型与引用所属类存在继承关系,用位于更底层的类型更新实际所属类,继续执行;如果有,判断待转换的类型是否处于引用所属类与实际所属类所在的继承体系中,如果在,用三者中位于更底层的类型更新实际所属类,继续执行,否则说明路径不可达。综上所述,类型转换的操作语义模拟算法的形式化语言描述如表8所示。表8 类型转换的操作语义模拟算法序号算法()();addrCT=getModel.etAddrCTepgyp())();realCT=getModel.etPT(.etRealCTeggypp)if(realCT==null()if(extendscastCT,addrCT) ())(etModel.etPT(.setRealCTelower gpgyp();castCT,addrCT)⑤lse e/路径不可达 /elseif(extends(castCT,addrCT)&&extends ()castCT,realCT)())(etModel.etPT(.setRealCTelower gpgyp();castCT,realCT)lse e/路径不可达 /[]23第2期杜婉莹,等:单元自动化测试中类的抽象内存模型研究· 89·3 对函数模块执行单元测试可以采用基于输入域的随机测试、边界值测试和基于路径的随机测试等。提取出函数的输入变量,根据每个变量的数据类型生成多个随机值并组合成测试用例。其中,基于输入域的随机测试是指在变量的取值区间内生成随机值;边界值测试指的是在变量的取值范围的边界处生成随机值,除此之外还要考虑某些特殊值,例如对于整型变量,要特别考虑取值为0的情况。这两种测试方式简单高效,无需考虑函数内部的实现细节,可以很快生成大量测试用例,但是也很容易造成过多的冗余测试用例,并且生成的测试用例很难能够执行到函数内部24]某些条件苛刻的语句[。此时可以根据函数的控制。在Java中,通常使用instanceof关键字来判断某个实例是否是某个类的流图提取出未覆盖元素集合,使用基于路径的随机测试来生成覆盖到这些元素的测试用例。当被测函数的输入变量含有基类的指针或引用且函数中出现了类型转换语句时,如果不对路径信息进行分析,就无法判断对变量进行初始化时应该传递哪种类型的实例。就算先不考虑基类为抽象类的情况,如果直接对该基类对象实例化,很有可能在类型转换时出错、或者在类型判断时无法执行到相应分支;如果对该基类的所有底层子类创建实例化对象,再以父类引用指向子类对象的方式进行赋值,很有可能会生成众多冗余的随机值,使最终得到的测试用例集合非常庞大,且测试的复杂程度会随着代码和继承体系复杂程度的提高而成倍增长,然而这其中很多都是没有必要的,会大大降低测试效率。这时,通过构建类的抽象内存模型,对类对象的具体类型进行约束,就能使生成的测试用例以较少的数量覆盖到尽可能多的语句。分析被测函数,提取类的类型判断语句和类型转换语句对应的覆盖元素,从下往上逐个分析。对于当前覆盖元素,判断其是否为未覆盖元素,若为未覆盖元素,生成经过该覆盖元素的路径,从函数入口开始,为输入变量中的类对象构建类的抽象内存模型,通过符号执行提取出路径上类相关的约束,得到变量的类型信息。当获得的类型信息中对象的实际所属类与之前不同时,如果分析得到的类是非抽象类,直接为其生成随机值对象;如果分析得到的类是抽象类,为其距离最近的非抽象子类生成随机值对象。将各个投稿网址:www.sclkz.comjjy Copyright©博看网 . All Rights Reserved.研究C++程序中函数调用关系的静态分析方法时,输入变量的随机值组合成多组测试用例并代入执行,根据执行后的插装信息更新已覆盖元素集合和未覆盖25],如此反复。直到全部类型判断语句及元素集合[· 90·  计算机测量与控制 第30卷考虑到了函数内部的类型转换语句,在记录变量的类型信息时,会分别记录变量的声明类型和动态类型,以便对后续出现的函数调用语句进行解析。目前已有的面向对象自动化单元测试工具,如针/对CC++语言的ParasoftC++Test和针对Java语言的Randoop,其研发的重心并不在函数输入变量中类对象的具体类型。当出现类的指针或引用变量时,很多都只为基类对象生成取值。只为基类对象生成取值、为所有派生类对象生成取值,以及对变量类型进行约束后生成取值,这三种测试用例生成方式的结果对比见下文中第五节。其分支和类型转换语句均已被覆盖,若覆盖率已达到100%,结束测试;否则考虑变量的实际类型为基类本身的情况,如果基类为非抽象类,直接对其实例化,不然就对距离基类最近的非抽象子类生成实例化对象。对类对象的类型信息进行提取,除了在测试用例生成中起到了很大作用之外,在函数摘要的提取中也能派上用场。通过路径分析得到函数调用点处对象的实际所属类,从而得知动态执行时可能会调用哪些子类的方法,进而提取相应函数的函数摘要。先通过引用所属类对应的符号表项获取到方法的相关信息,如果该方法不能被重写,说明调用的就是引用所属类中的方法;如果方法可以被重写,就需要根据对象的实际所属类来判断。从实际所属类开始,由下往上查找该方法,直到找到该方法最新被重写的地方,即为后面会被调用执行的位置。现如今,许多研究人员都在思考具有更高测试用例利用率的自动测试用例生成方法,如通过约束求解来提高测试用例命中率。在面向过程程序的单元自动化测试领域,北京邮电大学的唐荣对C语言中非数值类型变量的抽象内存模型和约束提取算法进行了研究和设计,实现了支持非数值型测试用例自动生成的面向路径的约束求解测试。在面向对象程序的自动化测试领域,类虽然是重点研究对象,然而大部分研究工作都局限于单个类内部一个或多个函数间的测试,没有考虑到由于类的继承和多态等特性所导致的多个类之间的相互影响,也没有对函数内部的类型转换语句进行处理。北京邮电大学的陈江南在研究面向路径的类测试方法时,提出了类成员方法扩展控制流图生成算法,根据被调用函数所属类所在的继承体系,将完整路径分为基本子路径和实例化子路径两部分,所有可能的函数调用情况都作为实例化子路径配合分支节点添加到原有的控制流图中,两部分路径分别生成后再进行组合。陈江南的研究默认基本子路径不会涉及对类对象实际类型的约束,相当于为所有派生类对象生成取值。在这一方面,中国科学技术大学的黄双玲在4 实例分析为了验证前两节中介绍的操作语义模拟算法和基于路径的随机测试算法的可行性,接下来以图2中的被测函数为例,演示路径分析中抽象内存的变化过程,展示如何通过类的抽象内存建模提高函数的覆盖率。图2 商店进货的代码片段函数s)的输入参数包含Gtock(oods类的指针,且函数体内存在对变量的类型转换语句L2,oodsg它也是一条判断语句。初始时,已覆盖元素集合为空,L2尚未被覆盖,生成一条经过该条件表达式真分支的路径Path:L1->L2->L3。在路径的起始节点处,为指针goods在指针抽象内存区分配抽象内存单元Mp0,指针来源为输入参数,此处指针取值还无法确定,所以指针状态为NOT_SURE,处理完毕后抽象内存的状态如表9所示。表9 指针抽象内存区状态一virAddrnamesourceteypPTstateNOT_SURE犕狆0oodsPARMGoodsg投稿网址:www.sclkz.comjjy Copyright©博看网 . All Rights Reserved.中新建一块抽象内存单元M分析L——将指针g1语句的语义—oods所指对象p1,指针来源为局部变的两个成员weiht和ratio相乘,并将乘积与全局g。由变量totalWeiht相加的结果赋值给totalWeihtgg指针的约束提取算法可知,应为指针添加非空约束,且需要为指针指向的类对象创建类的抽象内存模型。类Goods对应的类结构抽象内存模型尚未被创建,为其在类的抽象内存区中分配抽象内存单元Mc0。为类对象创建类实例抽象内存模型,分配内,变量来源为参数成存单元Mcoodsg1,变量名为员,其实际所属类为G。为类对象goodsoods添加成员g,它们的数oods->weiht和goods->ratiog据类型分别为整型和浮点型,在基本抽象内存区中新建抽象内存单元Mnneiht为实例g0和M1。由于w变量,只与goods这个具体实例有关,将其添加到Mcatio为静态变量,与类有1的成员域中;而r关,且在类Goods中定义,因此抽象内存模型中存储的变量名为G::r,将其添加到Moodsatioc0的成员域中。最后,为整型变量totalWeiht新建抽象内g存单元Mn2,变量来源为全局变量,并根据表达式信息更新其符号值。执行完这些操作后,抽象内存的状态如表10~12所示。表10 指针抽象内存区状态二virAddrnamesourceMp0teypPTMc1stateNOT_NULLvirAddr表11 类的抽象内存区状态二virAddrMc0Mc1nameGoodsoodsgsourceDECLMEMMc0realCTemembersyp{Mn1}{Mn0}Mn0Mn1Mn2表15 基本抽象内存区状态三smboly_wgG_r_tw+gwG_rnamesourceteypvirAddrMc0Mc1Mc2表14 类的抽象内存区状态三nameGoodsoodsgFoodsourceDECLMEMDECLMc2realCTemembersyp{Mn1}{Mn0}{}第2期杜婉莹,等:单元自动化测试中类的抽象内存模型研究· 91·量。要使条件表达式结果为真,应使变量goods能够成功进行类型转换,对指针food添加不为空的约束。类对象goods的引用所属类和实际所属类均为Goods类,类Food是类Goods的子类,约束oods的实际所属类为位于更底层的Food类。为gFood类在类的抽象内存区中分配一块抽象内存单元Mccoods的类2,M1的实际所属类指向它。对指针g型转换不会改变它的取值,即所指类对象的地址,因此指针food应指向同一个类对象,Mpp0和M1的指针域均为Mc1。执行完这些操作后,抽象内存的状态如表13~15所示。表13 指针抽象内存区状态三virAddrnamesourceMp0Mp1teypPTMc1Mc1stateNOT_NULLNOT_NULLoodsPARMGoodsgfoodLOCALFoodoodsPARMGoodsgoods->weihtMEMINTgg::GoodsratioMEMFLOATtotalWeihtgGLOBINT分析L——将指针f3语句的语义—ood所指对象的表12 基本抽象内存区状态二virAddrMn0Mn1smboly_wgG_rnamesourceteyp两个成员weiht和ratio相乘,并将乘积与全局变量gtotalFoodWeiht相加的结果赋值给totalFoodg。指针f,检查它Weihtood指向的类对象为goodsg的两个成员weiht和ratio是否已经被添加。其中,gweiht为实例变量,已经被添加进类实例抽象内存g模型Mcratio为静态变量,在类1的成员域中;::r,在基Goods中定义,完整变量名为Goodsatio本抽象内存区中已经创建了相应的抽象内存单元Mnoods的实际所属类Food1,然而它并没有与g对应的类结构抽象内存模型Mc2建立关联关系,将 oods->weihtMEMINTgg::GoodsratioMEMFLOATtotalWeihtgGLOBINT_Mntw+gwG_r2分析L——将G2语句的语义—oods类的指针变量ood类的指针并赋值给局部变量oods向下转型为Fg,判断ffoodood是否为空指针,不为空指针的真分支继续执行L3。为指针变量food在指针抽象内存区投稿网址:www.sclkz.comjjyCopyright©博看网 . All Rights Reserved.的支持。本课题对C其添加进McotalTS中的符号表和抽象内存模型2的成员域中。最后,为整型变量tFoodWeiht新建抽象内存单元Mng3,变量来源为全局变量,并根据表达式信息更新其符号值。执行完这些操作后,抽象内存的状态如表16~18所示。表16 指针抽象内存区状态四virAddrnamesourceMp0Mp1teypPTMc1Mc1stateNOT_NULLNOT_NULL· 92·  计算机测量与控制 第30卷进行扩展,将类的操作语义模拟算法和基于路径的随机测试算法应用于面向C++程序的自动化测试工具CTS-CPP中,使CTS-CPP能够提供基于输入域的随机测试和基于路径的随机测试功能。51 实验环境本课题在CTS-CPP中完成测试用例生成模块,其运行于CentOS7系统中,JDK版本为1.8,使用Java语言在Eclise平台中开发,虚拟机最大内存设p置为2G。oodsPARMGoodsgfoodLOCALFood表17 类的抽象内存区状态四virAddrMc0Mc1Mc2nameGoodsoodsgFoodsourceDECLMEMDECLMc2realCTeypmembers{Mn1}{Mn0}{Mn1}52 实验内容为了验证本课题提出的模型和算法的可行性和有效性,本章对表19中的5个函数进行了基于路径的随机测试,记录测试过程中生成的路径和约束提取情况,并将测试结果同基于输入域的随机测试作比较。表19 5个被测函数属性工程名函数名代码输入类对类型转继承体代码总行变量象个换节点系中类行数数个数数个数个数232424769610111215134618469202712179128367230表18 基本抽象内存区状态四virAddrMn0Mn1smboly_wgG_rnamesourceteypoods->weihtMEMINTgg::GoodsratioMEMFLOAT_Mntw+gwG_rtotalWeihtGLOBINT2g_Mnfw+gwG_rtotalFoodWeihtGLOBINTg3t()7CoffeeMchoose()9ShoddThinpag)6MainAdnamicA(y)7SementjumTo(gp()5ComilinomileBpgcp对路径Path:L1->L2->L3分析完毕后,得到对函数s)的输入参数goods的约束信息,tock(即指针所指向对象的类型应为Food类或其子类。此处Food类为非抽象类,直接对其随机生成多个实例化对象,并将对象的地址传递给指针g。将输入oods变量g、oodstotalWeiht和totalFoodWeiht的随机gg值组合成多组测试用例,代入并动态执行后,根据探针函数的返回值更新已覆盖元素集合和未覆盖元素集合,计算覆盖率。发现可以达到100%,可知当前测试用例集合已满足测试需求,结束测试。53 实验结果为了展示类的抽象内存模型结合操作语义模拟算法是否能够成功提取路径中类相关的约束,得到类对象的实际所属类,以c)函数为例,执hoose(行基于路径的随机测试。c)函数的输入变hoose(量有函数参数c、b、toffeealanceime和所属类Shop的成员变量s、b、m、c,其中变量aleseanilkhococoffee是Coffee类的指针,Coffee类存在于继承体系、L、M、Wh中,是Instantatteochaite等众多类的公共基类。在函数内部有5个类型转换节点,对应4个覆盖元素,根据coffee指向的子类类型不同,会执行不同分支。其路径生成和约束提取情况如表20所示。同理,5个被测函数的路径生成和约束提取情况如表21所示。对程序进行静态分析,将变量、函数和类的基本 5 实验结果及分析代码测试系统(CTS,codetestinstem)是gsy一款面向C语言程序的自动化单元测试工具,它采用动静结合的方式,支持以函数模块为单元执行基于输入域的随机测试、边界值测试和面向路径的测试。CTS已经完善了对C语言类型系统的符号表、抽象内存模型和操作语义模拟算法的设计与实现。CTS-CPP是CTS的C++版本,在其基础上提供了对类投稿网址:www.sclkz.comjjyCopyright©博看网 . All Rights Reserved.表2()函数路径生成和约束提取情况0 choose序号覆盖元素路径序列coffee实esresso是否生成覆盖率是p际所属类实际所属类随机值否提高Coffee是是第2期杜婉莹,等:单元自动化测试中类的抽象内存模型研究· 93·___1ifhead261590-1-2-3-5-6-8-15-23-24-26-27-29-30-33Viennese-35-37-38-41-44-46-47-48-49-51-53-540-1-2-3-5-6-8-15-16-18-19-20-22-32-35-37-38-41-44-46-50-52-53-540-1-2-3-5-6-8-9-11-12-14-34-37-38-41-44-46-50-52-53-540-1-2-3-5-6-7-36-38-41-44-46-50-52-53-54MochaLatte或WhiteEsressop___2ifhead19151Esressop是是___3ifhead13144Esressop是是___4ifhead10140Esressop是是表21 5个被测函数路径生成和约束提取情况函数名()choose()addThing)dnamicA(y()umTojp)comileB(p生成路径个数47676约束是否成功提取是是是是是覆盖率是否提高是是是是是函数名表22 测试结果测试方式基于输入域的随机测试只为基类对象为所有派生类对象生成随机值生成随机值基于路径的随机测试测试用覆盖率测试用覆盖率测试用覆盖率例数量/%例数量/%例数量/%()2choose8()36addThing)2dnamicA(4y()28umTojp)2comileB(0p33.318.836.413.247.7561328812410010087.310075100404448605210087.310075100信息存入符号表中,生成路径后,在符号执行中根据类的操作语义模拟算法构建并更新类的抽象内存模型,对被测函数的输入变量中类对象的实际类型进行约束,根据分析结果为各个输入变量在其取值区间内生成随机值并由此得到测试用例集合,在动态执行后统计函数的覆盖情况,这就是基于路径的随机测试的主要流程。其通过对对象的实际所属类进行限定来避免生成无意义的测试用例,从而提高测试效率。如果不采取这一举措,也就是采用传统的基于输入域的随机测试的话,对于输入变量中的类对象,可以选择只为引用所属类生成实例化对象,也可以选择为引用所属类的所有子类生成随机值对象,使用这一方式虽然可以快速生成大量测试用例,但是其中的冗余对测试效率的影响不可小觑。为了更好地说明在对类的抽象内存模型进行研究后,提出的基于路径的随机测试相比于基于输入域的随机测试在提高测试效率方面的优越性,分别采用两种方式对5个被测函数执行自动测试,测试结果如表22所示。 54 结果分析由实验结果可知,如果执行基于输入域的随机测试,只对引用所属类的对象生成随机值得到的测试用例数量和覆盖率均不高;对引用所属类的所有子类对象生成随机值虽然能够得到较高的覆盖率,然而其生成的测试用例数量同样很高。与此相比,基于路径的随机测试通过对类对象的具体类型进行限定,能够以更少的测试用例达到更高的覆盖率。在大型程序中,测试效率的提高将会更为明显。综上所述,本课题提出的类的符号表能够提取出测试用例生成所需的类的基本信息,类的抽象内存模型和操作语义模拟算法能够成功记录路径中类对象的语义和约束信息,将它们应用于基于路径的随机测试中,能够得到满足需求的结构和内容均正确的测试用例,并且提高了对面向对象程序单元测试的测试效率。投稿网址:www.sclkz.comjjyCopyright©博看网 . All Rights Reserved.· 94·  计算机测量与控制 第30卷6 结束语本课题基于面向对象程序特性,对类的抽象内存模型进行研究,并由此提出了类的操作语义模拟算法以及针对单元测试的基于路径的随机测试算法的概念。类的抽象内存模型能够记录类对象的类型信息及其与各个成员之间的关联关系,考虑到多个实例可能对同一个静态变量产生影响,将类的静态成员与非静态成员区别开,分别存储在类类型的抽象内存模型和类对象的抽象内存模型中。使用类的抽象内存模型,不仅能够在符号执行中提取类型约束,缩小类对象实际类型的可选范围,还能在今后配合其他类别的抽象]26内存模型获取其各个成员变量的约束信息[,结合116.[]11ZHANGJ.Smbolicexecutionofrorampathsinvolypg//vinointerandstructurevariables[C]Proceedinsgpgofthe4thInternationalConferenceonQualitoftyS,:ware(QSIC).PiscatawaNJIEEE,2004:8792.y[]12ZHAOYS,WANGYW,GONGYZ,etal.STVL:imrovetheprecisionofstaticdefectdetectionwithp/smbolicthree-valuedloic[C]/Proceedinsoftheygg,18thAsia-PacificSoftwareEnineerinonferenceggC:,:LosAlamitosIEEEComuterSocietress2011pyP179186.[]王留帅.基于函数摘要的C++过程间静态分析研究13[D].成都:电子科技大学,2017.[]代子营.面向符号执行的内存模型研究[14D].长沙:国防科技大学,2009.[]方登辉.基于抽象语法树的代码静态缺陷检测工具开15发[D].北京:北京邮电大学,2018.[]庞新法.C++继承性剖析[],16J.价值工程,2014):233(1807208.[]靳乔乔,王静一,郭怡冰,等.浅析J17ava与C++的区别[]):6J.数码世界,2018(105.[]谭国律,王 波,刘 萍.程序设计中的静态元素18[]):37,J.电脑编程技巧与维护,2021(1015.[]唐 容.支持非数值型测试用例自动生成的抽象内存19建模技术研究[D].北京:北京邮电大学,2013.[20]KINGJC.Smbolicexecutionandproramtestinygg[]:J.CommunicationsoftheACM,1976,19(7)385394.[]21SANOGOS,MESSINE,FRéDéRIc.Desinofsacegp:thrustersatoolotimizationproblemsolvedviaapgyop]BranchandBoundmethod[J.JournalofGlobal.Op,,):201664(2273288.timization[]徐正威,周 琼,许 珂,等.浅谈J22ava与C++中的内存管理[]:J.网络安全技术与应用,2016(3)5051.[]侯 勇.C++数据类型转换方法及其应用[]23J.电脑与电信,):62010(4465.[]王廷永,黄 松.测试用例自动生成技术综述[]24J.电子技术与软件工程,):52021(18153.[]于 航.单元测试中抽象内存模型优化技术研究25[D].北京:北京邮电大学,2019.[]李飞宇.基于内存建模的测试数据自动生成方法研究26[D].北京:北京邮电大学,2013.约束求解实现更为精确的面向路径的测试。参考文献:[]龙高贵.谈软件工程中软件测试的重要性及方法[]1J.电脑迷,):2,2017(8159.[]陈和平.面向对象的自动化单元测试[2D].武汉:武汉理工大学,2004.[]赵良福,王世签,郑科鹏.软件自动化测试研究[]3J.有线电视技术,,2):920185(6597.[]王雅文,宫云战,杨朝红.软件测试工具综述[]4J.北京化工大学学报(自然科学版),2:1007,34(s1)4.[]刘 芳.面向对象自动化单元测试技术研究[]5J.现):2代计算机,2020(14126.[]岳青玲.J]6ava面向对象编程的三大特性[J.电子技术与软件工程,):22019(2439240.[]吴晓琴.浅析面向对象程序设计特点[]7J.安徽大学学报(自然科学版),):32002(3337.[]黄双玲.面向C/8C++程序函数调用关系的静态分析方法研究[D].合肥:中国科学技术大学,2015.[:ac9]GOTLIEBA.Euclideonstraint-basedtesting//frameworkforcriticalCprorams[C]Proceedinsofggthe2ndInternationalConferenceonSoftwareTesting:IEEEComVerificationandValidation.LosAlamitos,uterSocietress2009:151160.pyP[]10XUZX,ZHANGJ.Atestdatagenerationtoolforu//nittestinfCprorams[C]Proceedinsofthe6thgoggInternationalConferenceonQualitoftware.LosyS:,AlamitosIEEEComuterSocietress2006:107pyP投稿网址:www.sclkz.comjjy Copyright©博看网 . All Rights Reserved.

发布者:admin,转转请注明出处:http://www.yc00.com/news/1688020723a67407.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信