C程序自动测试方法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C程序自动测试方法
【摘要】针对C语言的特点,提出了在Win XP/NT平台上对C源程序进行实时测试的原理、方法。在程序控制流适当的地方插入一探针函数调用,实时收集程序运行时刻信息,研究的结果对程序员的测试有极大的帮助,为程序优化提供了大量有用的信息。
【关键词】自动测试;静态测试;算法
1问题的提出
随着装备自动化程度的不断提高,计算机的应用越来越普遍,为了提高软件开发的效率、可靠性,必须用一种系统的方法对开发的软件进行评估,度量其可靠性,并自动对软件进行测试,找出软件中存在的缺陷或错误。C语言作为一种高级开发语言,具有通用性好,编程效率高,编程灵活,移植性好,因此C语言被选为各种装备软件开发的重要语言之一。装备的可靠性、可用性对软件的可靠性要求越来越高,如何度量软件的可靠性、对软件进行自动测试的任务迫在眉睫。正是为了提高软件的可靠性,对C语言编制的软件进行自动测试,以期找出软件中潜在的错误和缺陷,并协助程序员修改错误,提高软件的质量和开发效率。
对C语言编制程序进行控制流分析,并在源程序的适当地方插入一函数调用,使其在运行时刻收集程序的运行信息。帮助程序员设计测试用例,显示程序的运行过程,判断程序的执行情况,协助其改正错误。测试程序可作为软件测试的一种工具,将提高测试效率,保证软件的质量,把程序员从低级的、重复的劳动中解放出来,将主要精力放在软件的开发和设计上,成倍地提高生产率[3] [6]。
2自动测试目标和算法
2.1自动测试及其目标
基于被测试程序是否执行,可以把软件测试分为静态测试和动态测试。静态测试只分析被测试程序,如包含哪些语句,哪些函数或模块,函数之间的调用关系,标识符的引用关系等。而动态测试则收集程序运行时刻信息:如哪些路径被执行,每个路径执行的时间,每个变量在某一时刻的值,每个分支被执行时的条件等[4][5]。
动态测试的一般方法是,在被测试的程序里适当的地方插入信息收集函数(或称探针),再对源程序进行编译、运行,当程序运行到收集函数时,由收集函数往数据库中更新内容,然后由一个事后处理函数对数据库进行分析、统计、显示[2][9]。
需要完成以下目标:以WinXP/NT作为软件运行的平台,采用GUI(Graphics User Interface),针对VC6.0+的程序进行测试,分析出控制流图,并在屏幕上画出控制流图,实时跟踪控制流图中哪些弧被经历过,经历的次数是多少,每次经历的时间是多少;显示每个节点对应的源代码;当前运行的代码加亮显示;源代码中的关键字、注释醒目地显示等[1]。
2.2动态测试的算法
编程语言采用Delphi,数据库选单机版的Paradox。
算法思路
自动对VC6.0+的.DSW(Develop Studio Workshop)文件进行分析,从.DSW文件中分析出它所包含的工程文件.DSP(Develop Studio Project),一个.DSW文件中可能包含多个.DSP文件。然后逐个对.DSP文件进行分析,找出每个工程文件中包含的.C、.CPP文件,再对.C、.CPP文件逐一进行分析。在对.C、.CPP文件进行分析时,首先找出每个文件中所包含的函数,然后对每个函数进行分析。在分析过程中,边分析,边记录,同时在函数的适当地方插入探针[7][8]。
(1)dsw、.dsp文件分析
.dsw、.dsp文件为文本格式,用任何编辑器打开均可阅读其内容,稍加浏览即可明白其格式,不在此赘述。
1).dsw文件分析
a.从.dsw文件中分析出.dsp文件名
b.分析.dsp文件
c.重复1)直到所有的.dsp文件分析完毕
2).dsp文件分析
a.从.dsp文件中分析出.C或.CPP文件名
b.分析该文件
c.重复1)直到所有的.C或.CPP文件分析完毕
(2)C或.CPP文件分析
1)将源文件切分为一系列的Token串,存入一表中
2)从Token表中过滤掉注释部分,如/*…*/、//…
3)从Token表中过滤掉”…”部分,并考虑串中可能存在转义字符“\””。
4)从Token表中搜索并计算下列关键字所处的行、列,并存入另一表List 中:break、case、continue、default、do、else、for、goto、if、return、switch、while、{、}
5)从List表中搜索并处理goto关键字,并把goto的目的地址(行、列等信息)仍存入List表中,相关信息存入goto预处理表中
6)将List表按行、列的升序排序
7)对List分析得到控制流信息,在分析时,在源程序的适当地方插入探针。
(3)源文件Token化
利用了从Internet上收集到的一个控件TTokenList,设置好该控件的属性:1)与源程序对应的流式文件TFileStream的一个实例;2)分隔符属性,其设置方式是将布尔数组下标0~255对应的单元初始化,每个单元和一个ASCII码对应,若某个ASCII码为分隔符,则以该ASCII码的序号为下标,该下标对应的单元设置为true
1)指针指向Token表头
2)判断是否为/符号,若是转3),否则指针+1,重复2)直到Token尾部结束。
3)判断是否为*,否转5)
4)对/*…*/进行处理,处理完后转2)
5)判断是否为/,若是转6),否则转2)
6)处理//…直到换行符,处理完后转2)
(5)滤掉”…”部分
为了不影响对关键字的判断处理,还必须过滤掉”…”部分
1)指针指向Token表头
2)是”符号吗?是转3),否则指针+1,重复2)直到Token 尾部结束。
3)若是\字符,判断下一字符是否为”,若是则虑掉这两个字符,否则下一字符为”时结束过滤,转2)继续
(6)搜索关键字
因关键字有多个,若把每个Token和所有的关键字进行比较,将十分费时,因此,笔者考虑了一种较为有效的方法。一般编程语言中均提供了在某字符串中搜索字串的函数,若能成功匹配,返回其位置,否则返回-1或其它的值。但存在一种情况:Token中的串是关键字的子串,该如何处理这种情况?笔者的解决办法是:把每个关键字按升序排序,把所有的关键字串结成一个串,每个关键字之间插入分隔符,分隔符是关键字中所包含的字符以外的其它任意字符。为了简化处理,在串的头部和尾部也加上分隔符。因此,若某个Token为该串的子串,根据返回值,判断子串的头部和尾部是否同时为分隔符,若是则是一个关键字,否则仅为一般标识符。这种方法避免了采用关键字树等复杂的数据结构和算法,编程较为简单。笔者查看了Delphi中Pos函数的源代码,它采用了汇编代码,所以其运行效率十分高[3]。