时间:2024-07-28
刘 栋 方丽萍 李国要
(安徽继远检验检测技术有限公司,安徽 合肥 230088)
随着信息化、智能化进程的逐步加深,智能技术逐渐广泛应用于各类终端设备。嵌入式系统是智能化终端设备的核心,能够实现设备的自动运行、控制和管理。嵌入式软件作为嵌入式系统的重要组成部分,也日益受到人们的关注。嵌入式软件测试在保障终端设备功能完备、可靠稳定上发挥着至关重要的作用。覆盖率测试是对嵌入式软件开发设计质量的一种有效衡量手段。一般来说,在用例设计完整的情况下,软件覆盖率的高低能够较好地反映软件中存在的问题,软件覆盖率越高说明软件程序设计较为完整;软件覆盖率低说明软件程序中存在未被覆盖的代码和分支,可以帮助软件开发设计人员对代码进行分析,未被覆盖的代码是冗余无用的还是由于逻辑缺陷未被执行的,进而有针对性地进行缺陷整改,优化代码,提升嵌入式软件的设计质量,也提高了终端产品的可靠性和稳定性。
嵌入式软件测试一般是指对终端等智能设备中能够执行某种或某些特定功能的软件开展功能、性能、接口、逻辑覆盖等内容的测试。与应用软件测试存在着一定的差异性,嵌入式软件的测试与硬件的依赖性较强,不能脱离硬件设备,单独开展测试[1]。具体存在如下区别:
(1)嵌入式软件的功能测试与硬件关联性强,对于软件、硬件模块的缺陷定位耗时较长,尤其是对性能的探索性测试需要很大的时间、精力消耗,定位性能的瓶颈比较困难。
(2)嵌入式软件测试不具有通用性,测试的环境需要指定硬件平台,并且测试往往发生在宿主机上,受运行环境的影响,因此,嵌入式软件测试不仅需要在开发环境中开展测试,还要在运行环境中开展测试,这就增加了测试的难度,提高了测试的成本。
(3)嵌入式软件具有特定性,给嵌入式软件的自动化测试带来了技术上的难题。
嵌入式软件覆盖率测试是对嵌入式软件的代码逻辑和功能结构的正确、适用性进行验证的必要环节。在进行覆盖率测试时需要对软件代码按照功能模块进行插桩,并依据相关的设计架构和需求进行用例的设计,用例设计的原则是尽可能覆盖更多有效的代码语句、函数、分支条件等,能够贯穿软件的内部逻辑结构,只有这样才可能发现更深层次的代码设计缺陷和问题[2]。
嵌入式软件覆盖率测试一般在单元测试阶段进行,通过覆盖率测试可以检查出嵌入式软件代码是否至少执行一次,也可以发现用例的设计是否完整有效。在测试过程中,要求覆盖尽可能多的代码语句、代码的分支条件和路径、代码的重要函数等,保障覆盖率测试的有效性。嵌入式软件覆盖测试主要包括:逻辑分支覆盖、条件覆盖测试、语句覆盖测试、函数的覆盖测试以及组合覆盖测试等。
(1)逻辑分支覆盖:主要是检查代码中的所有分支结构是否能够完全执行。在足够的用例支撑下,尽可能使得代码中的每个分支都至少执行一次。在实际测试中,有部分系统的代码量巨大,要实现代码的所有分支覆盖是比较困难的,因此,对于代码中能够实现关键功能的分支覆盖率要测试充分,这样也提高了测试效率。
(2)条件覆盖测试:主要是代码中的判断语句中存在多个条件时,要对每个条件分别设计用例,以满足执行后可以获取多个不同的结果。代码中分支的变化与条件的变化关联程度较小,所以,条件覆盖充分还要单独验证分支的覆盖是否充分。为了提高测试的效率,条件覆盖也是保证代码的关键功能条件覆盖充分,不造成过多的人力、物力、财力的浪费。
(3)语句覆盖:语句覆盖是最基本的覆盖测试要求,是对代码中的语句在执行中是否被覆盖的情况统计。此处的语句指的是代码中的有效语句,也就是在编译后,能够成功执行的语句,不包括代码的注释语句和无关语句。语句覆盖率统计了代码中的语句在执行中是否至少被执行了一次。单纯的语句覆盖测试不能衡量代码的质量,因为语句覆盖不会关心代码中的分支和条件,有效的代码覆盖测试应当结合语句、条件和分支覆盖,进行综合评价。
(4)函数覆盖:函数覆盖主要是验证代码中的各个函数在执行中是否被覆盖,每个关键函数在执行中应该充分覆盖,避免出现函数未覆盖而影响代码的功能执行。关键函数的覆盖对软件产品的功能有着直接的影响,因此,函数覆盖也是嵌入式软件覆盖测试的重点。
(5)其他覆盖:其他覆盖主要是指一些多条件覆盖以及组合覆盖[3],至于嵌入式软件代码覆盖率测试中,可依据需求和设计架构,选择其他或者组合的覆盖策略,旨在实现代码覆盖充分。在面对大量代码的嵌入式软件时,代码的覆盖充分就是相对的概念,因为还需要考虑测试的效率,避免大量资源的浪费,选择关键的代码,进行语句、分支、条件、函数等的覆盖测试,就能够在一定程度上保障嵌入式软件的质量和测试的有效性。
嵌入式软件覆盖率的计算如下:
其中,嵌入式软件覆盖率为C,已执行的语句/分支/函数的代码的数目为E,代码中可执行的语句/分支/函数的代码总数N。
覆盖率测试是一种在嵌入式软件在单元测试阶段进行的白盒测试,进行覆盖率测试之前需要依据测试需求和架构说明对用例进行充分设计,设计完成后,对被测代码程序进行插桩操作,然后通过Gtest编译生成可执行文件,并运行可执行文件。此时,嵌入式软件中接口、功能、性能、边界值、分支条件等项均已执行完成,通过lcov统计覆盖率数据并写入文件,最后输出可视化的覆盖率报告。嵌入式软件覆盖率测试流程如图1所示。
图1 嵌入式软件覆盖率测试流程图
嵌入式软件的代码覆盖率测试是对嵌入式软件的代码设计有效性的一种评价依据,在用例充分设计的前提下,可以直接展示代码设计的质量以及各逻辑结构是否设计完全。
目前对于嵌入式软件的测试工具较多,由于大多数终端设备都是基于C/C++语言进行设计开发的,因此本文选用针对C/C++的测试工具。一些诸如:testbed、c++test等工具的覆盖率测试是需要付费使用,价格比较昂贵,对于单元和覆盖率的测试来说,选取一款开源且测试准确率高的工具十分必要。
Gtest是Google提供的开源测试框架,功能强大,测试用例编写也比较简化,是一种轻量级的测试工具,可以对嵌入式软件的功能、接口、变量、边界值等内容进行验证,实现嵌入式软件的单元测试,还可以结合lcov实现软件代码覆盖率的统计,支持语句覆盖率、函数覆盖率以及分支覆盖率的统计;还能提供程序的实际执行信息,包括代码的执行次数统计,通过html能够输出可视化的图形覆盖率报告,使用简单便捷。
在进行嵌入式软件测试时,测试人员应充分阅读产品需求说明和架构设计说明,熟悉产品的软件模块,以及软件的功能和运行流程,以便更好地开展测试,设计测试用例,提高测试的效率。
嵌入式软件的测试环境搭建,需要依赖终端设备。本文搭建的嵌入式软件测试环境由测试客户端、终端设备、Xshell工具、keil开发工具、Gtest测试工具、lcov覆盖率统计工具等要素构成。一般步骤如下:
(1)在测试客户端中需要安装Xshell工具,与终端设备建立连接,实现嵌入式软件代码的上传与下载。
(2)安装keil开发工具,可以实现代码的编辑、编译和插桩,为后面覆盖率的测试提供了前提条件。
(3)在linux系统下,安装Gtest工具和lcov工具,进行代码插桩,执行完成后,能够同时完成单元和覆盖率的测试,通过查看覆盖率测试的结果进而对代码的质量进行评估。
测试用例设计是测试开展的前提条件,只有充分的测试用例设计才会使得覆盖率结果更为准确,衡量代码的质量效果更好[4,5]。测试用例设计也就是在测试执行前确定本次测试需要涉及的内容和相关特性要求,提出基本的测试方法。
测试用例设计首先应获取嵌入式软件设计的架构和需求,在充分分析设计架构和需求的前提下,研究软件的功能模块,并依据模块,进行用例的设计。用例设计在兼顾代码重要模块的同时,还要延伸用例设计的思维,覆盖正反向用例、边界用例等。测试用例的基本要素包括:名称和标识、测试依据、测试的环境要素及要求、测试的输入输出、期望结果、结果的评判依据等。
测试用例的设计一般流程如下:
(1)查看嵌入式软件的设计需求及架构,测试人员应充分了解软件的模块及架构,整理软件的功能模块,并依据功能模块设计测试用例。
(2)选取涉及功能模块的关键代码,加入Gtest相关头文件,使用工具断言来实现测试是否符合预期结果。
(3)依次设计好关键功能模块的测试用例,满足测试的需求。
本文在嵌入式软件基本测试环境完备情况下,开展覆盖率测试的一般流程如下:
(1)安装Xshell工具,运行和配置ip,连接终端设备,通过xftp下载获取终端设备的嵌入式软件代码。
(2)依据产品的需求及架构设计文件,熟悉产品的模块功能和结构,安装keil工具,导入源代码文件,并对应进行编译和插桩操作。
(3)下载Gtest和lcov安装包,执行tar命令解压后进行安装,安装完成后查看工具的版本号是否安装成功。
(4)将插桩后的代码按照软件功能模块,将其划分为多个后缀为.c/.cpp的文件,并加入测试用例执行脚本后形成待执行文件。
(5)使用Gtest和lcov进行嵌入式软件的功能和覆盖率的测试,将待执行的.c/.cpp文件通过Gtest工具编译,链接lGtest库和lpthread库,生成可执行文件,执行文件可完成单元测试的结果验证。
(6)添加-fprofile-arcs和-ftest-coverage参数编译程序,生成可执行程序和.gcno文件,运行可执行文件,生成.gcda文件,通过lcov收集.gcda文件中的信息,并写入.info文件,在输入genhtml指令后生成的一个包含有.html文件的文件夹,其中.html文件即为覆盖率报告。
测试流程执行完成后,会生成测试结果。执行单元测试功能和接口等测试时,每次执行完成后会出现执行后的结果,若结果中出现报错信息,显示期望值与实际值的差异,测试人员可以依据错误提示,快速定位失败信息,并及时修改。若用例测试全部通过,也就说明没有任何报错。统计结果一般包括:该用例包括的用例个数、执行通过的测试用例个数、执行失败的测试用例个数以及失败用例序号等。执行覆盖率测试用例后,会生成覆盖率的结果报告,打开覆盖率报告,即可查看覆盖率的统计信息以及详细的语句覆盖、分支覆盖的代码信息,如图2所示。
图2 嵌入式软件覆盖率报告结果
可在覆盖率报告中展开详细信息,在文件或函数的视图下,可显示代码的具体行数。报告中的代码前数字表示该语句被执行的次数,代码语句前的“+”“-”符号,代表分支的个数,其中,“+”号表示该分支在执行中已经被覆盖,“-”号表示该分支在执行中未被覆盖,且以红色标识。
嵌入式软件覆盖率报告分别显示语句覆盖率、函数覆盖率、分支覆盖率的统计结果,代码中语句、函数、分支已经执行的个数以及总数。在覆盖率测试结果中,如果出现覆盖率结果小于100%,则可能出现两种情况,要分别检查排除情况。
(1)用例设计不够充分,可以从测试覆盖率的结果来检验用例的设计,覆盖率结果中出现某一分支的结果中有标记为“-”,查看对应的分支是否用例已经覆盖,未发现用例覆盖,则补充对应用例,再次执行测试,若覆盖率结果完全覆盖,则表明用例测试充分,若仍未完全覆盖,则对应寻找软件代码中的设计缺陷问题,记录缺陷,并与研发人员进行沟通,改进代码,保障代码的质量。
(2)代码本身的质量缺陷,在用例设计充分的前提下,代码覆盖率结果仍有未覆盖,则需寻找代码的缺陷,该路径存在执行失败的问题。
嵌入式软件覆盖率测试,可以衡量代码的质量和用例设计的充分性,在测试人员对用例设计充分的前提下,就能直接反映出代码本身的质量,对嵌入式软件的安全可靠提供了保障。
嵌入式软件在测试中除了关注软件本身的功能、接口、性能的测试结果,还需要关注软件的覆盖率情况,软件覆盖率在测试用例充分设计的前提下,可以直接反映出软件代码的质量,定位软件代码的缺陷问题,也可以帮助测试人员快速查找用例设计的缺失问题,保障用例设计的充分性。因此,嵌入式软件覆盖率测试是十分必要的。
本文在充分考虑测试资源的消耗以及测试成本的压缩上,选用Gtest和lcov完成嵌入式软件的单元和覆盖率测试,阐述了嵌入式软件覆盖率测试的方法和工具,并对测试的环境搭建、用例设计、详细流程以及报告分析等方面进行详细分析,提高了测试人员的测试效率,快速定位缺陷,也帮助研发人员发现嵌入式软件的设计缺陷,指导进行缺陷的修改,从整体上保障了嵌入式软件的质量。
我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自各大过期杂志,内容仅供学习参考,不准确地方联系删除处理!