鉴源实验室丨软件代码结构化覆盖测试-语句覆盖

作者 | 李伟 上海控安安全测评部总监

来源 | 鉴源实验室

社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区”

引言: 之前我们一直在讲功能、性能、以及专项等相关的测试,这些测试主要集中在集成测试,系统验证等阶段,从本篇开始我们将深入到代码层面,讲解单元测试中的一项重要工作-软件代码测试。

01

代码测试对功能安全的意义

在行业内功能安全越来越多地被提起,对于测试人员来说项目落地时的工作量是趋于增加的。单元测试的执行,在功能安全整体设计要求中是不可缺少的环节,而通常情况下测试工程师对单元测试阶段的任务设计是相对较少和覆盖不全面的。

功能安全标准ISO 26262-6中提供了不同Asil等级的零部件单元测试推荐使用验证方法,同时也对不同安全等级要求代码的结构化覆盖测试给出不同的测试方法。如下图所示:

鉴源实验室丨软件代码结构化覆盖测试-语句覆盖_第1张图片

ISO 26262-6:2018(E) Table 9

从本篇开始我们给大家介绍软件功能安全代码结构化覆盖度量测试的3种方法,本篇将介绍语句覆盖。

02

语句覆盖测试能测试哪些东西

上一章节讲的3种覆盖方法(statement coverage、branch coverage、MC/DC)是从不同维度对被测试代码进行测试设计。我们知道代码是从第一行开始由上向下来执行的,在执行过程中遇到某些循环或者逻辑判断时部分行会跳过,简单理解语句覆盖就是要求所有代码被执行一遍,从这个维度做测试设计进行测试。

我们用以下一段简单代码来举例说明:

鉴源实验室丨软件代码结构化覆盖测试-语句覆盖_第2张图片

这段代码总共19行,我们可以看到输入的变量a和b决定了输出值y,对于这段代码的语句覆盖率计算是看我们的代码执行到了哪一行,然后除以19得到的。如我们设计a=9,b=10,那么得到y=y+10=20,语句执行到第9行,跳到第19行结束,总共运行10行,这条测试用例的语句覆盖率就是50%。

如果我们设计a=15,b=10,会执行到第10至第14行。所以我们再设计第三条测试用例令a=30,b=10的时候,这3条测试执行会覆盖所有的语句,此时语句的覆盖率就达到了100%。

在实际的工作测试中,我们碰到的代码不可能这么简单,当然通常我们也都是借助工具来进行代码的测试工作,不会纯人工来对代码进行测试设计和手动测试。目前大多数测试工具都会自动生成一部分的用例来对代码进行测试,但覆盖率不会达到100%,此时就需要我们通过分析代码以及已生成的覆盖用例,手动添加完成剩余覆盖。

03

使用工具来进行语句覆盖测试

本章节我们使用SmartRocket TestGrid这款工具进行代码的语句覆盖测试分析,给大家介绍工具是如何生成测试用例完成测试任务的。工具的操作使用说明篇幅过大,且不属于我们文章分享的目的,在此我们不做过多介绍。

3.1 工具测试举例

针对如下代码:

鉴源实验室丨软件代码结构化覆盖测试-语句覆盖_第3张图片

这段代码我们可以看到函数的形参有两个,分别是lua_State *L、init op,代码逻辑也较为简单,当op!= LUA_OPUNM且op!= LUA_OPBNOT为真时执行api_checknelems(L, 2),判断为假时执行其他操作。

工具自动分析后会生产控制流图如下:

鉴源实验室丨软件代码结构化覆盖测试-语句覆盖_第4张图片

控制流图可以帮助我们分析代码复杂逻辑下执行的路径情况,对于覆盖统计有非常大的帮助。在本例中我们可以设计两条测试用例分别覆盖判读逻辑为真和为假的情况,这样就可以完成语句100%覆盖。这两天测试用例分别是1.op!= LUA_OPUNM为真,op!= LUA_OPBNOT为真,2.上述两个判断条件一真一假,或者两个都是假。

我们通过查看项目头文件可以得到LUA_OPUNM、LUA_OPBNOT两个常量的值分别为12和13,下图为工具自动生成的测试用例1:

鉴源实验室丨软件代码结构化覆盖测试-语句覆盖_第5张图片

我们主要看输入形参的赋值和输出指针目标的预期赋值,本函数中未编写对判断做出相应的返回值,只是针对不同判断结果执行了一些操作,因此工具没有对实际值和预期值分别进行赋值。本例中变量op赋值了14,所以这条测试用例覆盖的是代码中为真的分支语句。

下图为测试用例2:

鉴源实验室丨软件代码结构化覆盖测试-语句覆盖_第6张图片

本例中变量op赋值12,判断条件一真一假,所以覆盖的是代码中判断结果为假语句分支代码。对于形参L的赋值,需要查看代码中对于lua_State的定义,虽然这段代码没有返回值,但是两个分支都执行了某些操作执行,这些执行都涉及到了形参L。

我们可以看到工具通过这两条测试用例分别覆盖了两个判断的分支,把所有代码都执行了一遍,所以这段代码的测试覆盖率就是100%。

04

测试小结

在实际的代码覆盖度测试中,测试对象为软件代码,在代码测试的层面我们有几点总结跟大家分享,希望给大家带来帮助。

1. 工具自动生成的测试用例在某些情况下不能自动达到100%,此时就需要我们分析代码,以及已有用例的覆盖情况,对未覆盖部分进行人工补充。

2. 在代码中有部分是天然达不到100%覆盖的,这部分代码有些是做了故意的设计,对系统在代码层面做保护,对于这种情况需要手动补充说明,如设计中止函数自动退出此处代码执行等。

3. 使用测试工具的不同会遇到代码测试统计结果上的差异,如代码总行数会因为空行、注释、头文件等统计方法的不同,得到的最终代码总行数不同,还有覆盖率计算,有部分工具对于代码中函数“{}”等的统计方法不同,会出现即使同样测试语句覆盖用例设计,但最终工具给出的统计结果不一样。

4. 使用工具自动测试过程中通常会提示各种错误,这些错误通常是由头文件、宏定义、数组越界等问题导致,经过调整后会大大提升工具的自动测试覆盖率。

5. 既然测试对象是纯代码,所以严格意义上来说,对于测试人员代码覆盖度测试是没有很大的行业壁垒划分的。也就是我们的测试标准可以分为汽车行业软件功能安全标准、轨交行业功能安全标准、航空行业软件功能安全标准等等,但这些软件可能都是基于C、C++语言编写,对于测试人员只要是同一种语言编写的软件我们不会因为行业不同会遇到不同的测试技术上的问题,测试人员在代码测试的跨行业通用性上特别有利。

6. 测试行业在近几年互联网、计算机、软件工程等专业爆火的同时得到了快速发展,功能测试、性能测试、自动化测试、兼容性测试、健壮性测试等等测试技术也日趋完善,测试期待着新的技术普及点。代码测试以前在很多行业会省略这个验证过程,或者是由开发人员自测,现在伴随着功能安全乘势而起,对于提高测试工程师个人能力也有极大的帮助,我们也希望通过本课程更大家带来更多的提升。

参考资料:

[1] ISO 26262-6-2018 Road vehicles - Functional safety - Part 6 Product development at the software

你可能感兴趣的:(鉴源论坛,软件代码测试)