时间:2024-05-04
黄仁欢
摘要:Qt是一个开源的、跨平台的C++图形用户界面应用程序开发框架,使用其开发的应用软件可以按照代码走查、静态检查、覆盖率统计、单元测试、软件集成测试的测试步骤进行测试,有利于排查潜在的代码缺陷和故障,提高代码质量和健壮性。该文将阐述这一测试过程所使用的方法,总结实测经验,为软件测试人员提供借鉴。
关键词:代码走查;覆盖率统计;单元测试;软件测试实践;Qt应用程序测试
中图分类号:TP311 文献标识码:A
文章编号:1009-3044(2021)16-0070-03
开放科学(资源服务)标识码(OSID):
1 概述
Qt作为现阶段流行的跨平台C++图形用户界面应用程序开发框架,它的软件开发遵循着一般软件开发的正常流程,其开发生命周期按照可行性研究报告、需求分析、风险分析、架构设计、组件设计、实现与测试、验证与确认、部署与维护8个阶段进行。缺少任一环节,那么这个软件都是不完整的,不能投入市场进行部署运营。而软件测试,是保障软件质量最重要、最有效的方法[2]。作为一个优秀的、跨平台的应用程序开发框架,由它进行编码的软件,也需要经过严格的、全面的、多方位的测试过程,从而发现和消除软件内部隐藏的故障,只有这样,软件才会通过完整性、充分性测试。
本文涉及的项目需要通过SIL2等级的功能安全认证,由于项目本身只是一个应用层软件,在进行SIL2认证工作时不考虑硬件相关的因素,根据既有的软件开发的流程及参照《EN50128-2011》标准中对通用软件开发的要求,对软件开发的生命周期进行了微调,并且注重软件的测试方法、过程和细节。
2 测试过程
软件编码人员根据详细设计文档进行代码编写,遵照模块划分图、UML类图、接口定义将软件功能逐步实现,开发者会进行基本的功能验证工作,保证程序运行正常和功能完整,然后将代码提交SVN归档,完成开发工作。此后,便进入代码的测试阶段。
针对Qt应用程序软件测试的不同阶段,可以将测试过程划分为代码走查,静态检查,单元测试,覆盖率统计,集成测试五大阶段,这些阶段具有先后顺序,上一个阶段完成后才可以开展下一个阶段的工作。
2.1 代码走查
代码走查是以组为单位对代码进行审查,是一系列规程和错误检查技术的集合。在实际工作过程中,代码走查是最容易被开发者或测试者省略的一个阶段[3]。开展代码走查工作具有一定难度的,原因有以下两种:首先,代码走查人员如何安排;其次,问题排查难及验收标准模糊。代码走查的意识和重要性往往被项目负责人忽视,这往往是不可取的。
在我们的项目中采取交叉走查的方式,即开发者A对开发者B的代码进行走查,开发者B对开发者C的代码进行走查,开发者C对开发者A的代码进行走查。走查的内容分为三大块:
1)对注释进行走查;文件的注释走查,需简述文件要实现的功能、作者、修改日期等;函数的注释走查,需描述函数的功能,参数含义,返回值信息等;变量的注释走查,简述变量的内容;注释风格的走查,严格使用Doxygen风格注释,保证后期可通过Doxygen插件自动生成项目源代码帮助文档;
2)对代码的逻辑结构进行走查;每个走查者参照详细设计文档,找到每一个功能点对应的实现代码,逐行解释程序的数据结构、逻辑和调用关系,使某一个功能的实现方法与其他成员想法达成一致;
3)对异常处理的走查;包括运算错误异常走查、接口异常走查、输入/输出异常走查及重点数据的异常走查。
走查结果以表格的形式输出,包含走查问题类型、问题个数及问题占比;并且记录走查的工时,包含走查时间、问题修改时间、验证时间。
2.2 静态检查
静态检查是指不需要编译运行源代码本身,仅通过分析或检查源代码的语法、结构、过程、接口等来检查程序的正确性。开展静态检查的依据是基于业界认可或者标准化的规范,对于基于C++的Qt开发框架来说,目前我们采用的是汽车工业软件可靠性协会于2008年发布的《MISRA C++:2008》编码规范。
C++Test是Parasoft公司开发的一个针对C/C++源代码进行自动化测试的一个工具,它可以对源代码进行三种测试:白盒测试、黑盒测试以及回归测试。此外,它还支持对源代码进行静态检查。
在Qt编译的Debug目录下,打开Makefile.Debug文件,添加如下代码:
CC = cpptestscan gcc
CXX = cpptestscan g++
重新编译后,会生成一个bdf文件。由C++Test工具创建测试工程并导入该bdf文件,选择与Qt相同版本的编译器,设置静态检查规则,我们选择《MISRAC++2008》规则239条加上《Qt最佳实践》规则8条,值得一提的是,除了上述的247规则外,作为代码复杂度的衡量标准-圈复杂度并不在其中,因此,通过过滤器搜索将圈复杂度限制在20之内的规则勾选,总共依据248条规则对项目软件进行静态检查测试,然后执行静态测试。在结果输出窗体栏的质量任务可查看测试结果及对应的违规说明、案例示范,方便开发人员修正。最后,该工具会生成一个静态检查的报告文档。
2.3 单元测试
软件单元测试是通过编写测试用例对一个模块、一个函数或者一个类来进行正确性验证的测试工作。对C++来说,通常是面向对象的编程方式,所以我们以单个类为一个测试单元,然后再对类内的函数逐一测试。QTest是Qt提供的一种简单易用的单元测试框架,它不仅提供了单元测试框架的基本功能,还针对GUI(图形用户界面)的测试进行了扩展,如对键盘输入事件、鼠标点击事件等进行了模拟;并且QTest可以與Qt的工具链、基础类库、应用框架、集成开发环境(IDE)等良好地结合。
在QtCreator新建工程时选择QTest单元测试工程,以子工程pri的形式导入源代码工程;其次,针对每一个源代码文件xxx.cpp,都创建与之对应的单元测试文件,命名为tst_xxx.cpp,使得每一个测试文件都可以通过修改测试入口函数(QTEST_MAIN(类名))进行独立测试;然后基于每个函数的代码内容编写测试用例。
正常值测试:测试用例设置的值在数据类型的范围内,例如,字符串类型的数据,可以设置为“abc”,整型类型的数据,可以设置为123,对于确定数值范围的情况,还可以取数值的中间值进行测试;
边界值测试:这类型的测试用例需要清楚的知道数据的上限和下限,取临界点数据的左值和右值作为用例的数据,例如涉及旋转的角度问题,上限为360°,下限为0°,在设计边界值用例时,这个案例有4个边界值数据,即361°、359°、1°和-1°,要测试超出合理数据范围内的数值程序如何处理,是否有异常机制;
路径测试:也叫分支测试,是指程序代码中使用if…else、do…while、switch…case等关键字时需要编写的用例测试,通过改变控制语句的值,从而执行不同的代码。
异常测试:异常测试包含的范围比较广泛,所有不应该出现的情况都属于异常的范畴,在这里我们重点关注数据的异常,一个是开发者对数值运算产生的异常值,一个是用户输入的数据异常,在设计测试用例时需要输入异常数据来检验程序是否对异常数据进行处理。
QTest框架通过QCOMPARE宏来比较单元用例中期望值与实际值是否相等,从而判定该条用例是否测试通过,当两个值相等时,表明测试通过,否则,测试不通过。
2.4 覆盖率统计
在单元测试用例工程之后,我们可以进行覆盖率统计。通过代码覆盖率审查,可以发现程序的未测试部分代码,并且知道程序中哪一段代码最耗时,能有效地帮助开发人员重构代码,以提高代码质量[5]。
代码覆盖率统计主要流程:
1)对单元测试工程增加编译参数;
LIBS += -lgcov
QMAKE_CXXFLAGS += --coverage
2)重新编译单元测试工程文件,生成gcno文件;
gcno文件包含重建基本块图和相应的块的源码的行号信息。
3)运行单元测试程序,生成gcda文件;
gcda文件包含弧跳变的次数和其他的概要信息。
4)使用gcov工具,生成gcov文件;
gcov文件包含代码覆盖率信息,但是可读性较差。
为了对代码覆盖率的快速分析,有必要对覆盖率信息进行可视化输出。基于以上的流程,增加以下步骤:
5)使用lcov工具,生成info文件;
info文件包含一个或多个源代码文件所对应的覆盖率信息,但是可读性较差
6)使用ghtml命令,生成html文件
html文件是我们想要的可视化输出文件,如图3所示。
从图中我们可以清晰明了地看到源代码的覆盖率,包括行覆盖、函数覆盖及分支覆盖信息。对于每一个文件,还可以精确的看的哪一行代码、哪一个分支没有覆盖。这助于引导测试人员设计更合理的用例,实现代码覆盖,这对提高代码质量有着重大的作用。
由于lcov工具与Windows平台不兼容,考虑到Qt框具有的跨平台特性,将Windows下的Qt应用程序的源代码、编译生成的gcno、gcda文件放到Linux平台下,使用lcov工具生成info文件,该info文件会包含Windows平台下的路径,因此,需要对info文件进行如下修改:
1)删除包含第三方库的信息;
2)删除包含Qt源码的信息;
3)将源代码路径修改成Linux风格的路径。
最后,再使用ghtml工具生成html文件,也能实现图3的可视化输出效果。
如果发现源代码有未被测试用例覆盖的行,需要进行编写单元测试用例,使其覆盖。在我们的项目中,只需要满足行覆盖和函数覆盖即可,分支覆盖要求则更高,在这里不进行展开描述。
2.5 软件集成测试
软件集成测试是软件测试中处于组件测试和系统测试之间一个非常重要的环节,这是因为所有组件都经过单元测试并能正常运行并不意味着这些组件放到一起经过集成后还能正常运行[7]。
软件集成测试的依据是系统的概要设计文档,概要设计文档定义了的所有公共接口,需要将各个接口模块串联起来形成一个个独立的功能点,也是我们要设计的测试用例,用来覆盖系统需求规范里的功能。软件集成测试过程如图4所示。
与单元测试的测试用例不同的是,软件集成测试需要多个模块间相互配合,模块间有数据交互,形成数据流,由数据驱动达到某个功能点的测试目的。集成测试的实施方案有多种,如自底向上集成测试法、自顶向下集成测试法、三明治集成测试法等。对于Qt应用程序的软件集成测试,同样可以使用QTest框架进行测试,工程创建、用例编写、测试执行、结果审查等都与单元测试过程一样,此处不再赘述。
2.6 回归测试
在软件生命周期的任何一个阶段,只要软件代码发生了改动,我们就必须重新测试现有的功能,以便确定修改是否达到了目的[8],这就是回归测试。进行回归测试时,需要重新对用例库进行审查,比如:1)修正不适用的测试用例;2)删除冗余的测试用例;3)增加与新需求相适应的测试用例。可用于回归的测试用例准备完成后,应对回归测试的范围进行评估,使用恰当的方法进行测试,常用的回归测试方法有:1)全用例再测试;2)基于风险进行测试;3)基于操作进行测试;4)仅测试修改部分。
回归测试是一个不断按照“计划->执行->检查->改进”过程进行的工作,每一轮的测试结果恰好可以作为下一轮回归的依据,以使得回归测试更精准和高效。
3 结束语
本文阐述了一个完整的软件测试过程,通过该过程可以有效的发现和挖掘可能存在的错误和异常,能提高软件的质量和保证软件的安全,这一软件测试过程被成功应用于功能安全认证SIL2等级的认证中。
一个软件产品的上线,除了以上阐述的软件测试阶段的所必需方法,还需要通过严格的系统集成测试阶段、验收测试阶段,这样才能保证软件能够满足用户的需求。本文的立脚点是传统软件行业的测试,对于互联网、手持终端的软件测试,上述列举的测试过程不一定适用,这是本文的欠缺之处。
参考文献:
[1] 朱健.基于Qt Test的自动化单元测试[J].价值工程,2017,36(14):216-219.
[2] 鞠秀娟,赵明.软件自动化测试概述及应用工具分析[J].计算机应用,2007(S1):317-318,321.
[3] 周玫.有效开展代码走查工作的实践过程分析[J].现代信息科技,2019,3(1):190-191.
[4] 毛子晏.对计算机软件测试技术的几点探讨[J].电脑知识与技术,2020,16(18):77-79.
[5] 朱少民.全程软件测试[M].3版.北京:人民邮电出版社,2019.
[6] Jorgensen P C.基于模型的测试:一个软件工艺师的方法[M]. 王轶辰,王轶昆,曹志钦,译.北京:机械工业出版社,2019.
[7] 侯艳芳,楚书来.探析软件测试之集成测试[J].计算机光盘软件与应用,2012(3):78-79.
[8] 李龙,黎连业.软件测試实用技术与常用模板[M].北京:机械工业出版社,2018.
【通联编辑:谢媛媛】
我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自各大过期杂志,内容仅供学习参考,不准确地方联系删除处理!