沈雷 杨竣铎
摘要:随着国产化工作的推进,国产生态环境日益成熟,运行于国产平台的软件数量不断增加,对测试工具的需求也越来越高。文章对国产计算机系统的开源测试工具进行研究,从静态分析、单元测试、功能测试、性能测试和覆盖测试对工具进行了分类,提出了国产操作系统开源测试工具整合方案。
关键词:国产化;开源工具;软件测试
中图分类号:TP311 文献标识码:A 文章编号:1007-9416(2020)08-0080-03
0 引言
经过多年发展,开源软件运动已经获得很大成功,借助开源测试工具构造一个完整的测试解决方案,既能提高测试效率又能降低测试成本。另一方面,国产操作系统虽愈来愈成熟,但缺乏基于这些操作系统的软件测试方法。我们希望能够把现有的较为成熟的开源软件测试工具进行整合,形成一个能稳定运行于国产操作系统的软件测试解决方案。该方案能应用于静态分析、单元测试、功能测试、性能测试和覆盖测试等测试常用场景。
与商业软件测试工具相比,开源软件测试工具具有如下特点:
(1)数量大:仅在opensourcetesting.org网站上统计的开源软件测试工具就有超过360种,其中面向Java程序的单元测试开源软件工具就有70多种。
(2)目标单一:开源软件测试工具往往是面向一个非常具体的领域,而不像商业软件测试工具会将各种功能模块集成起来,解决各个领域的问题。例如,每种开源的软件单元测试工具往往只能支持一种开发语言。
(3)运行需求各异:不同的开源软件测试工具有不同的运行需求,包括不同的操作系统版本、不同的脚本语言版本(如不同版本的waitr需要先安装不同版本的Ruby)。
(4)用户使用不便:很多开源软件测试工具都缺乏良好的用户使用界面,也缺乏稳定的维护团队。
这些特点决定了将开源测试工具整合起来并不容易。在后面的讨论中,我们按照单元测试、功能测试、性能测试的顺序推荐了一些较为成熟、使用较为广泛的开源软件测试工具。要说明的是,考虑到广泛使用的国产操作系统一般都是基于Linux或类似产品开发的,本文中只讨论能基于Linux使用的开源测试工具。同时考虑到目前国产操作系统上较常使用的开发环境,本文中重点讨论针对Java、C和C++的开源测试工具。
1 单元测试
单元测试(unit testing)中,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。对于单元测试,使用最多的是基于XUnit框架的测试用例设计方法。
1.1 XUnit
XUnit是一个基于测试驱动开发的测试框架体系,为用户在开发过程中使用测试驱动开发提供了一个方便的工具。根据被测软件使用的开发语言的不同,XUnit的成员有很多,如JUnit、CUnit、CPPUnit、PythonUnit、PHPUnit、SQLUnit等,其中每个测试框架都有开源的安装包。这里我们重点讨论JUnit、CUnit和CPPUnit。
1.1.1 JUnit
Junit是单元测试框架体系XUnit的一个实例,也是该框架体系中最为成功的一个。通常使用JUnit进行测试的基本流程如下:
(1)创建一个TestCase的子类;
(2)写一个测试方法断言期望的结果;
(3)写一个suite()方法,创建一个包含全部testxxx方法的测试套件;
(4)写一个main()方法以运行测试;
1.1.2 CUnit
CUnit是一种C语言单元测试框架,使用CUnit进行测试的基本流程如下:
(1)书写待测试的函数(如果必要,需要写suite的init/cleanup函数);
(2)初始化Test Registry-CU_initialize_registry();
(3)把测试包(Test Suites)加入到Test Registry - CU_add_suite();
(4)加入测试用例(Test Case)到测试包当中-CU_add _test();
(5)使用适当的接口来运行测试程序,例如CU_co-nsole_run_tests();
(6)清除Test Registry-CU_cleanup_registry()。
1.1.3 CPPUnit
CPPUnit是XUnit框架针对C++语言的实现。使用CPPUnit进行测试的基本流程如下:
(1)初始化操作,包括:生成被测试的对象及其初始化值;
(2)按照要测试的功能或者流程对测试对象进行操作;
(3)对结果进行验证;
(4)测试资源的释放清理。
1.2 其他工具
1.2.1 对JUnit的扩展
一些开发者基于JUnit进行了一些扩展,增强了该框架的能力。例如,Cactus专门用于对服务端的Java代码单元测试(Servlets、EJBs、Tag Libs、Filters、...),DbUnit专门用于对数据库驱动项目的Java代码单元测试。
1.2.2 Check
Check是另一种对C语言进行单元测试的测试框架,最主要的优点是对于每一个测试用例的运行都fork一个子进程,这么做的原因是因为C语言的独特性:其他语言如Java,Python,Ruby等,单元测试运行出错时最多不过是抛出异常,而C语言如果指针操作错误,会遇到“coredump”问题,测试框架直接退出,用户看不到任何返回。Check的單元测试运行在fork子进程中,可以避免测试框架由于“coredump”而崩溃,优点显而易见。
1.2.3 CxxTest
CxxTest采用Perl分析C++源文件,从中抽取测试元素,创建用例。由于不需要编写额外的代码,增添新的测试工作量小,可移植性好。编译即测试是其最大的优点。
2 测试覆盖率统计
很多测试项目对测试覆盖率提出了明确的要求,因此对测试用例集的测试覆盖率统计有着很大的现实意义。根据被测软件使用的不同开发语言,已经存在多种开源测试工具,下面讨论几个常用的工具。
2.1 Emma & EclEmma
Emma是JAVA代码覆盖率的开源工具,支持包,类,方法,语句块(basic block)和行等多级别的覆盖率指标:能测出某一行是否只是被部分覆盖,如条件语句短路的情况。Emma能和Makefile和Ant集成,且执行效率高,适用于大型项目。
EclEmma是Eclipse和Emma两个工具的结合,增加了图形界面以及对集成开发环境的支持,便于用户使用。
2.2 gcov & lcov
gcov是C/C++软件的测试代码覆盖率的工具,配合GCC共同实现对C/C++文件的语句覆盖和分支覆盖测试;结合程序概要分析工具(profiling tool,例如gprof),gcov可以统计每一行代码的执行频率、覆盖情况及耗时(执行时间)。
lcov是gcov图形化的前端工具,是LTP(Linux Test Project)维护的开放源代码工具,最初被设计用来支持Linux内核覆盖率的度量。lcov基于Html输出并生成一棵完整的HTML树,包括概述、覆盖率百分比、图表,能快速浏览覆盖率数据。lcov支持大项目,提供三个级别的视图:目录视图、文件视图、源码视图。
3 代码静态检查
代码静态检查是指通过分析或检查源程序的语法、结构、过程、接口等来检查程序的正确性,找出代码隐藏的错误和缺陷,如参数不匹配、可能出现的空指针引用等。
3.1 Findbugs
FindBugs是一款开源Java静态代码分析工具。它通过检查类文件或JAR文件,将字节码与一组缺陷模式进行对比从而发现代码缺陷。在工具界面,需要先选择待扫描的 .class文件。如果有这些.class档对应的源文件,可把这些 .java文件再选上,这样便可以从稍后得出的报告中快捷定位到出问题的代码。此外,还可以选择工程所使用的库,这样可以帮助FindBugs做一些高阶的检查,发现一些更深层的缺陷。可以发现的典型缺陷如空指针引用、特定的资源未关闭、多余的If后置条件、错误地使用了“==”等等。
3.2 Splint
splint是一个静态检查C语言程序安全弱点和编写错误的静态测试工具,不需要运行程序即可进行错误检查,包括未使用的变量、类型不一致、使用未定义变量、无法执行的代码、忽略返回值、执行路径未返回、无限循环等错误。能通过splint的输出结果,分析出被测C语言程序中的错误所在,并实现错误在程序中的定位。
4 功能测试
功能测试是按功能需求对软件进行的测试,也叫黑盒测试或数据驱动测试。面向功能测试的测试工具的主要任务是快速生成正确的测试用例。
4.1 Abbot
Abbot是一个用来测试JavaGUIs的框架。Abbot提供了一组API可以允许开发抓取应用程序窗口中的各个组件,然后模拟用户的操作。Abbot提供了录制脚本的功能,可以利用录制工具在配置好相关应用的Jar包的类和函数后,启动应用并录制相关脚本。录制的脚本可以导出为xml格式的文件。也可以在脚本中添加断言来给自动化脚本添加一些业务逻辑的判断和控制。目前我们使用Abbot更多是用来做组件的功能测试,也可以理解为是一个对于组件的单元测试框架,可以继承到Junit或者是Fitnesse框架中。
4.2 Marathon
Marathon是一个基于Jython的开源自动化GUI测试框架。Marathon的录制功能比较强大,而且操作界面比较直观,方便使用。Mathon录制的脚本是基于Jython的,由于Jython是运行在JVM上面的Python,语法也和Java比较接近,对于有java经验的工程师而言,非常容易上手。Marathon提供的fixture和module功能,可以把自动化脚本模块化,提高了脚本的复用性。
4.3 Selenium(Selenium WebDriver)
Selenium是用于Web应用程序的一个开源测试工具,直接运行在浏览器中。可以在Windows、Linux和Mac上的 Internet Explorer、Mozilla和Firefox浏览器中运行。主要功能包括:(1)测试应用程序与浏览器的兼容性;(2)测试系统功能,包括创建衰退测试检验软件功能和用户需求。支持自动录制,可以自动生成.Net、Java、Perl等不同语言的测试脚本。
5 性能测试
性能测试是通过测试工具模拟各种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。负载测试和压力测试都属于性能测试。
5.1 JMeter
JMeter是Apache组织开发的基于Java的性能测试工具,可用于测试静态和动态资源,包括静态文件、Java小服务程序、CGI脚本、Java对象、数据库、FTP服务器等等。能够模拟负载,在不同压力下对服务器、网络或对象的强度进行测试并对整体性能进行分析。
5.2 DBMonster
DBMonster是一个用生成随机数据来测试SQL数据库的性能测试工具。DBMonster是一个Java的开源项目,通过JDBC方式连接数据库,可以在任何支持Java和JDBC的平台上运行。DBMonster开发的初衷是为数据库开发者服务,可以协助产生大量规则或不规则数据,便于数据库开发者基于这些数据进行数据库的调优。DBMonster通过两个XML文件(配置文件和 schema文件)控制数据产生的行为,配置文件指明需要连接的数据库、连接使用的用户名和口令、需要操作的scheme、重试次数等全局设置,而 scheme文件则指明针对每张数据表的每个字段产生数据的规则。
6 结语
本文总结了部分常用的开源测试工具,将这些工具整合起来,可以有效地在国产操作系统基础上对Java、C、C++的軟件产品进行各种类型的软件测试。在开源世界中,还有大量各具特色的开源测试工具,在使用过程中应根据项目的特点有针对性地进行选择。