时间:2022-04-26 00:49:09
引言:易发表网凭借丰富的文秘实践,为您精心挑选了九篇单元测试方法范例。如需获取更多原创内容,可随时联系我们的客服老师。
关键词:遗传算法;模拟退火算法;自动化;单元测试
中图分类号:TP311.53
随着计算机技术的发展,计算机智能技术也逐渐得到了开发应用,生物智能、人工智能以及算计智能的联合应用和优势互补,使智能技术的应用更加有效。随着计算机的普及,软件产品已经深入人们生活工作的各个领域,成为日常工作、生活、娱乐的必不可少的组成部分。而对于软件安全性能的要求则在很大程度上促进了软件测试的发展。软件测试是软件安全性能和良好的使用性能的重要哦保证,贯穿于软甲开发过程的始终,保证软件开发每个阶段的质量。
软件的质量需要经过软件功能测试才能得到保障,而单元测试则是软件功能测试的基础和前提,是软件测试的起步环节。单元测试针对的对象是程序中最小的软件模块,一般是软件开发人员通过编写小段代码,针对被测试代码的某个较小较明确的功能进行测试,看其是否可以正常运行。
1 参数化单元测试
单元测试作为软件测试的起步环节,同时也是不可或缺的环节,对软件的质量起着至关重要的作用。在实际测试中,单元测试代码的手动编写工作是一件极其复杂且耗时的工作,并且所选测试实例不能保证覆盖较大的代码,具有很大的随机性,进而降低单元测试的效率。
参数化单元测试将程序规格与测试用例生成分离,解决了传统单元测试存在的弊端。运用参数化单元测试方法,程序要实现的功能需要人工书写代码,然后测试工具就会通过对测试代码的分析和检测,自动根据测试的实际路径生成对应的实例和测试代码,实现代码的高覆盖率。
2 基于遗传算法的搜索策略
在退火算法的运行过程中溶入遗传算法,称为退火遗传算法,依旧是说,所谓的退火遗传算法,实际上是由退火算法和遗传算法两个部分组成,结合双方各自的优点和特性,所得到的新的综合性计算方法。
2.1 遗传算法依据
遗传算法的提出源于计算机发展初期提出的所谓“人工进化系统”,它是根据生物进化的特点,借鉴优胜劣汰的自然遗传法则,参照达尔文进化论的理论思想而形成的一种不依赖具体问题的直接搜索方法,在运用遗传算法进行数据计算时,不仅要用到进化学的概念,同时也要符合遗传学说的基因遗传原理。
运用遗传算法进行计算时,一般要经过几个基本步骤,即:初始化数据、数据的择优选择、随机对选中的两个数据进行交叉互换、根据遗产学说的基因变异原理所进行的个体数据变异、全局最优收敛,进而得出需要的结论或数据。
2.2 模拟退火算法依据
模拟退火算法是根据固体退火过程和组合优化问题之间的相似性而提出的。在对物质进行加热处理时,物质组成中粒子之间的布朗运动加强,当加热到一定程度时,温度达到物质熔点,固体物质会转化为液体形态。这时,对物体进行退火处理,使温度降低,则物体的粒子运动减弱,并且会逐渐趋于平衡和有序,最终达到物质性质的稳定。
模拟退火算法运用温度参数进行控制,当温度较高时,数据运动变化剧烈,从而使解的区间变化较大,容易接受到较差解;当温度降低,数据运动逐渐减缓时,解的区间也会逐渐趋于稳定,这时候就可以得到较为优良的解果,从而对遗传算法的不足进行弥补。
2.3 退火遗传算法依据
退火遗传算法,是指以遗传算法为主要运算方法,并在运算过程中引入模拟退火算法,使两者达到优势互补,进一步对群体进行优化调整。退火遗传算法可以分为两个组成部分:首先,运用遗传算法的进化理论,产生一个相对较为优良的群体,然后利用模拟退火算法,对群体中的个体进行优化和调整。
(1)针对遗传算子进行改进
所谓遗传算子,是指在遗传算法中,用来维持遗传多样性所使用的算子,遗传多样性是生物或数据演化过程中不可或缺的一个必要性质,遗传算子在遗传算法中类似于自然中的适者生存原则,对于个体的进化会产生巨大的影响。
初始进化阶段,为了保持种群的多样性,便于从中进行选择,应该加大对于个体间相互交叉和互换的概率;在进化的终极阶段,频繁的交叉互换不利于种群的稳定和最优解的产生,因此需要适当地减小个体间的联系和活动,减少最优解的求解难度,缩短求解过程。针对种群中的个体而言,在进行变异操作时,对优势个体进行较小的变异,劣势个体进行较大的变异,可以使其更加趋近于最优解。
(2)合理构造适应值函数
适应值函数可以针对遗传算法的求解过程进行指导,对最优解的数值区间进行限定,在适应值函数的构造过程中,引入关键分支的概念。关键分支,指在选定的路径中,对存在的结点的真实性进行判定,求解过程可能会在这些结点处产生偏离,引发错误,而这些会导致求解过程偏离目标路径的结点,就是关键分支。
适应值函数在遗传算法中是用来区分个体优劣的标准,是进行自然选择的唯一依据。原始适应值函数是对问题最初求解目标的反映。适应值对个体的判断有两个截然相反的情形:适应值越大,个体性能越好和适应值越小,个体性能越好。在遗传算法中,对适应值函数是有限制的,即适应值函数必须为非负数,这就需要选择较大的适应值函数来选择较为优良的个体。
为了使被测数据中每个参数都可以得到评估,根据相关数据对判断结点进行数据转换,在保证个体数据得到充分计算的情况下,不会对程序主体造成破坏
3 实验结果与分析
为了对退火遗传算法的性能进行验证,采用判断三角形的相关测试程序,将退火遗传算法与单纯的遗传算法进行对比,对进化每一代的最大适应值进行记录。
从实验数据可以看出,初始进化阶段,个体的产生具有随机性,在对实验进行多次运行后,可以看出,最高适应值之间差异十分明显。进化过程初期,两种算法的最高适应值都存在较大的波动,而随着遗传的不断进行,退火遗传算法的最大适应值范围逐渐趋于稳定,而遗传算法的最大适应值范围仍不稳定。因此可以得出结论,将模拟退火算法与遗传算法相互配合,可以有效避免单一遗传算法的不足,加快对最优解的计算速度,减少计算所需时间。根据实验的数据,对多次实验的结果进行统一总结,可以看出,相对于单一的遗传算法而言,退火遗传算法的进化速度大大加快,减少了计算时间。
4 结束语
经过实验和分析,我们可以看到,生成高代码覆盖率的测试用例是自动化测试的关键问题,是提高自动化测试性能的主要手段。针对遗传算法存在的缺陷,将遗传算法和模拟退火算法相互结合,实现优势互补,针对群体数据中的遗传算子以及适应值函数作出改进,最终通过对比实验,验证了退火遗传算法的有效性和优越性。
参考文献:
[1]赵慧娟,孙文辉.基于退火遗传算法的单元测试方法[J].计算机工程,2013,39(1):49-53.
[2]杨学红.自动化单元测试概述[J].信息通信技术,2012,(1):66-68.
摘 要:随着汽车电子市场的快速发展,汽车控制器的电子控制单元(ECU)已越来越多,对ECU的功能测试也变得日趋复杂。为解决车载ECU功能测试,研究了基于控制器局域网络(CAN)的ECU自动测试方法。以NI公司的软硬件为开发平台、CAN总线为通信平台搭建测试系统与被测ECU形成闭环结构。通过CAN总线传输测试信息,可实现对同型号ECU的批量测试。此系统采用了新的测试方法来降低测试误差,并支持ECU的流水线测试,大大降低了测试的复杂度,减少了工作量。同时,在完善仿真信号产生模块和测试模块用例库后,也能适用于其他类型ECU的功能测试。
关键词:
控制器局域网络;电子控制单元;批量测试;汽车电子;车载网络
中图分类号: TP206.1 文献标志码:A
Abstract: With the rapid development of automotive electronic market, more and more Electronic Control Units (ECU) for vehicle controller appear and the functional test also becomes more complex. In order to solve the problem of ECU functional test, the ECUs automatic test method based on Controller Area Network (CAN) was studied. The system included the software and hardware platform of National Instrument (NI) and communication platform of CAN bus, by which the system and ECU formed a closed-loop structure. To transmit the test message through CAN bus, the system could achieve batch test of ECUs with the same type. By using the new test method, the system can reduce the test errors, and support assembly line test of ECU, which greatly reduces the complexity of ECU functional test and test work. At the same time, the system can also apply to other types of ECU functional test by improving the generation module of simulated signal and use case library.
Key words: Controller Area Network (CAN); Electric Control Unit (ECU); batch test; vehicle electronic; vehicle network
0 引言
随着汽车电子的不断发展,汽车已进入电子控制时代,其标志为电子控制单元(Electric Control Unit, ECU)的广泛应用。现如今,车辆上电控单元数量不断增加,功能越发复杂,多个处理器之间相互连接、协调工作并共享信息构成了汽车车载互联通信网络。其中控制器局域网络(Controller Area Network, CAN)是汽车中应用较多的现场总线。其良好的实时性、可靠性和经济性能很好地满足汽车ECU之间数据通信的需要,已成为最有发展前景的现场总线之一[1-2]。因此,带CAN总线功能的ECU测试也将变得更加复杂。ECU功能测试属应用层功能测试范畴,是为了检测ECU是否符合给定的协议规范,能否进行正常的控制工作。这种测试在系统级开发中占据了很大的比重,成为应用层测试中最为关键的部分[3]。
在传统的ECU功能测试中,一种方式是利用测试面板产生ECU各种信号后连接到ECU各输入引脚,触发它的各驱动模块进行控制工作,有专门的线路负责数据交换,但这样的测试系统随着传感器数量的增多,连线非常困难,且需要高速的数据采集和信号调理设备,使整体成本增加[4-5];另一种则改进了信号的产生方式,即通过虚拟仪器模拟ECU的控制信号来代替传统的触发信号,采用人工对控制效果进行直接的观察和记录。这些测试方法都加大了测试过程中的测试误差、复杂度和测试工作量,且无法进行自动测试和结果的自动生成,也不能同时对多个ECU进行测试,给ECU厂商进行批量生产时带来很大的不便。
由此,引发了对新的测试方法的思考和探索。基于CAN总线的ECU功能测试方法以CAN总线的传输作为关键技术,采用闭环测试方法对同型号的ECU进行自动和批量测试。
1 基于CAN总线的ECU功能测试介绍
车载控制系统主要任务就是要解决车身电器设备的功能性问题,所以,首先应关注ECU是否能实现功能上的控制,即测试其是否满足控制协议的要求。ECU在控制功能上包括了通信服务功能、传送数据功能、诊断信息及标定信息功能、设备监控和网络管理功能等,具体的要求规范则由各ECU生产厂商自行制定。
目前应用层协议制定分为以测试为重心的模式和以设计为重心的模式。不论哪种模式,控制器开发过程中,都需要通过测试来验证功能的正确性,确定ECU工作正常并不干扰总线正常通信[6]。
由图1的控制器开发“V”模式图可见,控制器开发过程包括多个环节,其中的应用层功能测试是其重要组成部分,它包括ECU功能测试、网络管理功能测试、故障诊断测试等,是进行实车测试前的重要环节。在引入CAN总线后,将大大降低ECU功能测试的复杂度和测试工作量,是CAN总线测试的重要组成部分[7]。
在基于CAN总线的ECU测试系统中,通信网络是进行数据传输,实现各模块协调工作的桥梁[8]。利用LabVIEW[5,7,11]虚拟仪器产生仿真信号代替数据采集卡采集的真实信号,并在此基础上引入CAN总线作为测试的关键技术,充分发挥CAN总线在传输上的高可靠性和实时性等优点。通过总线对仿真信号的测试报文进行有效传输,如表1所示。
表1中:Message表示报文名称;ID表示报文仲裁场;DLC表示报文长度;Data表示报文数据。
将报文与同型号ECU进行连接,形成闭环测试结构,模拟实车中ECU的各种传感器信号来驱动其进行控制工作(于3.2节详细描述),将仿真报文数据和CAN总线上反馈回来的ECU控制报文数据进行解析,提取出Data的值,并自动进行多次对比和测试后,在人机界面上对测试结果和各种信号量进行直观显示,并利用测试结果自动生成测试报告,优化和改进了传统的测试方法。
2 设计方案
此方法采用仿真信号序列代替采集卡采集的真实信号,利用CAN总线的特点对数据进行传输,并将整个测试构建成闭环结构,大大降低测试的复杂性。
2.1 方法总体框架
由CAN2.0协议可知,CAN报文的基本要素是报文ID、周期和信号与消息的映射关系。因此对ECU的协议功能测试,主要任务就是测试ID、消息周期、确定信号与消息的映射关系是否满足要求,并测试在循环执行多次之后,ECU是否具备在控制功能上的稳定性[8]。
选用以LabVIEW为软件平台实现ECU的功能测试。测试系统整体框架包括三部分:上位机仿真和测试、CAN网络和底层待测ECU模块。如图2所示。
工业计算机仿真给定ECU的各种信号量,驱动ECU进行控制工作。由于各ECU之间是相互独立的,“测试与结果显示模块”采集不同ECU广播的控制信息,并通过ID对它们进行识别。对采集到的控制信息进行分析、对比原始输入来判定各个ECU在功能控制中是否满足协议要求。
具体测试方法如下:
首先,通过上位机LabVIEW模拟仿真信号(如:转向灯信号、温度信号等),通过NI 6259板卡,与待测ECU各引脚进行对接;
然后,发送仿真信号,驱动ECU进行控制工作,并发送出相应的CAN控制信息;
再次,通过NI 8473s板卡与上位机LabVIEW进行对接,接收采集到的CAN报文,并通过LabVIEW实现报文的解析、处理和ECU控制效果的同步显示;
最后,把原始仿真数据和处理后的数据进行对比,验证ECU在功能控制上是否满足预期效果,并对以上测试步骤循环多次,得出测试结论,生成测试文档。
在此,根据测试大纲要求,选用一个由实验室和整车厂联合开发的ECU作为应用实例,仿真信号由模拟信号和开关量信号组成,主要分为:转向灯信号、报警信号、状态信号、门信号、温度信号和压力信号控制信号。具体的控制量与变化范围因测试ECU功能要求进行定制化处理。测试ECU仿真控制信号如表2所示。
2.2 软件设计流程
上位机软件整体分为7部分:虚拟仪器配置、模拟信号仿真、同步信号显示、测试结果显示、系统数据判断、数据处理、测试报告生成。模块示意图如图3所示。
1)虚拟仪器配置。对测试时使用的板卡进行初始化配置,设定参数和使用通道。
2)模拟信号仿真。产生ECU仿真信号(如转向灯信号,水温信号等)。
3)同步信号显示。将采集到的CAN报文,进行处理之后,在人机界面上进行控件显示,方便测试者进行直接观察和分析。
4)测试结果显示。在人机界面上进行测试结果的显示,以表格和BOOL数组的形式显示出每个信号在多次测试之后的通过情况。
5)系统数据判断。将处理后的CAN报文数据与预先保存的仿真信号数据进行对比,得出测试结果。
6)数据处理。处理NI 8473s板卡采集到的CAN报文,提取数据信息。
7)测试报告生成。在人机界面上显示测试结果后,将测试结果以网页(.html)格式的文档进行保存,便于后期的分析和处理。
软件设计流程如图4所示。
3 系统分析
由图2测试方法总体框架图可知,此系统主要包含三部分:上位机仿真和测试、CAN网络和底层待测ECU模块。其中上位机仿真和测试模块又分为仿真信号产生模块和测试与结果显示模块两部分。
3.1 仿真信号产生模块
使用NI 6259板卡和上位机LabVIEW构建仿真信号产生模块。此板卡可支持48路数字信号输出和4路模拟信号输出。在调用接口函数模块后,可产生需要的仿真信号,在板卡对应引脚输出对应电压信号。
由表2的ECU控制信号表可知,此待测ECU具有两种不同类型的信号:模拟信号和开关量信号。所以需要在LabVIEW中使用DAQmx各模块仿真出ECU需要的模拟信号和开关量信号。
1)产生模拟仿真信号[10]。需要把模拟信号转化为ECU能识别的电压信号,一般范围在5V以内。
如:仿真发动机冷却水温度信号,水温与电压之间的关系如图5所示。
通过最小二乘法线性拟合得出公式:
y=-4×10-10x5+7×10-8x4-3×10-6x3+0.0002x2-0.0642x+4.2044
其中:y为输出电压值;x为冷却水温度值。
如:进气歧管压力信号,压力与电压之间的关系式:
V=V参(0.0023P-0.015)
其中:P为上位机模拟的压力值;V参为参考电压5V。关系如图6如示。
由图5~6可知模拟信号与电压值之间的转换特性,由上位机进行转换后通过板卡进行输出,传递对应电压值到待测ECU,驱动其进行控制工作。
2)产生开关量仿真信号。
在LabVIEW中定义各种开关量信号,通过板卡产生高/低电平。一般情况下,ECU检测到高边信号(ECU有效电平分两种:H、L,即高电平有效或低电平有效)后进行控制工作(一般情况下,ECU的高电平判断电压在2.5V~5V),控制信号的开启或关闭,并同步使用CAN模块广播CAN报文。
如:DriverDoorStatus(左前门状态),根据ECU手册可知,其为BOOL量,所以在前面板中放置一个BOOL型控件。在对信号进行操作处理后调用NI6259板卡的接口函数并配置通道信息,与此板卡进行通信,产生所需仿真信号(此功能是否正常可通过示波器进行验证)。
3.2 待测ECU模块
车载ECU控制功能工作原理:ECU外接12V工作电压,在人为进行操作或发生状态变化(如开启转向灯、水温变化)时电路接通,然后产生电压值传递到ECU的模拟输入引脚,如图7所示。
此系统使用板卡产生的各种电压信号代替左侧虚线部分图中未见虚线,请补充或说明。,ECU检测到信号后进行控制工作。
3.3 测试与结果显示模块
上位机LabVIEW调用NI 8473s板卡接口函数采集CAN报文[12]。根据ECU控制协议,对CAN报文进行解析、分析、处理,提取出周期、ID、DATA等控制信息。然后对比原始数据(3.1节部分),进行多次测试后,如果每次测试都全部通过,则判断为Pass,否则为False,并在前面板中进行显示。
其中:原始数据包括报文周期、ID和控制信号数据等;报文周期和ID由ECU控制协议决定;控制信号数据由仿真控制信号模块在产生仿真信号时提供。
4 测试实现
测试ECU在控制功能上是否满足给定的协议和规范,并测试在循环测试多次之后,ECU控制功能是否具有较好的稳定性。测试系统人机界面如图8所示。
“仿真信号控制部分”产生表1的ECU控制信号。“ECU控制显示部分”是对接收到的CAN报文进行解析、处理之后用控件进行形象的显示,并与“仿真信号控制部分”进行对比。结果显示,在循环测试100次之后,信号量“左前门状态”和“进气歧管压力信号”控制出错,在BOOL数组和测试表格中都有明确显示。“ECU控制显示部分”显示出“左前门状态”灯不亮以及进气歧管压力信号数据不一致,这些也同样说明了信号控制的错误。在生成的测试报告(.html格式)中也有明确显示,如图9所示。
从测试过程中得知,各个ECU的触发电平有可能不一样,大致在5V~12V。NI 6259板卡的工作电压需小于10V,所以在需要触发电平高于10V的ECU上进行测试时,则需要在板卡的输出端加入一个增压电路。
同时,为了保证测试的正确性,在使用示波器确认仿真部分的输出电压无误后,采用车载网络测试专用工具CANoe对ECU控制报文进行监测,观察结果如图10如示。
由图8和图10可知,使用CANoe监测的总线报文与测试系统监测到的报文一致,验证了本文所设计测试方法的可行性和准确性。在对比分析图8和图10中的监测数据,验证了数据一致性和通信协议的可行性。
根据不同ECU的控制协议,制定不同的仿真信号产生模块和测试模块,并在使用过程中,不断完善ECU的测试用例库,在完善后进行不同ECU功能测试时,进行规格选择后,即可实现对不同ECU的功能测试。
5 结语
本文介绍了ECU功能测试的现状,优化和改进了传统测试方法。此方法以仿真信号代替采集的真实信号来驱动ECU进行控制工作,并引入闭环结构和CAN总线,使测试过程更加简单和智能化。所测结果准确可靠,能运用于ECU生产线,提高ECU批量测试的工作效率,为整车厂进行ECU测试带来了方便。在完善仿真信号模块和测试模块用例库后可扩展到对不同型号ECU的功能测试。同时,此方法的思想,还可以应用于车载网络的测试、故障诊断等方面,具有较好的理论价值和实际意义。
参考文献:
[1]
夏巍,严辉,丁刚.CAN网络的实时性与可靠性的研究[J].安徽建筑工业学院学报:自然科学版,2007,15(1):65-68.
[2]
KONG FENG, ZHANG LIYAN, ZENG JIE, et al. Automatic measurement and control system for vehicle ECU based on CAN bus [C]// Proceedings of the IEEE International Conference on Automation and Logistics. Washington, DC: IEEE Computer Society, 2007: 964-968.
[3]
王立萍.CAN网络在汽车控制方法的应用[J].工业仪表与自动化装置,2009(5):77-79.
[4]
WU WEI-BIN, HONG T S, LUO CAI-RU, et al. Hardware-in-loop of alternative fuel engine ECU [C]// Proceedings of the Second International Conference on Computer Modeling and Simulation. Washington, DC: IEEE Computer Society, 2010: 291-294.
[5]
陈彦丰,朱君.基于PXI的汽车测试方案[J].汽车制造与装备,2005(3):44-46.
[6]
程跃,康劲松,徐国卿.一种车用CAN总线网络测试系统的研究[J].电子应用,2008,27(1):83-86.
[7]
梁锐.NI软硬件平台在汽车ECU开发和测试中的应用[J].世界电子元器件,2007(12):61-63.
[8]
WEI WEN-XIONG, GUO JIANG-WEI, LIU SHENG-LONG, et al. Design of CAN communication network in automobile ECU testing system [C]// Proceedings of the Second Pacific-Asia Conference on Circuits, Communications and System. Washington, DC: IEEE Computer Society, 2010: 1-3.
[9]
CAN Specification 2.0,Part A [EB/OL]. [2011-02-15]. can-cia.de/fileadmin/cia/specifications/CAN20A.pdf.
[10]
曹更彦.汽车燃气发动机电控系统实时仿真技术研究[D].重庆:重庆邮电大学,2009.
[11]
阮奇桢.我和LabVIEW[M].北京:北京航空航天大学出版社,2009.
[12]
Society of Automotive Engineers. SAE J1939 [EB/OL]. [2011-03-03]. 省略/PDFs/manual/drehgeber/M36X8/M3658_J1939.pdf.
[13]
胡思德.汽车车载网络(VAN/CAN/LIN)技术详解[M].北京:机械工业出版社,2006.
收稿日期:2011-06-16;修回日期:2011-08-21。
基金项目:
国家“核高基”重大专项(2009ZX01038-002-002-2);重庆高校优秀成果转化项目(KJZH08210)。
【关键词】车顶单元;制冷量;设计
上世纪90年代后,随着铁路空调客车的飞速的发展,车顶单元式空调器的产量逐年增加。据不完全统计,目前国内拥有空调器约20000多台。值得注意的是投入运用的空调器早已到了大修期,其中绝大部分为车顶单元式空调器。为保证检修后的空调器的性能,客车车顶单元式空调器的检修试验就显得十分重要。
一、客车车顶单元式空调器的性能试验装置
1、空调器的型号
目前,我国铁路客车用空调器的主要型式是车顶单元式。该型空调器自1980年从日本引进,仿制改进,至今已经运用20多年,通过不断地改进完善,现在已经形成标准化,系列化。空调器的结构型式主要有三种:平底侧出风口型,代号为“—”;圆底下出风型,代号为“Y”;平底侧出风口型,代号为“P”。平底侧出风型空调器安装于客车车顶端部,新造客车安装的绝大部分都是这种型式。
2、空调器的构造
车顶单元式空调器是将机械制冷部分的压缩机、冷凝器、干燥过滤器、毛细管(或膨胀阀)、蒸发器、气液分离器、冷凝风机、蒸发风机和空气预热器等集中装在一个箱体内,组成一个单元,可方便地安装在车顶部。与空调器配套的电气控制柜安装在车内配电室,空调器与电气控制柜通过电气连接器(插头、插座)连接,由发电车集中供电(亦可由本车悬挂式发电机供电)。空调器出风口与车内主风道之间通过软风道连接,空调器处理后的空气经车内主风道由送风口送入客室内,达到调节车内空气温度的目的。由此可见,客车车顶单元式空调器性能试验装置的重要性。
3、设计原则
1)试验装置结构力求紧凑,占地面积尽量小,以求适应于各类生产车间的工艺布局;
2)外形应该美观,设备整体性强;
3)工艺布置应该灵活,工艺设计应该简单;
4)操作方便,参数的测试及数据处理要求准确
4、设计方案的确定
目前现场使用的车顶单元式空调器性能装置有闭路式和开路式两种原理方法:
1)闭路式测试原理方法
该方式需要一间室外侧试验室一间室内试验室,被试空调器安装于室外侧试验室内,该室内的空气温度需要调节到名义工况下空调器冷凝器进风温度,经空调器制冷后的空气由送风道引入置于室内侧试验室的空气流量测试装置进行空气流量测量,接着进入空气调节装置,调节后的空气再由回风道被空调器吸入,即完成了一次循环。空气 参数调节及空气流量测量均在风道内进行,该方式的特点是测试环路必须密闭,热湿损耗较小。
2)开路式测试原理方法
该方式与闭路式的区别在于,空气经过流量测量装置后直接排入室内侧试验室内,在房间内进行空气调节。其优点是室内侧试验室的空气参数易于稳定,但热湿损耗较大。
对于这两种方式,均需要设置独立的试验房屋,房屋面积随实际情况而定。被试空调器的安装可采用固定式安装架或试验小车。如果采用固定式安装架,则一般采用箱式结构,室外需设置空调器吊装设备。若采用试验小车则一般采用房间式结构(即由几间相互隔热的房间构成)可在有起重机的检修间将空调器吊装到小车上,试验小车推入室外侧试验室,接上管道即可进行试验。
相比于房间式结构,箱式结构相对构造简单,占地面积较小,它的工艺布置也相对灵活,工艺设置简单,不需要大量的土建工程。所以,本设计“以箱体式空调器试验装置”作为总体设计方案。针对箱体式试验装置的特点,其室内可以安装加热加湿装置,弥补室内的热湿损耗,所以我们选用开路式测试原理。综上所述,我们本次设计方案最后确定为:“箱体结构式的开路式测试”车顶单元式空调器性能装置
二、制冷量的测量方法设计
1、设计原则
1)测量精度高,范围宽,系统环节少;
2)测量装置结构力求紧凑,体积小,以适应在箱体内布局;
3)装置安装操作维护应该方便,参数的读取和数据的处理应该力求简单方便。
2、测量方案确定
目前,由于某些设计单位设计的试验装置仅仅采用一种方法测试制冷量,不能有效地控制室外侧空调器的冷凝器的进风温度,造成试验工况的不稳定,影响了测试精度。
《客车空调三机检修及运用管理规程》中规定,空调器制冷量达不到原参数的90%时,应该分解制冷系统。这就要求所建的试验装置工况要稳定,测试数据应该准确。TB/T2432-93《铁道客车车顶单元式空调器试验方法》中规定,空调器制冷量试验方法采用室内侧空气焓差法为主测试方法,室外侧空气焓差法为辅测试方法。对于检修性能试验装置也可以只采用室外侧空气焓差法。但是为了保证试验装置测试制冷量的的精度及使所测试空调器性能的稳定性,我们采用室内侧空气焓差法为主测试方法,室外侧空气焓差法为辅测试方法测试制冷。两种方法测试的结果相对偏差不大于6%,若超出6%,则要进行管路损耗修正。它的特点是稳定性好,不受外界因素变化的影响。
3、测量原理方法
所谓室内侧空气焓差法,即在规定工况下通过测得流经空调器室内侧空气焓差及量流量,经过计算获得有效制冷量的方法。
所谓室外侧空气温差法,即在规定工况下通过测得流经空调器室外侧空气温差及重量流量,经过计算获得有效制冷量的方法。
三、制热量的测量方法设计
1、设计原则
1)测量精度高,范围宽,系统环节少;
2)测量装置结构力求紧凑,体积小,以适应在箱体内布局;
3)装置安装操作维护应该方便,参数的读取和数据的处理应该力求简单方便。
2、测量方案确定
我国车顶单元式空调器运行在制热状态时候一般在冬季,采用的制热方式一般是直接加热。当空调吸入的新鲜空气和室内的回风在空调器加热室内被混合加热后,将其直接送入客室内即可,它相对于制冷状态而言比较简单,所以我们测试其制热量时候可只用一种方法——室内空气焓差法测试即能满足要求,为了保证热损失在控制要求的范围以内,要用输入电加热器的瓦数所制得的热量来验算(验算公式为qd=3.41·x,x为输入电加热器的瓦数,x可以在试验装置控制柜上读出来),若误差大于6%则要进行管路损失修正。若需要修正,修正方法为将两种结果的差值加给室内空气焓差法计算的制热量。
结 语
目前车顶单元式空调器在铁道客车上的运用已经越来越多,但是空调器性能试验装置的价格都非常高。因此,空调器的检修和性能测试的是急需解决的问题,它直接关系铁道客车运营情况的好坏。车顶单元式空调器性能试验装置能得到广泛的应用,有助于提高客车空调器的性能,从而提高铁道客车乘坐的舒适度,也就在一定程度上提高了铁道客车和其它交通工具的竞争力。
参考文献
[1]王其伟.单元式空调器性能试验装置的工况控制[J].铁道车辆,2008(12)
关键词关键词:软件工程;软件质量;单元测试;测试框架;面向对向程序
中图分类号:TP302 文献标识码:A 文章编号文章编号:16727800(2013)008004503
0 引言
随着现代软件工程的不断发展,人们对软件质量和生产力的要求越来越高。软件测试技术和框架复用技术作为提高软件质量和生产力的有效手段,近年来倍受人们的重视。
传统的“黑盒”、“白盒”测试技术主要应用于面向过程的程序设计中。随着面向对象技术的发展,这种技术已不能满足软件测试的需要。自动化单元测试框架应用于面向对象单元测试中,通过它来实现单元测试自动化。
单元测试是对软件进行正确性检验的测试工作,是软件设计的最小单位。单元测试的目的主要是发现每个程序模块内部可能存在的错误。程序员的基本职责是单元测试,单元测试能力是程序员基本能力的体现,程序员必须对自己所编写的代码认真负责,软件的质量与程序员的工作效率直接受程序员单元测试能力高低的影响。
单元测试是一项很重要而且必要的工作。在实际工作中,许多程序员并不愿意对自己编写的代码进行测试。软件开发的工作压力大,大多数程序员们因为没有时间测试自己的代码,使程序的代码质量得不到保证,有些代码还需重新编写,程序员根本没有时间对代码进行测试。自动化单元测试框架能够从根本上解决这个问题,它可以使测试工作变得简单,这样更有助于程序员进行代码开发工作。
1 自动化单元测试框架设计目标
自动化单元测试框架的设计应达到以下目标:首先,框架简单,可以使测试程序的编写更简化。框架使用常见的工具设计,测试工作操作简单;其次,测试框架应能够使除作者以外的其他程序员进行代码测试,并能解释其结果,即将不同程序员的测试结合起来,且不发生相互冲突。最后,测试用例可以复用,可以以现有的测试为起点形成新的测试。
本文将以这些目标为指导,讨论如何用以Kent Beck和Ralph Johnson提出的“模式产生体系结构”的方式来设计框架系统。自动化单元测试框架的设计思想是从0开始根据设计问题应用设计模式,一个接一个逐步设计,直至获得最终合适的系统架构。其中实现部分采用Java语言来实现,并会使用UML图来表示各种类及类间关系。
2 面向对象自动化单元测试分析
自动化测试定义为:管理与实施各种测试活动,包括开发测试脚本、执行测试脚本,这样使验证测试需求更加方便,通过这些脚本实现了自动测试,可以把它称为自动测量工具。使用这种自动测试工具对增量软件集成测试提供了巨大的方便,增加了巨大的价值。每一个新的构件可以重用先前开发的测试脚本,即使需求和软件有变更,作为一个重要的控制机制,自动测试也能够确保每一次重新构建的稳定性与准确性。
3 面向对象自动化单元测试框架
自动化测试框架实质是一种自动测试工具,单元测试的核心问题是实现测试自动化。一个完整的自动化测试过程通常包括5个测试活动,分别是测试标识、测试设计、测试实现、测试执行与评估。测试用例针对被测试系统的各项功能准确地开发与设计,而且每一个测试用例都要按顺序执行这5个测试开发活动,测试开发活动如图1所示。
图1 测试活动
测试标识与测试设计这两个测试活动主要为智力活动,分别标识测试条件和设计测试用例。测试执行与测试比较这两个活动属于比较机械的活动,它们的功能分别为:执行测试用例、将测试输出结果并与期望输出结果值相比较。前两个活动决定了测试用例的质量,后两个活动适合自动化。在单元测试中,测试执行和测试比较这两个活动要重复多次,测试标识与测试设计通常只执行一次。因此,在单元测试过程中,重复性的活动特别需要自动化执行。
4 自动化单元测试设计与实现
首先构建对象来表达基本概念:Test Case(测试用例),然后将对象发送到测试框架,再由测试框架执行,最后报告测试结果。
采用Command命令模式将一个请求封装成一个对象,Command模式可以为每一个操作生成一个与之对应的对象,同时能够给出一个对应的执行方法。这样可以对多个用户请求进行排队,也可以将多个请求记录到日志,并使用不同的请求对客户进行参数化。具体实现方法如下:
其中的run()方法为模式中的执行方法,可以通过继承来重用该类,为了便于在测试失败时能够识别出失败的测试,每一个Test Case在创建时都要给出与之对应的名称,这样即可判断出失败的测试。
图1展示了测试框架组成部分的快照,也展示了应用于TestCase中的标记。
图1 测试框架组成部分
5 单元测试用例执行流程
在实际测试过程中,构造参数或资源、测试、释放资源为测试的业务逻辑过程。例如,在测试数据库的插入、更新、删除、查询等操作时,首先要对数据库进行连接,然后测试,最后释放连接。这样,在一个Test Case中有多个测试,需要反复书写代码,这增加了测试人员的工作量,不符合设计目标。
建立测试支架即为所有的测试建立一个共同的结构,可以解决以上问题,初始化代码、测试代码和释放资源的代码均放在测试支架上,每次运行测试代码之前,首先都运行初始化代码,最后运行释放资源代码。这样,每一个测试都会和与之对应的支架一起运行,而且测试结果互不影响,每一个结果都不会影响其它的测试结果。这样便实现了代码的复用,大大提高了软件单元测试的工作效率。
以上通过模板方法实现,模板方法的Template Method静态结构如图3所示。
其中,setUp方法初始化测试信息,如数据库的连接,cleanUp方法的功能是测试结束后释放资源。runTest方法的功能是进行测试业务逻辑。TestCase的方法的功能为进行测试逻辑框架的设计,run为模板方法。在这里,setUp和cleanUp可以被用来重写,由框架来进行调用。
6 测试结果收集
创建对象TestResult来收集运行的测试结果,实现代码如下:
UTF使软件开发者们更愿意接受测试代码的工作。有种种好处:UIT使测试用例的实现简单、一致且模块化;测试实现与执行的特性支持迭代、增量开发;重新运行测试包的便利使高频率的回归测试成为可能;同时它还能保证单元测试的持久性。此外,单元测试框架UTF也是可扩展的,例如,利用Decorator模式,可以不断向UTF添加新的功能;TestResult类也是框架的一个扩展点。客户能够自定义它们的TestResult类,例如, HTMLTestResult可将结果上报为一个HTML文档等。
参考文献参考文献:
[1] (美)普雷斯曼.软件工程:实践者的研究方法[M].北京:机械工业出版社,2011.
[2] (美)麦格雷戈.面向对象的软件测试[M].北京:机械工业出版社,2002.
关键词:软件测试;单元测试;模拟对象
中图分类号:TP311文献标识码:A文章编号:1009-3044(2008)05-00ppp-0c
1 引言
随着极限编程在实际软件开发项目中的推广,越来越多的项目开始采用测试驱动开发作为主要的软件开发方法。单元测试不仅优化了软件系统设计,还大大简化了功能测试的工作量[1]。但是另一方面.更多的项目在开始不久就发现在很多情况下针对一个类编写单元测试比较困难.随着项目的进行,越来越多的代码无法进行单元测试.到最后整个项目无法继续采用测试驱动的方式进行开发。因此,要将测试驱动开发真正在整个项目里贯彻执行,必须有一种方法能够相对容易的解决这些问题。本文将首先讨论了单元测试和无法或很难进行单元测试的情况,然后引入Mock Object的概念,基于Mock Object实现单元测试。接下来讨论在软件开发过程中引入Mock Object对测试和设计的影响。最后简述了Mock Object的局限性。
2 单元测试
2.1 什么是单元测试
单元测试是对程序中的单个子程序或过程进行测试的过程,也就是说,一开始并不是对整个程序进行测试,而是将注意力集中在对构成程序的较小模块的测试上面[2]。单元测试从两个角度进行测试:一是测试数据都是针对程序的功能来设计的黑盒测试;二是针对程序的逻辑结构来设计测试用例的白盒测试。
2.2 单元测试面对的难题
造成针对一个类难以进行单元测试的主要原因是因为这个类依赖于一些其它的难以测试的资源。主要有这三类最主要的资源:数据库,第三方组件和网络硬件资源。下面我们将对这三大类难以测试的资源进行分类讨论。
2.2.1 数据库
现在大部分的软件项目都会采用数据库作为数据存储。常见的开发团队会在每个开发人员的机器上安装一个本地的数据库,每个人针对自己的数据库进行开发调试。这样做的问题是:必须有一种方式同步数据库的设计。如果有一个人修改了数据库schema或者某个存储过程,这个修改必须同步到所有开发者的本地数据库以及测试服务器上。采用敏捷软件开发的很多项目组往往会浪费大量的时间在数据库设计同步上。更严重的是每周都会遇到由于数据库设计不同步,修改冲突导致的问题导致整个项目的中心源码库在Auto Build时失败。每个开发人员都有自己的测试数据,除了上面提到的需要把这些测试数据同步到所有开发机器和测试服务器上外,还面临更重大的问题。因为测试用例需要修改数据库,因此还必须准备一种机制能够在每一个测试用例执行结束后重新将所有的测试数据调入数据库。采用最简单直接的方法就是在每个测试用例执行前都将数据库清空,然后再将测试数据调入,这样会大大减慢单元测试的时间。单元测试时间越长,开发者就越不愿意执行这些测试用例,单元测试所发挥的作用越小,这也是很多测试驱动项目最终无法进行到底的一个重要原因。另一个非常严重的问题是为了清理测试环境,在针对商业逻辑的测试用例中加入了大量的数据访问层的代码。采用这样的方式强迫开发者在开发商业逻辑层的同时开发数据访问层,并且严重降低了可读性。
2.2.2 第三方组件或应用服务器
数据库是最常见的第三方服务器。除此以外在越来越多的项目中使用第三方的组件和应用服务器。例如:客户环境中的ERP系统,全球定位系统(GPS)的Web Service接口,绘图引擎等。对于这些第三方提供的内容,造成难以编写单元测试的最根本的原因有:一是系统不透明:对于大部分商业组件或者服务来说,一个很重要的内容是良好的封装。但这个特性带来的问题是在外界无法对其内部状态进行控制和访问。往往经过好几个操作后才能在外部观察到相应的变化。二是环境配置困难。由于项目组成员计算机配置不同,加入项目的时间不同,在项目中负责的内容不同导致无法为所有开发人员配置一个完全一致的环境。例如一个绘图引擎的开发版的license是按照一个局域网内部同时使用的人员个数收费的,就不可能只为了能够进行完整的单元测试就为只编写商业逻辑层的开发人员也安装一套。
2.2.3 网络资源和硬件资源
在稍大一些的项目中都或多或少的用到一些网络资源。例如将文件部署到远程的webDAV服务器上同时很多项目还会用到一些硬件资源。常见的有打印机、指纹识别验证或者条形码阅读器等。这些资源有两大特点导致很难针对与他们相关的类编写测试用例。
一是资源访问冲突。很多网络资源对于并发访问的响应协调是通过锁机制进行的,在实际项目中常见的是一个开发人员在调试本地代码时导致远端资源被锁定导致其它开发者无法访问这些资源。
二是环境可控因素。对于网络资源和硬件资源相关代码的测试与针对商业逻辑层代码的测试最大的不同是环境的不确定性。访问网络资源有可能遇到的异常情况非常多,例如网络忙造成访问超时,也有可能建立链接后数据传输失败,还有可能数据传输完成后校验失败。针对访问这些资源的代码进行的测试必须能够覆盖到所有可能出现的每一种情况。如果没有一个可控,并且是全自动的环境辅助单元测试的话,这项任务基本上不可能完成。
3 模拟对象
3.1 什么是模拟对象
Mock这个单词翻译成中文大概的意思是假的,模拟的。如图1所示:通过一个常见的对商业逻辑的测试描述了一个Mock Object。在图中我们可以看出:测试代码需要测试商业逻辑,而商业逻辑代码需要通过IMyDataAccess接口访问底层数据库,这就是数据库依赖问题。为了解决这个问题我们引入一个Mock Object,并将这个Mock Object而非真正的Data Access传递给商业逻辑代码进行测试。这里的Mock Object不需要实现任何逻辑只需要根据商业逻辑的需要返回适当的内容就可以了。
图1 使用Mock Object对商业逻辑进行测试
3.2 模拟对象实现单元测试应用实例
现在我们写好了类AccountService,具体如下:
public class AccountService {
private AccountManager accountManager;
public void setAccountManager(AccountManager manager) {
this.accountManager = manager;
}
public void transfer(String senderId, String beneficiaryId, long amount) {
Account sender = this.accountManager.findAccountForUser(senderId);
Account beneficiary =
this.accountManager.findAccountForUser(beneficiaryId);
sender.debit(amount);
beneficiary.credit(amount);
this.accountManager.updateAccount(sender);
this.accountManager.updateAccount(beneficiary);
}}
现在我们想测试transfer方法,它内部调用的AccountManager的两个方法。但是对于AccountManager来说,它只是个接口,如下:
public interface AccountManager {
Account findAccountForUser(String userId);
void updateAccount(Account account);
}
所以现在我们必须写个MockAccountManager对象。而且里面的方法体都是非常简单的,就是假定它就返回某某值。
我们这里还有Account类。
public class Account {
private String accountId;
private long balance;
public Account(String accountId, long initialBalance) {
this.accountId = accountId;
this.balance = initialBalance;
}public void debit(long amount) {
this.balance -= amount;
}
public void credit(long amount) {
this.balance += amount;
}
public long getBalance() {
return this.balance;
}
public String getAccountId() {
return accountId;
}}
public class AccountService1Tests extends TestCase {
public void testTransfer(){
AccountService as = new AccountService();
MockAccountManager mockAccountManager=new MockAccountManager();
Account accountA = new Account("A",3000);
Account accountB = new Account("B",2000);
mockAccountManager.addAccount(accountA);
mockAccountManager.addAccount(accountB);
as.setAccountManager(mockAccountManager);
as.transfer("A","B",1005);
assertEquals(accountA.getBalance(),1995);
assertEquals(accountB.getBalance(),3005);
}}
这里我们在假定AccountManager方法都工作正常的情况下,完成了对transfer方法的测试。
从以上代码可以看出,采用Mock Object进行的单元测试基本上可以分为下面几步:
(1)基于一个接口定义Mock并实现这个接口的所有函数。
(2)创建Mock Object的一个对象
(3)设置对象内部属性
(4)告诉对象测试代码希望看到的反应
(5)进行测试
(6)检查Mock Object的确按照希望的顺序进行工作。
3.3 模拟对象的优点
3.3.1 模拟对象作为测试手段的优点
Mock Object最直接的优点在于提供单元测试的质量和覆盖率:
(1)只要在测试中对期待发生的问题指定好执行的顺序引入Mock Object对象后的单元测试就是在一个完全可控的环境里进行的。也就是说我们再也不会无法定位一个“时隐时现”的bug。相反我们可以非常迅速的将问题定位在一个类的内部,而不是一个函数调用序列。
(2)于测试人员来说,最常见的问题是测试人员提交的bug无法在开发人员那里复现。有了Mock Object这个工具测试人员可以利用Mock Object明确的指定输入和输出编写一个测试用例让开发人员修复。
(3)超过8O% 的异常处理代码没有被充分测试过。主要原因是在没有Mock Object之前很多情况是无法由人工进行控制的,例如写文件失败网络连接超时,数据库数据传输失败或者从网络接收到的数据已经损坏。通过控制Mock Object我们很容易就可以模拟上面的这些情况。
3.3.2 模拟对象作为设计手段的优点
虽然Mock Object最直接的优点在于给予测试代码更多的可控性和可操作性,它最大的优点在于对软件设计的影响[3]。
(1)测试驱动开发与Mock Object一起使用,可以写出低耦合高内聚,非常优雅干净的代码。
(2)强迫设计者放弃对第三方库的强依赖关系,取而代之的是比较弱的依赖关系。
(3)设计人员可以将更大的注意力放在商业逻辑的实现和测试.由于Mock Object的存在,我们不需要实现数据访问层就可以对商业逻辑进行测试。而商业逻辑才是任何系统中对于客户最重要的内容,它的正确与否决定了整个系统是否能完成任务,它的稳定性决定了整个系统架构的稳定性。
(4)在项目初期,甚至是中期,将设计人员解放出来,不用对系统底层的基础设施做出判断。例如,在商业逻辑并不明确,需求还不稳定的时候,我们是更多根据感觉来做出很多重要的判断的,而这些判断往往导致比较关键的决定。例如,在项目之初,谁能够明确的回答到底需要什么样的数据库?Oracle?SQL Server?还是XML文件?到底需要什么样的队列服务器 MSMQ还是IBM―MQ?由于Mock Object的引入,我们可以将这些决策推迟到商业逻辑层更加明确之后进行,从而可以获得更加准确有针对性的答案。
3.4 模拟对象的局限性
Mock Object在实际项目中的应用存在一些限制,一些是由于Mock Object本身性质决定的,有一些则是由于其它类库设计存在的缺陷导致的。
(1)一个典型的不是Mock Object的问题,而是类库设计的问题。是Mock Object无法模拟比较深的对象树。有一些第三方的类库,尤其是一些消息处理函数的参数,提供的不是接口而是一些对象。往往这些对象内部有很多子对象,也就是我们常说的一棵大的对象树。我们需要花费太多的精力去构造这些对象来进行模拟,时间消耗巨大。
(2)一般性而言,单元测试的粒度越细,功能测试的粒度就可以越粗[4]。但是引入Mock Object的单元测试仍然无法取代功能测试。一个很好的例子就是误差积累的测试,哪怕每个单元的误差都在可接收范围内,我们仍然需要一个功能测试确保整体误差也是可以接受的。
4 结束语
模拟对象解决了传统单元测试的两个问题:一是如何将需要测试的代码与相关环境隔离;二是如何创建一个快速、可控的环境辅助测试开发。随着模拟对象技术的成熟,基于模拟对象的单元测试会越来越广泛地被采用。
参考文献:
[1]Kent Beck.测试驱动开发[M].北京:中国电力出版社,2003.
[2]Myers.王峰,陈杰译.软件测试的艺术(第二版)[M]. 北京:机械工业出版社,2006.50-52.
[3]David Astels.崔凯,译.测试驱动开发实用指南[M].北京:中国电力出版社,2004.120-130.
[4]Paul C Jorgensen.韩柯,杜旭涛,译.软件测试(第二版)[M].北京:机械工业出版社,2003.
【关键词】Testbed/Tbrun 软件单元测试 嵌入式
单元测试是保障软件质量的重要技术手段,其过程十分复杂,如果不借助辅助工具,仅靠人工处理,则不仅效率低下,工作量巨大,而且可能出现无法解决的问题。因此,利用一套好的单元测试工具帮助测试人员提高工作效率、工作质量是非常必要的。
1 单元测试的定义
单元测试(图1和图2)是一个在隔离状态下测试单个独立软件单元的过程,而集成测试(图3)允许好几个单元的同时分析,是多单元测试。因此,在单元测试时,需要模拟被测单元与其他模块之间的交互,开发驱动模块和桩模块构建一个可执行的环境。
2 单元测试的要求
单元测试重点要考虑的测试类型有:
2.1 功能测试
根据需求的关键成都选取相应单元开展单元测试(建议需求的关键程度为关键、重要的单元应100%开展单元测试,需求的关键程度为一般的单元可以通过代码审查验证其功能)。
2.2 覆盖率测试
根据软件等级确定覆盖率测试(见表1)。
3 如何达到充分的覆盖率测试
3.1 根据对被测程序的期望实现的功能来构造最有可能的功能测试
这些功能从软件需求说明书或用户文档获得。在加载测试数据的情况下,应该能够通过测试工具监控源代码的执行。当实现功能测试的数据用完后,检查覆盖率来发现程序中的哪些部分仍然没有被测到。应该进一步的构造测试数据并进行执行、分析。一直持续到进行功能测试的数据被执行完或者达到所需的测试度量标准。如果测试数据执行完那么进行(3.2);否则的话(达到测试度量标准的要求)那么任务就完成了。
3.2 检查测试覆盖度量指标
如果语句覆盖率没有达到完全覆盖,那么可能是由于某个特殊的用例运行失败,错误退出等造成的。为了将代码中的每一行都执行到,将程序执行多次通常是必须的。通常功能测试只能覆盖程序中40%到60%的可执行语句。当语句覆盖达到完全,每一条语句都被执行时,便可进行(3.3)。
3.3 检查所有没有被执行的分支
通常这些分支中的一部分可以通过构造专门的用例实现对它们的测试。找出程序中未执行分支,将分支测试充分实施后再进行(3.4)。
3.4 有些没有执行到的分支和路径,是由于相关的测试用例只有在程序执行出错或者计算出错的错误状态下才能实现
这些通常是和程序的冗余保护设计相关,这样的路径应该完整的保留。一旦不可行测试路径被去掉,那么源代码将会更加有效、健壮并且占用更少的空间。
4 Testbed/Tbrun在单元测试中的应用
使用/Tbrun可自动产生软件测试的驱动、桩模块,从而节省时间,测试人员可将重点放在设计测试用例上,提高软件测试效率。使用Testbed/Tbrun的基本方法:
(1)在已集成了开发环境的Testbed中加载被测软件单元。
(2)创建并设计测试用例。设置输入变量值。Testbed/Tbrun创建的测试用例,初始默认的输入变量有时可能不满足实际执行路径的要求,也有可能存在当前执行路径不需要的输入变量,可将多余的输入变量删除掉,输入变量选择完成之后,根据希望被测函数执行的路径,设置各输入变量的值;设置桩函数。Testbed/Tbrun能够通过对被测函数的分析自动为被测函数生成桩函数,在桩函数管理界面,选择需要进行设置的桩函数,分析判断是否需要设置桩函数的返回值,还是需要通过调用桩函数改变某些全局变量的值;执行测试用例。设置完成输入变量和桩函数之后,就可以开始执行测试用例了。
(3)查看覆盖率信息。每成功执行一个测试用例后,Testbed/Trbun都会统计当前测试用例执行的路径以及相应的覆盖率,其中“S”表示语句覆盖率,“B”表示分支覆盖率,“MCDC”表示MC/DC覆盖率,即修正条件/判定覆盖率。
(4)动态覆盖率报告的保存。动态覆盖率报告以.c文件为基本单元,包含当前.c文件中所有函数的动态执行情况,建议每执行完成一个函数的单元测试之后,为各被测函数单独保存动态覆盖率报告,在该报告中找到被测函数的具体动态执行信息。
在实际应用中,需要注意以下几个方面:
(1)main函数的测试。Testbed/Tbrun不支持直接对名称为main的函数进行单元测试,可通过修改main函数的名称后再进行单元测试,如将main函数名称修改为testmain等。
(2)指针变量的测试。Testbed/Tbrun不支持直接对指针进行引用的操作,容易跑飞,需要将指针映射到相应的变量,Testbed/Tbrun支持对指针进行映射。
(3)指针指向绝对的内存地址。在头文件中,代码可能包含下列风格,用#define来引入绝对内存地址。例如:#define CONGIG_PAGE_1_ADDR 0x418000,然后在函数中直接从绝对地址中写入和读出数据。当在一个主机/主机的测试环境中运行这个函数时,内存访问违反将发生,易出现程序跑飞的现象。
5 结论
相对于完全人工测试,使用Testbed/Tbrun工具测试提高了工作效率、工作质量。因此,Testbed/Tbrun可以较好地支持嵌入式软件单元测试的开展。
关键词:Testbed/Tbrun;软件单元测试;嵌入式软件
中图分类号:TP311 文献标识码:A 文章编号:1009-2374(2013)18-0027-02
嵌入式软件作为嵌入式系统的重要组成部分,嵌入式软件质量问题可能会带来设备的损坏和人员的伤亡,因而用户对其质量有较高的要求。软件测试是对软件质量检验的一个非常重要的手段。而软件测试中动态测试最基础的测试就是单元测试。如何开展单元测试以及如何提高单元测试的效率是一个值得研究的问题。
1 软件单元测试的要求及重点
软件单元测试是对软件基本组成单元进行测试,测试软件单元是否正确地实现规定的功能,是否满足软件性能和接口要求。并验证程序与详细设计说明的一致性。因此在单元测试时,需要模拟被测单元与其他模块之间的交互,开发驱动模块和桩模块两种辅助模块,构建一个可执行的环境,驱动模块用于模拟被测单元的上层模块,测试执行时由驱动模块调用被测单元使其运行;桩模块用于模拟被测单元在执行过程中所调用的模块。
单元测试重点考虑的测试类型有:(1) 接口测试。接口测试主要检查实参与形参的数目是否相等、实参与形参的属性是否匹配、实参与形参的单位是否一致、传到被调用模块的实参的属性是否与形参的属性匹配、是否把常量当作变量传递等内容。(2)功能测试。功能测试主要是对照软件单元的设计说明,验证软件是否完成了所需的功能。(3)重要执行路径测试。应设计测试用例以发现错误的计算、不正确的比较和不正常的控制流向等错误。在计算中比较常见的错误是:误解或错误处理算术运算的优先次序、混用不同类的操作、计算精度不够等。另外在控制软件执行流程的比较操作中比较常见的错误有:不同数据类型的比较、不正确的逻辑操作符或不正确的优先次序、因精度不够使本应相等的数不相等(如浮点数)等。(4)软件单元的局部数据结构测试。软件单元的局部数据结构是一个主要的错误来源,应设计测试用例来发现不正确的或不一致的数据说明、初始化有错或没有赋初值、不正确的变量名、不一致的数据类型、上溢/下溢或引用错误等类型的错误。(5)错误处理路径测试。一般软件错误处理路径测试应考虑下面几种可能的错误:对错误的描述不易理解、指出的错误并不是所遇到的错误、出错时还没有进行出错处理就先进行系统干预、错误边界条件的处理不正确、描述错误的信息不正确从而不足以确定出错的原因等。(6)边界测试。边界测试是检测软件在其输入/输出域、过程参数、状态转换、功能界限等具有一定范围的边界或端点条件下的运行情况,考核软件的功能或性能在其边界条件下或边界的邻近区域内是否依然满足设计要求。按照上去要求进行单元测试时,为达到要求的覆盖条件,还需采取一定的技术手段对测试覆盖率进行记录和分析,确保达到相应的覆盖率指标。采用TBrun单元级测试工具,能自动产生软件测试驱动、桩模块,提供友好的输入输出人机交互和覆盖率统计功能,能有效提高单元测试的测试效率。
2 Testbed在单元测试中的应用
使用 Testbed/TBrun的基本方法是:设计测试用例;在Testbed/TBrun中加载被测单元文件,通过Testbed/TBrun对被测软件进行源程序自动插装;根据测试用例设定输入和预期的输出,执行插装好的源程序单元;分析输入数据、预期输出和实际输出;得到被测软件在当前的测试用例执行过程中代码的覆盖率。需要注意的是,每执行一个测试用例就需要重新编译并执行。Testbed/TBrun的覆盖率统计只具有累加的功能,因此不能查询每一测试用例执行后的覆盖率信息。在执行完所有的测试用例后会生成一个总的覆盖率文件,Testbed/TBrun通过对覆盖率文件的分析得出软件单元相应语句的覆盖情况,根据这些覆盖情况可以较快确定冗余的测试数据并增补遗漏的测试数据,从而指导新的测试用例设计。在实际应用Testbed单元测试时,需注意以下三个方面:(1)数组和指针类型的变量的输入。数组可以通过在Testbed/TBrun插装后的源代码中插入数组的初始化语句对数组赋值或者在 Testbed/TBrun 环境中对数
组的一部分赋值。因指针不能被直接赋一个地址,所以输入指针可采用映射的方式来赋值,将指针变量映射成相应的自定义变量,然后对自定义变量赋值。在测试执行的过程中,这个自定义变量的值就是指针的输入值。(2)被测单元代码的必要修改。在实际的测试过程中,有的代码单元不能直接使用Testbed/TBrun直接执行测试。须在分析之前对代码单元做少量修改。如Testbed/TBrun 插装源代码时会生成 main()函数,因此被测单元中的 main()函数要改为其他的名称以避免造成名字冲突;Testbed/TBrun 执行分析时会执行被测单元,因此被测单元中的 while(1)之类的死循环结构要去掉,否则分析将无法结束。(3)模块测试后显示最终整体覆盖率,不能查询每一测试用例执行后的覆盖率信息。
3 结语
Testbed有效地支持了测试人员的测试工作,相对于完全人工测试提高了测试效率。该工具仍存在不足,还需在实践中不断完善使用方法。
参考文献
本文就如何运用反馈——矫正手段提高教学目标效果谈几点看法。
一、在课前通过诊断性测试,获得学生在学习新内容前的知识反馈,为上新课做好准备。
诊断性测试一般安排在新学期或新开课前进行,测试时间一般5~10分钟,测试应侧重于考查学习新课所需要掌握的基本知识和基本技能。例如,在上动物模拟人体手术实验课前,先测试学生关于无菌技术和无菌原则方面的知识并补偿,由此提高他们的学习外科手术的前提能力,最终提高实验目标。
二、在课前或课后,通过形成性测试了解学生的达标情况,及时查漏补缺。
1、编制形成性测试题,包括课堂测试题和单元测试题,要确保适合各自的特点。
(1)课堂测试题,要适合在课堂教学中进行测试。课堂教学时间一般以二学时为单位,共80分钟。其中用以进行课堂测试及反馈矫正的时间通常只有5分钟,故编制此类试题要突出重点,考虑课堂操作的可行性,试题量不能过多。例如,在“复苏”一章编制的课堂测试题为:①快速诊断心脏骤停的方法;②心肺初期复苏的abc步骤;③心脏按压有效的标志是什么;④心肺复苏有效的指标是什么等。这些题中包括了本章的重要知识点,学生掌握后,在遇到心脏骤停病人时就会懂得如何去诊断和处理,而且试题量适中,便于在课堂上进行测试和矫正。
(2)单元测试题,即教师根据教学的情况,一般按章节划分为一个教学单元,每学完一个单元后进行一次单元测试,以评价学生的单元达标情况。单元达标测试覆盖的目标范围较大,而且每一目标都应有相应的检测题,测试时间为20~30分钟,测试内容多时间少,因此编制此类题主张多用选择题和判断题,少用填空题、名词解释和问答题,以方便学生答题,做到既能检测目标又不影响课堂授课。此处,通过定期的单元测试,又能促使学生经常系统地进行复习,有利于知识的巩固和强化。
2、编制平行性测试题,此类试题适用于对矫正生的检测。
即用以检测单元测试中的未达标者,在经过补救矫正后是否已达标。编制此类别试题应与单元形成性测试题是同质不同形的,即用不同的试题形式去检测同一目标。例如,检测“补钾原则”这一目标时,如果在单元形成测试中采用选择形式,则在平行性测试中可采用判断或填空题的形式进行检测。
三、反馈——矫正是对经测试反馈的未达标者及时补救矫正,使其达标。
1、课堂反馈矫正。
课堂测试反馈一般采用提问、回答、接力填空等形式,其中最常用的是课堂提问的形式,而课堂提问的形式主要适合于对个别学生,这与目标教学要面向全体学生的宗旨是矛盾的,为了解决这一矛盾,在提问时应使所提问的学生具有代表性和随机性。所谓代表性是指所提问的学生能代表全班学生中的某一部分,如优生、中等生或差生。要做到有计划有目的地进行提问检测,尤其对差生要多进行检测矫正。随机性主要是针对课堂教学的具体情况,在全班同学中随机地进行提问。笔者曾在上“急性阑尾炎”一节时,发现一位同学在上课时开小差,当时立即对她进行提问检测:“急性阑尾炎最有特征的症状是什么?”她回答是“腹痛”。这样通过提问,可及时地使她调整思维、融入课堂。虽然她答得不全对,但是通过提问既能起到对她及时补救矫正的效果,同时也能引起其他同学的重视(尤其是对提问的这一问题的重视),结果在单元形成测试中全班同学都能答对这一题。这样通过抓典型、抓代表,达到“牵一发而动全身”的效果,既能及时纠正课堂上出现的个别问题,又能调动全班同学的课堂积极性和主动性,因而能有效地提高教学目标达成度。
市建设经济运行信息管理系统是建立在j2EE框架基础上,其BLE(BizLogicHandler)是J2EE框架中的Domain层的实现;BPO(Business Persistence Object)是DAO与BO的结合体,对应J2EE中Persistence层的实现;Web层开发采用Struts框架。涉及各政府职能部门,和下属乡镇政府,辖区大中型企业、重点企业和新招商企业等诸多干系人,需要实现系统查询、问题反映、信息上报,信息审查,网上办公,跟踪督办,即时通讯,短信提醒,报表打印等主要功能。
对于应用系统的测试,我们划分为单元测试、部件组合测试、功能测试、性能测试和验收测试。其中重点关注了单元测试和性能测试,下面分别介绍。
单元测试阶段,我们采用开发人员自己写测试代码、小组内同级审查和测试组抽查相结合的测试策略。要求单元测试应用紧接在编码编译通过之后,鼓励进行测试先行(即先编写测试用例,然后用测试驱动代码的实现)。
单元测试工具采用junit测试框架。因为,我们的开发语言是JAVA,开发工具采用的是MYECLIPSE,而junit是当前JAVA自动化单元测试的实际标准,MYECLIPSE对junit提供了很好的支持。
对Action部分使用StrutesTestCase进行单元测试,StrutsTestCase for Junit是对标准Junit中TestCase的扩展,可以对Strus framework的测试提供方便。我们使用了其中的Mock object方法,测试Action objects、mappings、form beans以及forwords declarations,它不需要servlet引擎及web application container的环境,而且StrutsTestCase提供了许多“validation methods”,方便测试案例编写。我们采取的原则是,尽可能的把逻辑代码从jsp/servlet/action中移出,使用Junit作单元测试。该系统单元测试中面临两个脱离,脱离BizDelegate(封装了对Session Fa?ade 的调用过程,降低Application 层与Services层的耦合性)对action进行测试,脱离BPO对BLH进行单元测试,为此我们使用EaseMock技术,为一个接口创建一个模仿对象,将模仿对象作为参数来调用域代码,具体为测试者提供了抽取方法和工厂方法。
为了保证测试的质量,我们测试之初就设置了专门的测试小组。在单元测试阶段,该小组监控所有的测试活动和任务的执行情况,对测试的总体进行跟踪、控制和报告,对于类的提交,我们制定了严格的审核过程。首先,开发人员测试自己的类;然后小组内审查人员审查相应的类,打上已审查标记;最后,测试小组审核和抽查已审查的测试类和代码;测试小组还需要根据审核和抽查情况进行统计分析,调节测试资源分布。
在性能测试阶段,我们分为四个阶段实施;启动阶段、准备阶段和分析阶段。测试工具采用Rational Test Manager 2003,测试环境包括local computer和Test agent,Local computer作为测试平台的控制主机,负责整个测试的计划、设计、实现、执行和评估,作为Test agent的机器,统一接收由Local computer,最后由Local computer生成统计报告。在测试中我们也发现响应时间慢的问题,在经过对服务器的调优,以及相应部分的代码优化、SQL优化之后,性能得到明显改善。
下面简单介绍性能测试中我们对遇到的问题所采取的策略:
(1)该系统采用的是J2EE架构的一种模式,GUI客户端直接和服务器连接,采用的是BEA公司独有的T3协议,而且前自动化测试工具能够录制和回放脚本的大都是基于HTTP协议的浏览器客户端方式。对此,我们采取自动录制和手工编写脚本相结合的方式,对于浏览器客户端的测试,采用自动测试工具录制脚本;对于GUI客户端的测试,用JAVA配以性能测试工具提供的API包,手动或半手动编写测试脚本。
(2)该系统业务功能繁多,测试需要准备的数据量大,而测试时间短。我们分析出业务具有代表性的重要和关键用例,并且利用开发过程已有的客户端程序,减少测试脚本的开发量。
(3)该系统渠道多,与外部系统接口复杂,而且系统采用多家公司产品,如果出现问题,分析和定位困难。对此,我们利用性能测试检验客户和系统之间的交互,包括浏览器和GUI客户端等方式的连接。同时在进行性能测试的时候,将内部各种系统,与其连接的各外部系统的日志和监控工具全部打开,记录各部分的处理过程,这样当发现性能问题时,便能及时的定位瓶颈出现的位置;测试环境准备和测试时,请相关厂家的工程师提供现场支持,进行性能监控和问题分析。
由于采用了适当的测试方法、测试策略和测试工具,总体来看,我们的测试取得了不错的效果,有力地保证了项目的质量,XX市经济运行信息系统现已正式稳定的运行,也受到用户的好评,这是我们重视软件开发过程的测试保证软件质量的结果。当然也有不足的地方,具体存在以下几个方面;
(1)开发人员的测试观念还不够强,虽然我们制定了良好的单元测试策略,但开发人员并没有很好的执行,以至于在以后阶段的测试和运行中受害不浅。
(2)每种测试之前,我们都组织力量充分准备了测试方案,但是在测试数据的准备上,由于系统复杂性等多方面的原因,有些数据准备的不够完备。
要解决以上问题,我认为首先还是要树立开发人员的测试理念,只有从具体的开发人员做起,才能整整提高测试的质量,其次还要坚决贯彻执行项目中确立的测试方法和策略。
我们从实践中领会到,测试确实可以在保证软件质量方面起到很大的作用。但同时我们也认识到,测试中还有很多领域和知识需要继续研究和实践,新技术的发展对测试也提出了新的要求和挑战,我们将在测试领域不断探索,不断创新,为我国电子政务建设和企业信息化建设多做贡献。
作者:孟晓微 来源:科学与财富 2010年11期