软件边界测试的典型案例分析

2021-12-18 13:42李莉张青
电脑知识与技术 2021年31期
关键词:堆栈数组边界

李莉 张青

摘要:软件的安全性和可靠性在今天越来越受到重视,由于软件边界值处理不当引起的问题层出不穷,该文结合若干边界测试的典型案例,从循环边界、数据值边界、数据量边界、状态转换边界等多个角度阐述软件相关边界问题产生原因,总结软件中的边界处理要点,为软件设计提供参考。

关键词:软件测试;边界测试

中图分类号:TP311      文献标识码:A

文章编号:1009-3044(2021)31-0132-03

1 边界测试概述

随着大数据和人工智能时代的来临,各种软件在人们的工作和生活中承担的任务越来越重要,随之而来,对软件的可靠性要求也越来越高。软件测试是保障软件安全可靠性的一种重要手段,测试类型从最初的功能测试,扩展和细化到现在的功能、性能测试、数据测试、接口测试、边界测试、余量测试、安全性、可靠性测试等等众多类型。

由测试数据统计得知,大量的软件错误是发生在输入或输出的边界上,而不是发生在输入输出范围的内部[1-2],但是在软件设计和程序编写过程中,设计师常常对需求中的输入或输出边界重视不够,导致出现各种错误,因此针对各种边界情况开展测试,我们可以查找出更多的软件错误[3]。

2 边界测试方法

边界值分析是边界测试的主要测试方法,它是对等价类分析方法的一种补充。开展软件边界测试首先需要确定边界情况,然后选取正好等于、刚刚大于或刚刚小于边界的值作为测试数据,而不是选取等价类中的典型值或任意值作为测试数据[4]。常用的边界值分析方法有三点法、五点法、七点法等等,分别针对一至多个边界点,选取相应边界值开展测试,原理比较简单。

3 边界测试点选取

一旦边界点选定,相应的边界值也随之确定,测试数据也顺利生成,看上去非常简单。但是实际操作中,边界问题还是层出不穷,其原因就在于:

1)设计师并未意识到当前数据是有边界要求的;

2)有些边界要求不体现在软件文档要求中,而是随着设计师的程序编写过程不断产生的;

3)需求隱含了一些功能边界要求,但是这些要求需要设计师在领会整个系统流程的基础上总结概括得出,如果对系统理解不全面,可能会漏掉对相关边界的处理。

综上所述,对于软件测试人员来说,边界测试的重点在于寻找被设计师忽略或理解错误的数据点。因此,边界测试的难点不在于测试执行,而在于测试对象即测试点的发现和选取。

通常,软件边界测试分为数据值边界和数据量边界:数据值边界是指有明确边界要求的数据,这些数据有些在软件需求规格说明或者详细设计中特别提出,有些是程序内部自定义数据,需要根据其含义自行界定其边界;数据量边界包括数据长度边界、数据容量边界(存储区容量、堆栈容量等)、通信通道容量边界等等,这些边界要求通常隐含在接口说明或硬件说明中;还有一些边界要求并没有在文档中出现,需要测试人员结合软件文档和程序上下文推导得出。

在这些显性或隐性的边界点的处理上出现了不少软件问题,下面我们结合具体案例介绍。

4 边界测试典型案例分析

4.1 循环边界

循环边界是比较常见的测试边界,通常包括:

1)有明确要求的循环次数;

2)与时序有关的循环。

案例1:

需求要求某个操作循环执行3次。

循环变量初始值times=0,软件实现如下图:

从图中代码可见,由于while判断times终止值为3,显然循环次数已达到4次,超过3次循环的要求。

这种循环数据边界的问题在单元测试中是频发问题,设计师在编写循环处理语句的时候需要严格对照需求的要求,特别注意循环的起始值和结束值的处理,以避免循环次数超限。

案例2:

需求要求每20ms执行子程序Calu_20(),采用前一拍引力进行当前拍位置计算,程序初始值Gx0,Gx1的值均为0。子程序实现如下图所示:

由以上程序可得:

第1拍20ms当前位置PX1计算,使用的Gx0值为初始值0;

第2拍20ms当前位置PX1计算,使用的Gx0值为第1拍中Gx1赋予它的值,也是0;

第3拍20ms 当前位置PX1计算,使用的Gx0值为第2拍中Gx1赋予它的值,即Gx0=Gx0_1_Step;

由分析可知,由于语句②的位置错误,导致当前位置PX1计算时使用的其实是前2拍的引力值,程序应将语句②放在语句①之前执行,才能保证时序的正确。修改后的程序如下图所示:

在嵌入式软件中,常常用中断去执行一些与时序有关的计算或控制,定时中断由于定期不断执行,因此我们可以把它看作是一种特殊的循环。此时,我们需要格外注意从上一次中断到下一次中断的切换执行,通常时序错误都发生在切换的边界。例如上面这个例子,如果2拍引力值的偏差较小,这种错误很难在动态测试中发现,通常只有通过代码走读才能分析得出。

4.2 数据域边界

数据域的边界一般包括:

1)数组范围的边界;

2)数据类型的边界。

案例3:

软件需求要求程序采集每20ms电压测量值,通过累积每20ms的电压差值,计算得出2s电压差值,程序实现如下:

由以上程序可知,数组DY[]中存放的是每20ms的电压差值,程序需要计算的是2s累计的电压差值,共100个差值就应该涉及到101个电压测量值。但是由于程序将电压测量值数组DY[]大小定义为100,所以该数组大小不够,应定义为101个元素。此外,程序循环到i=99时,DY[]数组下标已引用到100,而数组的下标最大应该比数组大小小1,因此,此处对数组的引用已溢出。

在数组的应用上,出错频率较高的是数组下标边界,特别是当下标用作循环变量时,设计人员经常容易忽略其范围要求而超范围使用下标。

案例4:

软件运行环境为TMS320C5416,是16位的定点DSP,其中一段程序实现门限的计算,具体见图5:

在16位定点DSP中,Unsigned int类型数据表示范围为0~65535,这段程序用到的三个变量都是Unsigned int类型。

设置PRI=90,Δd=50,则程序运行计算时,算到20*PRI*Δd时,中间结果20*PRI*Δd的计算值已达到90000,超过了Unsigned int表示的最大范围,数据溢出,中间结果由90000变成了24464,再经过/200的运算,最后计算结果为122,程序实现错误。

这是一个典型的白盒数据边界测试问题,此处进行计算的代码运算执行顺序是从左到右,因此导致中间结果溢出。对于不同的编译器,程序的运算顺序可能有所不同,因此无论是软件设计人员还是测试人员,都应当深入了解程序运行环境,深刻理解每种数据类型的表示范围,避免数据超出类型表示范围边界。

4.3 数据量边界

数据量边界通常与硬件相关,一般包括:

1)存储区容量边界;

2)堆栈容量边界;

3)通信通道容量边界;

4)信号有效范围边界。

案例5:

这是一个非常著名的案例,丰田汽车不响应刹车而失控爆冲,该事件后有软件专家对其控制软件进行了测试,以下是其中部分软件缺陷描述:

丰田的软件系统有两块相邻的内存块。第一块内存区域存储所有任务以及任务的运行状态,称为“堆栈(Stack)”,大小为4KB。与“堆栈”相邻的内存中储存了操作系统进行任务分配的记录。在某些情境下,如果任务及任务的运行状态数据很多,那么会往堆栈里写入太多东西,如果大小超过4KB,那么就会错误地写入相邻的内存块,即任务分配表,这种错误被称为“堆栈溢出”。可以想象,一旦出现堆栈溢出,任务分配表内容会被改写,系统就会错误地分配任务,造成任务内容、执行次数的错乱,甚至某些任务直接被忽略[5]。

这是一个典型的堆栈使用超边界问题,这些问题的产生通常是在软件的系统规划和设计阶段没有对后期使用作充分评估,导致内存分配不够引起的。类似的存储容量、通信通道容量等也应当在系统设计初期就做好规划,否则一旦使用中超出其容量边界,会引起整个系统瘫痪等致命故障。

4.4 状态转换边界

在软件运行过程中从一个状态切换到另一个状态也是一个重要的边界。例如:有些软件分阶段运行,包括测试态和正式状态,两者会调用一些相同的函数,靠外部信号来进行状态转换。还有一些软件,执行时有明确的运行状态,各状态分工清楚,切换时机明确。

案例6:

某飞行软件所控制的飞行阶段明确分为一、二、三级,一级关机后进入二级飞行段,二级关机后进入三级飞行段。在程序中,每级关机会读取三次关机信号,分别存储于三块不同地址的内存中,程序需要对这三个地址中存放的关机信号进行三取二的可靠性判断。由于一、二、三级飞行按顺序进行,不会并行,因此设计师复用了三个地址存放三个级别飞行时段的关机信号。

需求要求一级关机的条件是收到0xA信号;二级关机的条件是收到0xB信号;三级关机的条件是收到0xC信号。

测试人员在一级关机时给出三个值为0xA,0xB,0xA,一级顺利关机,进入二级飞行阶段。一级转二级时,程序没有将三个地址的数据清零,因此转二级飞行时,内存中三个值为0xA,0xB,0xA,进入二级后,测试人员给只给第一个地址赋值0xB,内存中三个值为0xB,0xB,0xA,经过三取二,得出当前已收到0xB信号的结论,因此二级关机——但此时实际上程序刚收到一次关机信号,另两次关机信号还未发出。由于状态转换边界处理不当,程序发生误判,导致提早关机。

状态转换时涉及到的信息处理工作很多,一不小心就会有遗漏,导致程序出错。因此,设计师应关注状态转换边界,查看程序状态转换时涉及到的数据和控制信息,避免发生错误。

4.5 输出边界

软件的边界测试不仅关注输入边界和硬件使用边界,还应结合外部接口要求,考虑输出数据和信号的边界。

例如:

1)DSP和FPGA交互时,向对方输出的数据是否有值域要求。

2)软件向硬件发出一些信號信息时,考虑硬件是否有特殊要求,比如限幅等。

5 结束语

软件在计算机系统中所占比重越来越大,相应的软件面临的风险也越来越多,本文结合典型案例将软件测试过程中发现的各种边界问题进行了总结和归纳,为软件设计和测试人员提供参考,以避免软件边界问题,增强软件的可靠性。

参考文献:

[1] 王轶辰,殷永峰,刘斌.航电设备软件系统测试过程研究[J].测控技术,2004,23(8):53-55,64.

[2] Jorgensen P C.软件测试[M].韩柯,杜旭涛,译.北京:机械工业出版社,2003.

[3] MOLLY_CICI.边界值分析法--测试用例设计方法[EB/OL].[2020-10-18].https://blog.csdn.net/molly_cici/article/details/102626757.

[4] 刘畅,王轶辰,刘斌,等.软件边界组合测试的典型案例分析[J].计算机工程与应用,2009,45(20):74-77.

[5] SCHWARZ.丰田栽了的原因[EB/OL].(2013-11-03)[2021-09-27].http://www.amobbs.com/thread-5557598-1-1.html.

【通联编辑:谢媛媛】

收稿日期:2021-06-20

作者简介:李莉(1978—),女,江苏启东人,高级工程师,硕士,研究方向为软件工程、软件测试、软件开发技术;张青(1979—),男,江苏启东人,高级工程师,硕士,研究方向为软件工程、软件研发。

猜你喜欢
堆栈数组边界
JAVA稀疏矩阵算法
拓展阅读的边界
JAVA玩转数学之二维数组排序
论中立的帮助行为之可罚边界
嵌入式软件堆栈溢出的动态检测方案设计*
基于堆栈自编码降维的武器装备体系效能预测
Excel数组公式在林业多条件求和中的应用
寻找勾股数组的历程
“伪翻译”:“翻译”之边界行走者
思考新边界