时间:2023-01-24 13:46:06
序论:好文章的创作是一个不断探索和完善的过程,我们为您推荐十篇单元测试方法范例,希望它们能助您一臂之力,提升您的阅读品质,带来更深刻的阅读感受。
Abstract:The design of unit-testing case is one of the most important part of the unit testing,and it is an important guarantee for improving the software quality to design reasonable unit-testing cases.The article puts forward a designed method of unit-testing cases of a complex function,by introducing the cantata++ which is a testing tool and its function in unit testing,also considering that the true condition of making use of unit testing.This software unit-testing method is widely used in some other tastings and also well reputably.
Key Words:unit testing;cantata++;test case
1.引言
随着软件系统越来越复杂,在产品开发各阶段进行完全的软件测试也越来越重要,大多数软件开发者都已意识到这一点。但考虑到测试费用问题,软件开发者往往面临着在提高产品质量与减少费用之间进行选择的问题。IPL提供的Cantata测试软件应这种需要,在合理的费用下提供给软件开发者的强有效的软件测试工具。Cantata可以同时支持C和C++语言的测试,能够满足开发者进行高效的单元和集成测试的需求,该产品不仅能提高产品质量,还能帮助提高生产率。
作为专业软件测试工具,Cantata++除包含一些标准的特征之外,还提供了一些新功能:
(1)支持语句、判定和布尔代码覆盖率度量;
(2)支持运用白盒测试技术,自动获取私有类数据;
(3)支持面向对象测试用例的重用;
(4)图形化和XML形式的结果报告。[1]
2.单元测试用例的设计
软件质量的好坏很大程度上取决于测试用例的设计质量。不论程序员的编程水平、软件设计水平有多高,软件工程化执行得多好,如果没有通过合适质量的测试用例进行测试,其最终软件质量都是难以保证的。因此,测试用例设计是软件测试的最核心和最重要的内容之一。[2]
单元测试主要使用白盒测试技术,测试用例的设计方法一般分两种类型,即测试人员自己编写测试脚本和借助测试工具生成测试脚本框架后维护测试数据。Cantata++测试工具可用于生成和维护测试脚本,编译并运行测试可执行程序,查看测试结果和覆盖率数据。
3.基于cantata的测试用例设计方法
在cantata工具中常见的单元测试用例的实现方法很简单,不再赘述。本文主要介绍复杂函数实现的单元测试用例的设计方法。如单元测试的被测单元函数使用的函数形参是结构体变量和全局变量是结构体数组且结构体的成员是指针时,在设计测试用例时如何给结构体变量赋值?
3.1 函数的形参为结构体类型
Cantata测试工具自动生成的测试用例中,函数形参的默认值都是“NOT_SET”,编译测试脚本时不能被识别,给函数的形参赋正确的参数值是得到正确的测试结果的前提。设计带有结构体类型的形参的测试用例时,我们分别做了如下实验:
(1)按照在C语言中结构体变量成员赋值的方式给测试用例中的结构体变量赋值;
(2)使用改造C语言结构体变量成员赋值的方式把“->”改为“・”给测试用例中的结构体变量赋值。
编译结果证明两种赋值方式均不能被正确识别。
3.2 全局变量为结构体类型的数组变量,且其成员为指针
Cantata在自动生成测试用例时使用其本身封装的INITIALISE()函数给全局变量赋初值为0x55,以满足一般的测试需要。为达到充分测试的目的,需要给全局变量赋相应的数值,当全局变量为结构体类型的数组变量,且其成员为指针时,我们进行了如下实验:
(1)使用C语言中数组初始化的方式给结构体数组赋值;
(2)一个数组元素一个数据元素的方式给结构体数组赋值;
(3)使用分配内存的方式给结构体数组赋值。
编译结果证明三种赋值方式均不能被编译器识别。
结构体形参赋值时是不是因为该形参在赋值之前没有被分配内存空间所以无法赋值?结构体数组赋值的情况会不会因为cantata测试工具对编码规则要求较严格,必须按照相应的编程规则才可以编译通过?带着这种疑问我们查阅了大量编程规则的资料,通过反复实践,最终找到了解决该两个问题的办法。
其一,假设函数形参是如下两个结构体变量:
struct DIST* StrCount;
struct FILTER* StrFilter;
在测试用例脚本中可以通过下面的方式给结构体变量赋值:
StrCount = malloc(sizeof(struct DIST));
StrFilter = malloc(sizeof(struct FILTER));
memset(DIST_COUNT,0,sizeof(struct DIST));
memset(DIST_FILTER,0,sizeof(struct FILTER));
StrCount->cnt = 100; /*结构体成员赋初值*/
free(StrCount) ;
free(StrFilter) ;/*释放内存*/
如此赋值后的测试脚本文件加入测试工程后编译通过,得到了覆盖率测试结果,函数形参是结构体类型变量的测试用例设计的问题得以解决。
其二,假定定义如下的结构体数组:
PORT_CB g_PortCbTable[10];
其中:PORT_CB 为如下的结构体类型:
typedef struct
{
char num[16]; /* 端口名称*/
CONNOBJ* pObj; /* 端口句柄指针*/
}PORT_CB;
在测试用例脚本中,修改指针成员变量的方式为:
g_PortCbTable[0].pObj = (CONNOBJ*)-1;
g_PortCbTable[1].pObj = (CONNOBJ*)1U;
g_PortCbTable[2].pObj = (CONNOBJ*)1U;
g_PortCbTable[3].pObj = (CONNOBJ*)1U;
g_PortCbTable[4].pObj = (CONNOBJ*)1U;
g_PortCbTable[5].pObj = (CONNOBJ*) -12;
g_PortCbTable[6].pObj = (CONNOBJ*)2U;
g_PortCbTable[7].pObj = (CONNOBJ*)2U;
g_PortCbTable[8].pObj = (CONNOBJ*)2U;
g_PortCbTable[9].pObj = (CONNOBJ*)2U;
其中有后缀U或无后缀指明所赋常量的类型,强制转换类型不可以忽略。如此赋值后的测试脚本文件加入测试工程后编译通过,得到了覆盖率测试结果,至此全局变量为结构体类型的数组变量,且其成员为指针时,测试用例的设计问题得以解决。
4.小结
本文介绍了测试工具cantata的功能特性及其在单元测试中的应用,在此基础上提出了一种复杂单元函数的测试用例设计方法,该方法在类似的软件测试项目中得到了应用,在实践中取得了良好效果。
参考文献
[1]Cantata++ Reference Manual v6.1 2011,3.
[2]周伟明著.软件测试实践[M].电子工业出版社,2008:46.
关键词:
控制器局域网络;电子控制单元;批量测试;汽车电子;车载网络
中图分类号: 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。
基金项目:
灵敏度是反应载波通信单元的接收机通信能力的一项重要指标。在同样的低压集抄环境中,灵敏度越高的载波通信模块,抗干扰能力越强、通信距离更远、通信能力更加可靠。电力部门在采购载波通信单元时,需要通过低压集抄综合测试系统测试不同厂家生产的载波通信单元的通信能力,尤其是接收机灵敏度参数。
目前行业内对载波通信单元灵敏度的测试方法相当麻烦、简单、粗略,通常使用固定值衰减法测试。固定值衰减法测试时,需要不断跟换不同衰减值的衰减单元,操作不便,且一般衰减值都是10的整数倍,如此一来,只能大概判断载波通信单元接收灵敏度,无法实现精确测试。
程控衰减法就是研究对电力线载波强电信号进行可上位机程控式衰减的一种方法。它的原理就是首先将220V强电与系统隔离开来,提取出被测的载波信号,然后输入衰减电路,通过程控上位机可以设置0-120db,步进≥1db(最小单位1db)的信号值衰减,载波信号被衰减后,再耦合至电力线,输出给载波接收设备。最终通过程控衰减器的具体衰减值以及被测载波接收设备是否正常接收到信号,来计算得载波接收设备的灵敏度。
本文采用的程控衰减法是用来精确测试低压载波通信单元灵敏度测试的一种方法。
1 程控衰减法的电路实现方法
程控衰减法的电路实现就是实现一种程控衰减器,包括了载波隔离滤波电路和通信主板电路、程控上位机,系统框图如图1。
1.1 载波隔离滤波模块电路组成及作用
1.1.1 载波信号隔离电路
通过串联谐振的方法,滤除非载波信号,通过耦合变压器将市电220V与载波通信信号隔离开来,保证整个系统的安全性。
1.1.2 滤波电路
由电阻、电容、电感构成串联谐振以及并联谐振,起到滤波作用,当需要某载波频率f的信号时,则需要计算匹配RLC参数,只有该频率附近的信号可以通过。计算公式是谐振频率
(1),品质因数
(2),在满足其他参数情况下,Q越大越好,通过计算插入损耗值计算电阻R的取值。
1.1.3 过零检测电路
当检测到50Hz市电正弦波经过零点时,将判断信息传送给MCU处理器。因为载波通信是在市电过零点时发送数据,所以过零检测也是十分重要的。
1.2 通信主板
1.2.1 稳压集成电路
为整个系统提供稳定、安全的直流电。
1.2.2 衰减电路
内置各种高精度贴片电阻网络,分别可以实现1db、2db、4db、8db、10db、20db、30db、40db信号衰减,通过不同的电阻网络导通组合,可以实现对载波信号进行0-120db衰减,具体电阻网络组合方式由MCU控制。
0-120db衰减值对应电阻网络选择组合方式如表1。
从表2看出,选择电阻网络的组合方式,可以直接实现0-115db的信号衰减,载加上程控衰减器其他电路固定衰减值5db,通过正确的组合,就能实现0-120db信号衰减。
1.2.3 微型处理器MCU控制电路
地位相当于“大脑”,它处理上位机发送的信息,实现对衰减电路的控制。
程控衰减法的实现依赖上述电路功能的实现。
1.3 程控上位机
通过键盘、鼠标就可以对程控上位机进行各种操作,程控上位机可以直观设置和显示衰减值,操作简便、直观、人性化。
1.4 程控衰减法测试载波通信单元灵敏度框图
程控衰减法的实现需要依靠程控衰减器,程控衰减器与载波通信单元的连接如图3所示。
2 测试载波通信单元灵敏度步骤
以下为使用程控衰减法测试载波通信单元灵敏度的步骤:
第一步:根据已知载波频率,通过计算公式(1)算得出滤波电路中R、L、C具体匹配参数。
第二步:根据匹配参数,做好对应的载波隔离滤波电路模块,并且将模块插入对应的位置中。
第三步:通过程控上位机,设置程控衰减器的衰减值为0db,被测载波发送设备发送符合测试标准的载波信号。
第四步:被测载波接收设备能正常接收载波信号,然后通过上位机不断加大衰减值步进值为-10db。
第五步:假如现在程控衰减值为-70db时载波接收设备能正常接收信号,程控衰减值为-80db时无法接收信号,那么将衰减值从-79db开始按照步进值1db,不断减小,直到载波接收设备能正常接收信号为止。
第六步: 假如当程控衰减值等于-75db时,载波接收设备刚好能正常接收数据,那么载波通信单元的接收灵敏度等于-75db加上程控衰减器其他电路的固定衰减值-5db,最终得到载波接收设备灵敏度等于-80db。
3 案例分析
为了充分说明该方法,以421KHz载波频率的载波通信模块测试为例。根据相关计算公式(1)计算,得出滤波电路中的R、L、C参数如表3。
使用程控衰减法测试421KHz的载波接收设备灵敏度数据记录如表4。
表4中的输出衰减值,可以直接通过程控上位机设置并且显示出来,观察表4记录表,可以得出载波接收设备的灵敏度等于-75db加上电路固定衰减-5db,等于-80db。
4 结束语
要实现对不同载波频率的载波通信单元接收灵敏度的测试,首先通过计算得出载波隔离滤波模块电路中RLC匹配参数,通过该电路,滤除非测试频率的信号。然后通过调节合适的信号衰减值,来确定载波通信单元的灵敏度。本文研究了基于程控衰减法测试载波通信单元灵敏度方法,总结出测试载波通信单元灵敏度的测试步骤。通过对421KHz载波频率的载波通信单元灵敏度测试分析,精确的测试了该模块的接收灵敏度等于-80db,验证了该方法的可操作性和有效性。
参考文献
[1]高锋,董亚波,等.低压电力线载波通信中信号传输特性分析[J].电力系统自动化.2000
[2]戚国光.基于OFDM的电力线载波通信系统的研究[D].长沙:湖南大学,7-35.
[3]Zho Wen.110dB Voltage controlled attenuator.JournalofMicrow aves,1993(3):127
中图分类号:G642文献标识码:A文章编号:1009-3044(2008)35-2435-02
Object-oriented Unit Testing of the Case Teaching Method
ZHENG Li-xiang
(Quanzhou Senior Technical School, Quanzhou 362000, China)
Abstract: This article describes a software testing in the curriculum, students have learned the combination of Java-related knowledge, the case teaching method used to explain the object-oriented unit testing the contents of teaching so that students can understand the theory of knowledge can master the practical skills and to improve their interest in learning to cultivate the ability of students.
Key words: Java class; object-orient unit test; test case
1 引言
面向对象的单元测试(简称为OO Unit Test)是检验面向对象程序最小单位,即检查类有无错误的测试工作。因为类是面向对象程序中最基本的单位,所以对于类的测试必须要100%通过,这样面向对象单元测试就显得非常重要了。面向对象的概念及程序设计方法本身就是一个难点,那么要帮助学生理解和掌握面向对象单元测试就更困难了。学生们对此也觉得很枯燥,听不懂,学不会,最后放弃了。为了让学生掌握这方面的知识和技能,我采用的方法是以Java类为例,讲解面向对象单元测试的基本操作过程,以案例代替概念,理论与实践相结合,采用案例教学法。
为什么要采用Java类作为案例进行教学呢?这主要是考虑到以下两点:
一是Java语言是当前应用前景非常好的软件设计开发语言,现在的计算机专业一般都会开设这一课程,并且是在《软件测试》之前开设,学生有知识基础。
二是Java语言是纯面向对象的语言,它摒弃了C/C++中的一些不易掌握的结构,如指针等,其最小处理单位就是类,而且Java语言的程序非常简洁,理解起来比较容易。
当然作为案例的Java类不能太难了,否则一开始学生就看不懂该Java类的功能,更不用说理解该类的测试过程了。
为了让学生能够掌握面向对象单元测试技术,我根据学生的知识水平,选用合适的被测试的Java类,为其设计测试用例,执行测试并生成测试文档,用完整的案例进行教学。
2 针对面向对象语言的特征,选择自动化的单元测试方法
在一个典型的软件项目中,有两种类型的测试最为重要:程序员测试和用户测试,或称为单元测试和验收测试。单元测试由程序设计师自行编写测试代码,目的在于验证程序设计师所撰写的代码是否依据其所设想的方式执行而产生符合预期的结果。即验证程序代码的正确性。如果是对采用面向对象方法设计的软件进行单元测试,就是面向对象单元测试了。
通常,在进行面向对象的单元测试前,我们都要分析几个问题:
1) 面向对象的单元测试的对象是谁?
2) 采用人工测试还是自动化测试?
3) 如果是自动化测试,那么使用什么样的工具合适?
4) 如何进行面向对象的单元测试?
对于不同的程序代码来说,以上的问题可能都有不同的答案与之相对应,那么如果使用的是Java语言所编写的代码的话,该怎样决定呢?
首先,我们知道Java语言是一种高级的、通用的、完全面向对象的程序设计语言,其程序的基本处理单位是类。所以单元测试的对象就是类,即Java的单元测试指的是面向对象的单元测试。
其次,随着软件的复杂程度越来越高,面向对象单元测试的工作量也随之增加了,若采用人工测试恐怕难以完成。因此,自动化的单元测试要比人工测试要来得适用。再者,自动化测试的另一个好处是能生成测试文档,这样也可以减少文档的撰写工作。
当然,如果选择了自动化测试就需要工具来支持了,使用何种工具比较合适呢。在此,推荐使用JUnit,这是一种轻量级的测试框架。JUnit是一个开发源代码的Java测试框架,用于编写和运行可重复的测试。它是用于单元测试框架体系xUnit的一个实例(用于Java语言)。主要用于白盒测试,回归测试。JUnit一般不需要另行安装,通常集成的程序设计平台,如Eclipse、JBuilder等都会装有JUnit。
3 设计简单的Java类的单元测试用例来解析面向对象单元测试
3.1 选取待测试的Java类
为使学生更易理解,案例的选择要先易后难。我们可以用HelloWorld为例说明JUnit是如何进行单元测试的,因为每一种语言在其学习用书的第一个例子通常都是HelloWorld,它最简单了。以下是代码:
// HelloWorld.java
packageHelloWorld ;
public class helloWorld {
public String sayHello( ) {// 返回测试字符串的方法
returnstr;
}
private String str;
}
3.2 设计测试用例,帮助学生掌握测试步骤
为了对HelloWorld类进行测试,我编写了以下测试用例,它本身也是一个Java类文件。代码如下:
// HelloWorldTest.java;
package hello.Test ;
import helloWorld.*;
import junit.framework.*;// 引入junit.framework包
public class HelloWorldTest extends TestCase{
//继承TestCase类
public HelloWorldTest ( String name ) {
super ( name );
}
public static Test suite ( ){
returnnewTestSuite ( HelloWorldTest.class );
}
public static void main ( String args[] ) { //主方法
中图分类号: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.
单元测试是软件检测的主要任务之一,主要分为两种不同形式:
(1)建立在标准的基础上,利用黑盒来进行单元测试,来进行测试。
(2)建立在程序主体产生基础上,利用白盒检测系统和程序的逻辑性和合理性。
1 面向程序的单元测试弊端阐述
对于单元测试来说,其自身弊端不能忽视。包括文件性质自身弊端OPEN语句错误CLOSE语句错误,在缓存时,其缓存内存量和记录长度不符合,正文编写错误等等问题,会对整个系统的板块和数据带来影响。其次,测试错误处理现象的发生,也会影响描述正确性无法对错误定位,对板块和系统产生干预。
2 AOP编程阐述
2.1 1AOP编程重要性
AOP编程思想是社会发展的产物,是科学技术和社会经济发展的产物,具有时代性。对AOP编程思想发展背景进行分析和研究,发现AOP编程思想产生于1997年西方国家召开的编程论坛会议上,西方国家的研究人员,在编程会议中给出AOP编程这一理论思想。
单元检测,也被叫做板块检测,其主要服务对象为软件系统中的最小板块,针对系统中最小板块,来判断程序中板块的正确性。软件开发和设计的不断发展,增加了软件的种类和复杂性,增加软件测试的难度,增加单元测试的复杂性。面对这一发展形势,为了保证软件开发有效运作,保证软件的实际应用性,我国开始对软件测试和开发方法进行深入研究和分析,在长久的研究工作中,发现AOP编程思想具有实际应用,可以满足软件开发要求,满足单元测试发展目标。站在世界角度来说,增加AOP编程思想关注,对整个世界经济发展具有重要意义。
3 AOP编程思想在面向对象程序的单元测试应用
AOP编程思想在面向对象程序的单元测试应用,包括在对象程序单元测试应用,在契约的单元测试,独立单元检测应用。
3.1 AOP编程思想在面向对象程序单元测试步骤
对于AOP编程思想在面向对象程序应用来说,主要是对程序系统进行简化,简化为银行板块的模式,来对单元进行测试。AOP编程思想在面向对象程序应用主要包括以下几点内容。
(1)对系统的代码进行测试,对存在的与消费有关的信息和数据进行反馈,保证不同数据和信息积分反馈的真实性和准确性。详细来说,系统代码检测主要包含三个不同性质的对象,存钱、消费和取钱主体等等。系统代码可以对着三个不同主体的信息记录和代码件反馈。
(2)可以利用账户的优势,利用ID对使用账户和新增加的账户展开管库,保证了主体管理的可持续性,保证管理周期最大化。
(3)transfer具有自身的优势,这一方法可以展现不同账户的信息,增加了和账户的联系性,保证服务的完善性。
3.2 契约的单元测试
在对AOP编程思想在面向对象程序单元测试分析后,发现在利用传统的银行代码中,具有自身的便利性,但是也会存在众多问题。例如:BankAccount这一系统中,运作形式类别简单和便捷,但是其却会在应用过程中,出现数据和参数为零的现象,导致不同使用账户的财务为负数形式。面对这一发展现象,可以增加契约检测力度,来避免这一弊端的产生。契约单元测试主要包括以下两种形式。
(1)利用JAVA系统来运作。1.4系列是JAVA具有代表性的系列,其具有断言能力,满足契约检测的要求。
(2)对契约形式再次构建,保证设计的合理性和构建的科学性。这一构建工作,主要是针对技术来说,对服务主体对象应用技术展开设计,可以保证单元测试的完整性,保证软件的实际应用性,提高软件质量。
3.3 独立单元检测
独立单元的检测和测试具有自身的优势,降低了单元测试难度。例如:对于独立单员中存在遗留的代码来说,运作和替代具有自身难度,利用传统的检测方法,无法保证测试的真实性。在面对这一现象,可以利用AOP编程思想优势,对独立单元进行隔离处理,把单元换分为几个系统和板块,在一一处理,在保证单元独立性基础上,增加了对不同板块信息了解。其次,也可以利用Mocks这一方法展开测试,增加测试主体的协作性,对独立单元进行划分,给予隔离层。辩证来说,Mocks这一方法不具有逻辑性,无法满足逻辑需求。总的来看,AOP编程思想在独立单元检测中具有自身的应用优势,可以对系统中代码进行修改,和模仿主体的性能类似,利用ID来查找账户的信息,并把测试结果展现在系统中。
4 结束语
AOP编程思想是社会发展的产物,具有自身特点,可以利用账户的优势,利用ID对使用账户和新增加的账户展开管库,保证主体管理的可持续性,保证了管理周期最大化。
参考文献
[1]楼程伟,陈丽红.关于计算机编程思想与AOP编程思想的研究[J].电脑知识与技术,2015(24):52-53.
[2]谢林.AOP思想在项目中的应用与研究[J].电脑知识与技术,2010(15):4130-4132.
[3]杜玲玲.AOP技术在国库集中支付系统的应用[J].计算机应用与软件,2009(03):190-191+204.
[4]赵艳,刘同明.面向方面软件开发在J2EE企业应用系统中的实现[J].计算机技术与发展,2008(10):225-229.
[5]张永.AOP技术在自助设备运行管理系统中的应用[J].中国金融电脑,2008(08):91.
作者简介
1 软件测试简述
软件测试是在软件投入商用前,对软件需求分析报告、设计规格说明书和编码的最终复查,是软件质量保证的关键方法,软件测试并不等于程序测试。它贯穿于软件定义和开发的整个过程,因此,软件需求分析、软件概要设计、软件详细设计和程序编码等各阶段所得到的文档,包括需求规格说明书、概要设计说明书、详细设计说明书,以及源代码都是软件测试的测试对象。随着软件规模的不断扩大,以及软件设计复杂程度不断的提高,软件开发中出现失误或缺陷的概率越来越大。随着市场对软件质量重要性的认知程序的提高,因此软件测试在软件项目实施过程中的重要性尤为突出。软件测试将会成为一个具有很大发展前景的行业,市场将需要更多具有丰富测试技术和先进管理经验的测试技术员和项目经理。
2 软件开发项目测试的误区
软件测试从1990年左右进入中国,目前国内大的测评中心、大型企业已经完全掌握了软件测试的测试策略和测试方法。小企业普遍存在测试人员不懂什么是单元测试,怎样进行单元测试,很少能看懂代码的细节。而开发人员很少能够提供完整的详细设计报告、需求报告。导致单元测试,以拼凑测试报告为目的。
认知误区一:软件测试是软件开发的最后一道步骤,工程师们一般认为,软件实际项目要经过下面六个阶段:需求分析,概要设计,详细设计,软件编码,软件测试,软件。因而,认为软件测试只是编码后的一个孤立的阶段,这就是不了解软件测试流程的认知偏差。软件测试是一个系列的活动过程,是一个开放的体系,包括软件测试需求分析,测试计划设计,测试用例设计,执行测试。从而,软件测试应当贯穿于软件项目的整个生命周期,并不是软件开发后最后一道步骤。认知误区二:软件商用后如果发现质量问题,就武断认为是软件测试人员的工作失误。这种认识很狭隘,很是打击软件测试人员的工作积极性。软件测试只能确认软件存在错误,不能保证软件没有错误。因为从根本上讲,软件测试不可能发现全部错误,软件后的错误可能来自软件项目中的各个过程。认知误区三:软件测试对测试人员技术要求不高,任何人都可以做。很多工程师认为软件测试就是安装并运行程序,按按键盘的重复性工作。随着软件测试技术的不断改进和完善,新测试方法、新流程、新工具都在不断被开发出来。这就需要软件测试工程师掌握和学习很多专业测试新理念和新技能。认知误区四:只有编写程序的高手才是软件专家,而软件测试没有前途。由于我国软件行业整体研发能力比较低,软件开发过程不规范。不少软件项目的开发都还停留在“累加堆叠“阶段。项目开发依靠个别程序员决定,他们一人负责总体设计和代码编写,给人的印象是程序员是真正的牛人,完成了所有的软件项目开发工作。但在微软等世界知名软件企业里,软件测试人员的待遇和数量与一般程序员没有多少差异,优秀测试人员的待遇甚至比普通程序员要高的多。
3 嵌入式软件单元测试流程
单元测试是指对软件中的最小可测试单元进行检查和验证。单元是规格说明书中的最小单元,包括函数、子程序、程序。单元测试关注独立的函数功能,是测试过程中最低级别的测试活动。需要开发一个或多个测试用例执行单元测试。把代码问题缩小范围在开发阶段锁定Bug是单元测试的主旨要求,以下将介绍一种容易操作的嵌入式单元测试实战流程。
第一阶段,制定测试记录表,记录测试过程,和测试情况。测试记录表包含:源文件名,子函数名,用例标号,用例名称,用例个数,用例通过个数,语句覆盖率,分支覆盖率,MC/DC覆盖率,测试结果,问题描述,测试人员,测试时间。针对第一阶段的测试结果,此时需要大家分析出问题的代码,各抒己见,总结问题,给出解决方法。
第二阶段,解决部分测试用例failed问题,找出阻止生成用例的共性。常见问题汇总:局部变量未初始化,调用函数未声明,局部变量直接赋值,结构体嵌套、结构体指针、声明问题、声明位置问题,函数指针,大循环、死循环,绝对地址,指针变量,C语言程序中带有goto语句。解决办法:局部变量声明后,需要赋初值再使用。调用函数未声明,该问题发生在隔离测试阶段,属于代码书写不规范问题。解决方法:自定义的函数都需要在头文件中做统一声明。局部变量直接赋初值:该问题发生在测试用例无法生成阶段,属于代码书写不规范问题。解决方法,结构体局部变量,指针变量需要先声明后赋初值。结构体嵌套、结构体指针、声明问题、声明位置问题:该问题也属于代码书写不规范问题。解决方法:根据MISRA代码书写规范,结构体需要放在头文件中统一声明。大循环、死循环:单元测试需要有程序结束的出口。解决方法:把大循环改为小循环,注释掉死循环(if(1)、for(; ;),while(1))。绝对地址:单元测试不连接真实的硬件设备。遇到寄存器等绝对地址时,需要对寄存器做变量处理。指针变量:需要声明一个同类的数组,然后把数组的首地址,赋给指针变量。函数指针:需要虚构一个函数实体,取函数地地址赋给函数指针,完成映射。C语言程序中带有goto语句:需要改变程序结构,增加判断语句,去除所有的goto语句,以便确保C语言程序的稳定性。
测试第三阶段:基本圈复杂度高于MISRA阀值要求的函数,先考虑把复杂函数改为几个小函数。改不了的由开发人员写声明以及具体原因,再按照路径分支来设计测试用例。汇总测试结果,提交测试问题报告单,并提交行业标准测试报告。
4 结束语
文章简述了软件测试的基本概念,澄清了软件测试工程实践中的几个误区,依据单元测试实践的具体案例,介绍了一种高效、容易操作的嵌入式单元测试的流程。
参考文献
[1]胡丹,杜新华.基于目标机的嵌入式软件单元测试[J].电子测量技术,2006(2).
[2]赵正海,王宁.跟踪雷达“指示引导”功能软件测试方法研究[J].现代电子技术,2013(36).
[3]于园园.软件测试技术与测试管理研究[J].江苏科技信息,2016(7).
[4]王琨.嵌入式计算机软件测试关键技术探讨[J].科技创新与应用,2016(7).
[5]张金环,田洪涛.浅析设备软件测试与质量保证[J].电子工业专用备,2016,45(1).
一、在课前通过诊断性测试,获得学生在学习新内容前的知识反馈,为上新课做好准备。
诊断性测试一般安排在新学期或新开课前进行,测试时间一般5~10分钟,测试应侧重于考查学习新课所需要掌握的基本知识和基本技能。例如,在上动物模拟人体手术实验课前,先测试学生关于无菌技术和无菌原则方面的知识并补偿,由此提高他们的学习外科手术的前提能力,最终提高实验目标。
二、在课前或课后,通过形成性测试了解学生的达标情况,及时查漏补缺。
1、编制形成性测试题,包括课堂测试题和单元测试题,要确保适合各自的特点。
(1)课堂测试题,要适合在课堂教学中进行测试。课堂教学时间一般以二学时为单位,共80分钟。其中用以进行课堂测试及反馈矫正的时间通常只有5分钟,故编制此类试题要突出重点,考虑课堂操作的可行性,试题量不能过多。例如,在“复苏”一章编制的课堂测试题为:①快速诊断心脏骤停的方法;②心肺初期复苏的ABC步骤;③心脏按压有效的标志是什么;④心肺复苏有效的指标是什么等。这些题中包括了本章的重要知识点,学生掌握后,在遇到心脏骤停病人时就会懂得如何去诊断和处理,而且试题量适中,便于在课堂上进行测试和矫正。
(2)单元测试题,即教师根据教学的情况,一般按章节划分为一个教学单元,每学完一个单元后进行一次单元测试,以评价学生的单元达标情况。单元达标测试覆盖的目标范围较大,而且每一目标都应有相应的检测题,测试时间为20~30分钟,测试内容多时间少,因此编制此类题主张多用选择题和判断题,少用填空题、名词解释和问答题,以方便学生答题,做到既能检测目标又不影响课堂授课。此处,通过定期的单元测试,又能促使学生经常系统地进行复习,有利于知识的巩固和强化。
2、编制平行性测试题,此类试题适用于对矫正生的检测。
即用以检测单元测试中的未达标者,在经过补救矫正后是否已达标。编制此类别试题应与单元形成性测试题是同质不同形的,即用不同的试题形式去检测同一目标。例如,检测“补钾原则”这一目标时,如果在单元形成测试中采用选择形式,则在平行性测试中可采用判断或填空题的形式进行检测。
三、反馈——矫正是对经测试反馈的未达标者及时补救矫正,使其达标。
1、课堂反馈矫正。
1.软件测试
软件测试是指利用相关测试工具,按照一定的测试方案和流程对软件系统的功能和性能进行测试,对可能出现的问题进行分析、评估,发现开发错误并跟踪,以确保所开发的软件满足用户需求。软件测试是保证软件质量的主要手段,是根据软件开发各阶段的规则说明和程序内部结构而精心设计的一批测试用例,并利用这些测试用例运行程序以发现软件是否存在错误的过程,软件测试的范围应当包括更广泛些,除了考虑正确性外,还应关心程序的效率、健壮性等因素。
软件测试过程包含单元测试、集成测试、确认测试和系统测试四个步骤:
(1)单元测试:对每一个程序单元进行独立测试,检查各程序模块是否正确地实现了预定的功能。
(2)集成测试:把已通过测试的模块组装起来,对软件体系构造的正确性进行测试。
(3)确认测试:检查已完成的软件系统是否已满足了需求规格说明中的各项需求,软件配置是否完全、正确。
(4)系统测试:将经过确认的软件系统置入实际的运行环境中,与其它系统成份结合在一起进行测试。
2.单元测试
单元测试又称模块测试,是以软件系统设计的最小单位——程序模块为对象,进行正确性检验的测试工作。单元测试常被看作编码的附属品,在代码被开发、编译调试、审查后,单元测试用例设计便开始了。进行充分的单元测试,是提高软件质量,降低研发成本的必由之路。几乎所有的开发人员都会对每一段代码做一定程度的单元测试。如果一个模块要完成多项功能,可以将该模块看成由几个小程序组成,对每个小程序分别进行单元测试。如果是关键模块,往往还要做性能测试。
单元测试以详细设计说明书和源程序清单为依据,常采用白盒测试的用例,辅之以黑盒测试的用例,以寻找模块内部可能存在的错误为目的,主要完成模块接口测试、局部数据结构测试、路径测试、错误处理测试、边界测试等任务。
(1) 模块接口测试
单元测试开始时,要对通过被测模块的数据流进行测试。包括调用该模块的输入参数的正确性、调用其子模块时提供参数的正确性、全局变量的定义在各模块中是否一致等。
(2) 局部数据结构测试
包括数据类型的一致性、变量名、变量赋值、全局数据对模块影响的正确性等检验。
(3) 路径测试
对基本执行路径和循环进行测试,查找由于错误的计算、不正确的比较或不正常的控制流而导致的错误。
(4) 错误处理测试
检测对错误条件的响应是否正确,错误描述是否与实际的错误是否相符、是否能够对错误定位、是否易于理解等。
(5) 边界测试
通过设定边界值检测数据流、控制流中等于、大于或小于比较值时出错的可能性。
在面向过程编程时代,单元测试所说的单元一般是指函数,而在面向对象编程时代,单元测试所说的单元一般是指类。以类作为测试单位,测试的复杂度相对较高,所以目前通常采用的办法是为软件开发建立对应的测试工程,为每个类建立对应的测试类,为每个函数建立测试函数测试结构化的局部代码。
3.单元测试用例的设计
测试用例是指对某特定的软件系统进行测试任务的描述,它体现了测试的方案、方法和技术,包括测试目标、测试环境、输入数据、测试步骤、预期结果、测试脚本等,并形成文档。
测试用例的设计也就是测试需求细化的过程,测试需求分析和测试用例设计是密不可分的,前者是后者的依据,后者是前者的体现。测试用例的设计应与复审相结合,根据相关设计信息设计测试数据,以增大发现错误的可能性。
单元测试用例可以选取正确输入、边缘数据和错误输入作为测试数据。以系统用户注册模块中出生年、月、日的设置为例,通过等价类划分法设计测试用例。
在高中英语教学中在对一个单元进行完整教学后,进行一次英语单元测试是必要的。由于一个单元有知识范围窄、相对涉及面小等因素,所以如何从语言学的角度在一定的范围内对学生理解和英语语言掌握的程度进行全面测试,需要作出一番认真的思考命题,才能达到应有的效果。同时,一套好的单元测试应该是注重学生的语言能力基础和语言运用能力的层面上,不仅对它进行检查测试,更重要的是对学生的基本英语语用技能和综合运用能力起指导的作用。现行教材注重学生的口语交际、听说能力的培养,语言知识在生活中的实际运用,这就要求命题者抓住这一功能,对学生进行语言能力的全面检测。就英语单元测试如何选题的策略,我在教学中作了一些尝试,与广大同仁共勉。
一、注重选择有代表性的题目
在英语教材中有很多单元,而每个单元又含有若干个知识点,具体包括语言知识(如词汇、语法、句型等)和文化知识,也包括已知的知识和未知的知识。教材有步骤、有程序地介绍了一些语言和文化知识,潜藏了很多语言信息,但是为了检测学生在学习相关的知识,能否灵活运用,这就要求命题者在有限的测试题目中容纳尽可能多的信息。因此,命题者可以提出若干个预选命题方案,然后借助预测测试的结果,对不同的方案进行多方位在难点、能力考查、实际运用等方面有代表性的题目。一般情况下,代表性的题目包含重点题、典型题及综合运用题等,它们可以体现在不同的题型中。命题者不能命语言测试建立在难、偏、怪,能难倒学生的难题,一方面挫伤了学生的积极性,另一方面,题目不具有代表性,不能起到考查本单元知识掌握的程度。代表性的题目只有在“抓纲务本”的精神指导下,才能获得以点带面、触类旁通的效果,才能体现出语言测试的特点。
二、要注重选题的典型性
英语教材中的单元教学内容安排是“秩序渐进、循环反复”地不断操练英语基础知识的,但是英语对中国学生而言,学习的策略方面各有不同,学生往往会对一些知识存在理解上或应用上存在不同疑惑,所以命题者的选题要能够让学生在一定程度上借助于测试的手段观察、发现、探索和研究其自身语言学习上的差异。比如,当今的中学英语语言测试体系不能体现出学生“说”的能力,所以命题者在选题的过程中,要切合于语用学的实际,参照“任务型”教学活动目标,有意识、有策略地通过单元测试的题型的转变,将“说”的能力测试融于“听”的测试中。这样的单元测试的命题导向就是针对学生之缺,了解学生之愁。此外,命题者要结合教学实际中的学生在平时作业中的“常见病”和“多发病”,选编一些“对症下药”的治病题,这也是具有针对性意义的。比如:look for与find的用法的差异性就可以成为测试的内容。
三、要注重选题的多用度
在英语单元测试中的多角度是指在一例的题目中容纳多个知识点或能力点的考查,训练学生运用“一题多思”的思维方式。由于当今的英语教学模式侧重于“任务型”和“交际型”的活动,这就要求学生具备能在不同层次、不同形式的情景中,综合应用语言知识完成语言任务的能力;这也就要求测试题目能体现出不同知识点之间的纵横联系,能检测学生的综合分析问题和解决问题的能力。也就是说测试题灵活性要起到影响试题区分指数的作用,这也就有利于指导教师将来的授课行为,有利于培养学生的解题思维。比如说,完形填空的空白就显示了对两种语言模式(一者是作者表达自己的思想的语言模式,一者是读者根据自己的理解作出的猜测性语言模式)和一种测试意图(命题者的测试目的),避免了就题论题的俗套。当然,命题的灵活性的特征要体现在与教材的关联性上,并不是指“难”、“偏”、“怪”。
四、要注重选题的可信度和准确性
英语单元测试题目的好坏应是建立有可信度和准确的基础上的语言信息(包括知识和能力)的检测。它必须达到巩固知识和培养能力甚至对未来教学活动的目的有针对性。一个单元的知识体系,在语言知识上要学生追求多方位,在学习能力上对学生讲究多层次。但是在英语单元测试中,测试题应当有一定的可信度和准确性,不能胡子眉毛一把抓,把握好以一个单元的内容为基础,对学生进行有的放矢的检测。
五、要注意选题时侧重训练学生思维能力的培养
要培养学生的自学能力,英语教材中有大量体现了学生思维能力训练的内容,因而英语单元测试应该体现英语思维检验的自主性。
所以英语单元测试也应该体现出英语思维的策略性。试题中一定程度地突出解题方法的训练可以培养学生的综合测试的能力。这些测试题目的选择,能够培养学生独立思考问题及解决问题的能力,从而避免学生在题海的幻觉中去摸索所谓的方法,使学生的思维形成定势。
总之,一套科学的单元测试题能够对学生知识的培养起导向作用,培养学生的英语知识运用能力,培养学生的学习思维方式,提高学生的学习效率,扩充学生的知识。