唐跃川,赵渝洁,饶义琼
(重庆金美通信有限责任公司,重庆 400030)
随着软件业的日益壮大和逐步成熟,软件测试也在不断发展。从简单的开发人员自行调试逐渐往规范化、流程化的方向发展。其活动过程十分复杂,如果不借助辅助工具,仅靠人工处理,则不仅效率低下、工作量巨大,而且可能出现无法解决的问题。而单元测试又对测试人员的从业素质提出了更高要求。鉴于以上问题,利用一套好的单元测试工具来帮助软件测试人员提高工作效率,提高工作质量,改善工作条件是非常有必要的。
C++Test是美国Parasoft 公司研发的一款针对CC++的单元测试工具,具有自己的专利技术,其功能覆盖了从代码静态检查到仿真代码运行环境进行动态检查,以及自动生成测试用例和回归测试等方方面面,从横向的测试宽度和纵向的测试过程都能够给软件单元测试提供足够的支持。
C++Test 提供了以下一些功能:
(1)静态代码检测。C++ TEST 内建了包括MISRA C++2008 在内的共1456种编程规范,用户可根据实际需要选择符合自己要求的规范来对代码进行静态编程规范检测。
(2)BugDetective(C ++ Test 专利技术)。通过搜索代码中的“可疑点”,开始分析正在测试的源码。可疑点是潜在的错误点。这些可疑点在Bug-Detective 规则中被定义。只要识别了可疑点,Bug-Detective 就调查导致该可疑点的可能执行路径,并检查是否有任何确实违反BugDetective 规则的路径存在。如果找到了这样的路径,就报告一个违例。
(3)单元测试。用户可根据需求,配置TestConfiguration,进行异常测试,功能测试,回归测试。
(4)自动生成测试用例、驱动函数、桩函数。根据用户配置的TestConfiguration,自动生成单元测试所需要的测试用例、驱动模块、桩模块,并且用户可以添加、修改、删除这些自动生成的模块以达到精确测试的目的。
(5)TCM(团队配置管理)和CVS(源码控制器)。TCM 主要用于一个项目或者一个公司级的测试配置、抑制条件、规则文件和测试用例文件的共享,C++TEST 支持与CVS的连接来支持共享源码和相关测试资源。
(6)GRS(组报告系统)。用于向项目管理者、软件设计总师、软件开发人员提供基于角色的报告。
做单元测试最大的问题就在于驱动函数和大量桩函数的编写,这将占用测试人员大量的时间并且要求测试人员必须拥有比较丰富的编程经验,现在,C++TEST 可以帮助我们完成这个复杂的工作。
其执行过程如下:“Generate Unit Tests”→“Generate Stubs”→“Build Test Exectable”→“Run Unit Test”,其中“Generate Unit Tests”产生驱动函数,“Generate Stubs”产生桩函数。所产生的驱动函数和桩函数均保存在用户指定的工作空间内,可修改。
执行“Generate Stubs”后,可以从用户指定的工作空间中找到C++TEST 自动产生的桩函数如图1所示。
图1 C++TEST 自动产生的桩函数
用C ++Test 对某型交换机的嵌入式系统(Vx-Works)运行程序(开发环境:Tornado2.2)进行静态代码测试。在系统环境变量下面添加PATH 变量的值如下:
从GUI 面板中直接导入Tornado 工程,方式如图2所示。
然后执行:“Test Using”→“Builtin”→“Static Analysis”→“MISRA C++2008”。执行完成后察看C++TEST的违规报告如图3 所示。
在C++Test的主面板中执行:“Test Using”→“Builtin”→“StaticAnalysis”→“BugDetective”。我们选择的程序中包含以下的函数语句:
执行“BugDetecctive”后,C ++TEST 报告一个除0的违例。显然,当min(x,y,m,n)函数的返回值为0时,出现除0的情况。该功能还能查找出使用未初始化内存、空指针解除引用、内存和资源泄露等问题。
执行嵌入式系统的单元测试过程如下:
(1)使用交叉编译器,为目标平台建立C ++TEST 运行时库;
(2)配置C++TEST 使其可以在交叉编译器和开发环境上工作;
(3)自定义测试流程定义;
(4)执行测试并使用C++TESE的GUI 来进行结果分析。
下面就Tornado2.0.2 编写的一个简单程序说明如何在C ++TEST 上执行嵌入式系统的单元测试。首先,从C++TEST的GUI 中导入一个Tornado项目,我们所使用的Tornado 源代码如下:
在C++TEST的安装目录下找到pluginscom.parasoft.xtest.libs.cpp.win32.x86_7.2.10.34oswin32x86libsource arget 目录下的WR_egcs_simnt_VxWorks5_4.mk 文件,然后查询和修改相关变量,在主Mkefile 文件中找到了这个变量,并将其值修改为:WR_egcs_simnt_VxWorks5_4,然后查找PLATFORM 宏,并 在 主 Makefile 文 件 中 查 找CPPTEST_INC_DIR 变量,将其值定义为../../etc/include,然后将Tornado 安装目录中的make.exe 文件拷贝到主Makefile 文件所在的目录并执行Make,如果编译顺利通过,可以在目标目录下得到third_tornadoTest.out 文件,将这个文件拷贝到C ++TEST工作空间下的workspace.cpptest hird_tornadounit-datacurrent_tubf179707 目录下,开启Tornado的注册器、目标服务器和仿真器,之后,在C ++TEST的GUI 中按照单元测试的步骤依次执行到“构建测试可执行文件”并执行:“Test Using”→“Builtin”→“Embedded Systems”→“Tornado”→“Load and Run Vxworks Test Object”。
回归测试是在确认已知程序正确性的基础上,为这些已知的正确程序生成一个叫做“回归基”的测试套件。如果用户更改了这个已知程序,比如:源码修改、添加、删除等,那么,可以运行已经生成的回归基测试套件,C ++TEST 能自动捕获测试输出的不同点,并作为一个违例报告给用户。如果所有的输出都是相同的,则不会有违例报告产生。根据这个违例报告,可以确认用户修改后的源代码是否使以前的程序功能受到了影响。当我们对一个程序作了充分测试并修改后,执行“Test Using”→“Builtin”→“Unit Testing”→“Generate Regression Base”,就可以生成回归基。以前的测试用例集和现在作为回归基的测试用例集的区别:
没有作为回归基的测试用例集的函数格式为:
CPPTEST_POST_CONDITION_INTEGER("int_return",(_return)),其作用是:当这个测试用例执行完成后,在C++TEST的Console 面板中报告_return的值。
而作为回归基的测试用例集的函数格式为:
CPPTEST_ASSERT_INTEGER_EQUAL(0,(_return)),其作用是:当这个测试用例完成后,比较_return 和0是否相等,如果相等,则不产生操作,如果不相等,则产生一个违例报告给用户,其中的这个“0”值,就是在执行“Generate Regression Base”时,C++TEST 在执行该测试用例时所产生的值。然后C++TEST 把这个值作为执行这个测试用例的标准输出,当用户以这个回归基为标准进行回归测试时,C++TEST 就将这个标准输出和进行回归测试时得到的输出作比较。
从图4 中可以看出更改了函数内容后C ++Test 所报告的违例。
图4 C++Test 所报告的违例
从两个红色方框可以很清楚地看到,当执行test_max_3()这个测试用例时,原来程序的返回值应该是1,更改后的程序返回值是0,所以C ++TEST 给出一个回归测试的违例报告。
C++TEST 支持以下几种覆盖率分析:
Line Coverage:语句覆盖。
Block Coverage:块覆盖。
Path Coverage:路径覆盖。
Decision Coverage:决策覆盖。
Simple Condition Coverage:简单条件覆盖。
Modified Condition/Decision Coverage:修正的条件/决策覆盖。
按照前面介绍的单元测试流程,执行一遍单元测试,查看C++TEST的Coverage 面板如图5 所示。
以上是选择Line Coverage 显示的覆盖率结果,同时,我们还可以选择查看以其他方式统计的覆盖率结果,如图6 所示。
从C++TEST的主面板上查看源代码的覆盖率也是很方便的,它提供对已经覆盖部分和未被覆盖部分的不同颜色的高亮显示。
由于C ++TEST 不检测预处理语句、变量和函数定义等语句的覆盖率,如int x=1;这样的语句是不会有绿色的高亮显示的。
用于用户定义适合自己项目的测试配置,包括测试源的过滤(只对某些代码进行测试,而另一些代码不进行测试)、静态代码规范的选择、产生测试用例的规则(产生测试用例的对象、方式,测试用例集存放的地点)、执行超时时间、外部符号表等内容,这里面的配置比较简单,各种选项基本上都能见名知义,并且带有通用性的配置选项不多,只需要按照用户自己的需求进行选择就行了。
C++TEST 作为一个以单元测试为主的测试工具,功能还是比较强大的。它的静态编码规范检测内置的编码规范有1456种,并且具有TCM 和Rule-Wrizad 功能。只需要一个比较了解该项目或者公司实际需要的编码规范的人来制定相应的编码规范,就可以在全公司范围内得到应用和继承。如果要做单元测试的话,利用它的这些功能,能极大地降低测试人员的工作量,还能降低出错概率和调试时间。由于它具有“回归基”测试套件的功能,在比较熟悉一个项目源代码的情况下,用它来作回归测试也是个相当不错的选择。同时,开发人员也可以运用这个功能作增量测试。
[1]Dorota Huizinga,Adam Kolawa.Automated Defect Prevention:Best Practices in Software Management [M].Wiley-Blackwell,2007.
[2]Adam Kolawa.The Next Leap in Productivity:What Top Managers Really Need to Know about Information Technology[M].Wiley,2009.
[3]Delores M Etter,Jeanine A Ingber.Engineering Problem Solving with C ++ (3rd Edition)[M].Prentice Hall,2011.
[4]D.S.Malik.C++ Programming:From Problem Analysis to Program Design[M].South-Western College Publishing,2012.
[5]Ana Colton- Sonnenberg.Computer- based Language Testing:C- Test Vs.Rapid Profile[M].GRIN Verlag oHG,2007.