电子说
测量代码覆盖率对于嵌入式系统来说越来越重要,但需要一些经验。这是因为有一些障碍需要克服,尤其是小目标。但是,使用正确的方法和合适的工具,无需过多努力即可测量测试覆盖率。九个实用技巧可帮助您入门。
测量测试覆盖率,也称为代码覆盖率,对于嵌入式系统变得越来越重要。在许多情况下,这些设备对安全或业务至关重要。流程基于物联网设备,患者依赖工作起搏器和智能胰岛素泵,没有嵌入式软件就无法想象汽车和航空业。这份清单几乎可以无限延续。随着各种设备的重要性增加,在安全、安保和功能方面必须满足的要求也在增加。安全标准将这一点考虑在内,并明确要求将测试覆盖率记录为产品验证的一部分。
特别是对于初学者来说,测量代码覆盖率似乎非常复杂和耗时。但是,如果您注意一些基本方面,事情很快就会变得容易。
1.设定期望
通常并不完全清楚对代码覆盖的期望。覆盖率测量并非旨在直接改进代码。他们的目的是确定代码是否经过全面测试以及测试用例是否完整。因此,代码覆盖率更适合于改进测试——并最终证明已经执行了足够的测试。
2. 确定所需的测试覆盖水平
有许多不同的测试覆盖级别。可以说:测试覆盖率越严格和详细,实现它所需的努力和成本就越大。
不幸的是,只有少数标准,如航空领域的 DO-178C、电气/电子、可编程电子安全相关系统的功能安全性 IEC 61508 或汽车领域的 ISO 26262,对所需的代码覆盖级别给出了具体指导。
根据 IEC 61508 的安全完整性等级 (SIL) 或 ISO 26262 的汽车安全等级 (ASIL),需要语句覆盖率、分支覆盖率或 MC/DC(修改条件/决策覆盖率)(有关代码覆盖率级别的更多信息,请参阅单独解释)。以下适用于所有标准:可能错误的影响越危险,所需的覆盖级别就越严格。
这可以从 ISO 26262 标准的下表中看出。最高安全等级 ASIL D 需要最高覆盖等级 MC/DC。表中++代表强烈推荐,+代表推荐。在这里我们可以说完整的修改条件/决策覆盖自动意味着完整的分支覆盖,而完整的分支覆盖自动意味着完整的语句覆盖。
图 1:ISO 26262 表 12 – 软件单元级别的结构覆盖度量(来源:国际标准 ISO 26262-6)
对于没有通过标准规定的软件,提前确定哪些代码需要根据哪些标准进行测试也很重要。将上述标准用作指南并将测试范围与系统的关键性保持一致可能会有所帮助。
三、测试范围的确定
完整的代码覆盖率最初意味着已达到指定测试级别的 100%。然而,这通常只在安全关键区域是必要的。
仅仅为了满足这个标准而瞄准 100% 的代码覆盖率通常是没有帮助的。重要的是要知道为什么要运行某些测试用例。如果您不知道,那么重复测试一遍又一遍地运行已经测试过的代码的风险很高。这种更高的努力并没有得到回报,因为这些额外的测试并没有提供任何新的见解。顺便说一句,使用代码覆盖分析器是避免这种冗余测试的好方法。
在非关键应用领域,测试既不应该“太少”也不“完整”,而应该“足够”。
4. 确定支持的编程语言
有许多代码覆盖分析器:从免费工具(例如 GNU 编译器集合 (GCC) 的一部分 GNU Coverage Testing Tool Gcov)到全面的解决方案(例如Verifysoft Technology 的Testwell CTC++ ),它除了支持所有代码覆盖之外级别还支持各种语言。如果可能,公司使用的所有语言都应该能够使用单一的覆盖工具进行处理。这样,开发人员和测试人员可以在统一的界面中工作,而不必熟悉不同的工具。对于嵌入式软件开发,该工具应至少涵盖 C、C++ 和 Java。
关于代码覆盖级别的进一步说明
功能覆盖
函数覆盖率测量是否调用了程序的所有函数。功能覆盖率是通常测试覆盖率级别中“最弱的”。由于它忽略了软件的内部工作,所以它的实用性很低。
声明覆盖范围
语句覆盖率决定了测试执行了哪些语句。例如,这可以用于检测死代码。它还显示测试是否适用于所有语句。
决策覆盖/分支覆盖
在此覆盖级别上,每个决策必须至少测试一次为真,一次为假。对于普通的 if 语句,这对应于分支覆盖,其中每个分支都必须已执行。
条件覆盖
条件覆盖详细考虑复合决策。对于由通过布尔运算符组成的多个原子条件组成的决策,必须将这些条件中的每一个单独测试为“真”和“假”。
多条件覆盖和修改条件/决策覆盖 (MC/DC)
对于多条件覆盖,必须检查所有可能的真假组合以进行复合决策。在一个决策中有多个条件的情况下,这需要大量几乎不切实际的测试用例。因此,在实践和标准中,修改的条件/决策覆盖(MC/DC)是相关的,其中测试用例的数量减少了,而测试覆盖的信息价值仍然足够高。对于 MC/DC,使用复合条件的所有原子条件。对每一个原子条件测试一个测试用例对,这会导致复合条件的整体结果发生变化,但只有考虑的原子条件的真值发生变化,而其他原子条件的真值必须保持不变持续的。
5.节省内存空间
在小目标上测量代码覆盖率时,有限的内存空间通常是一个障碍。原因是需要对代码进行检测:为了测量覆盖率,代码覆盖率工具会在代码中插入计数器。此外,必须在要测试的目标上实现一个库,其中包括处理到主机的数据传输。
计数器通常作为全局数组存储在数据存储器中。特别是对于尺寸非常紧凑的目标,这可能会导致问题。
补救措施是专门用于嵌入式设备的代码覆盖率分析器。此类工具尽可能少用。在检测开销仍然很高的情况下,可以针对各个代码部分单独分析代码覆盖率。
第三种方法是减小计数器的大小。通常,计数器的大小为 32 位。特殊安排将计数器大小减少到 16 或 8 位。但是,必须注意避免溢出。覆盖分析仪 Testwell CTC++ 的 bit-cov-measure 是针对小型嵌入式目标和微处理器的特殊安排。
6. 检查可能对处理器造成的影响
为了节省成本,很多嵌入式设备不仅内存小,而且处理器也经常有局限性。但是,仪器也会影响处理器。因此,可能会超出定义的时间,这可能会导致在某些情况下程序运行错误。
不幸的是,由于处理器负载略高,无法提前可靠地预测是否会出现问题。可能的影响只会在相应的项目中变得明显。出于这个原因,还应根据其对时序的影响来选择代码覆盖分析器。如有必要,使用较小的计数器(如上所述)或部分仪器可以纠正这种情况。
也可以在覆盖分析的情况下运行一次测试,在没有覆盖分析的情况下运行一次,以确定覆盖分析是否导致程序行为的变化。
7.检查集成到您的工具链中的可能性
越来越多的测试正在自动化。这是有道理的,因为人工干预始终是潜在的错误来源,也会导致巨大的成本。构建系统测试的自动化是必需的,尤其是在使用持续集成/持续部署 (CI/CD) 的敏捷开发中。但是,这要求使用的代码覆盖分析器可以集成到工具链和构建系统中。此外,覆盖工具也应该独立于所使用的编译器。
尤其是在大型开发项目中,自动化测试和代码覆盖率的自动捕获是不可缺少的。因此,重要的是代码覆盖工具可以轻松顺利地集成到工具链中。另一方面,复杂的仪表板和前端对于自动化测试来说是微不足道的。
8. 验证报告的可理解性
代码覆盖会产生大量数据。每个测试领域——单元测试、模块测试、功能测试等——都提供了自己的代码覆盖率数据。为了获得完整的图片,应该汇总这些信息。由代码覆盖率分析器以有意义且可解释的方式准备此信息。
此外,这些数据在可能需要的认证或审核方面也很重要。
重要的是,覆盖工具提供的信息既可以用于进一步自动处理的机器可读形式(例如 XML),也可以以人类可读的形式(例如 HTML)提供,以便快速和良好地概览。
图 2:代码覆盖率分析器 Testwell CTC++ 的 HTML 报告(函数摘要)一目了然地显示了测试覆盖了哪些函数。完全覆盖的功能以蓝色显示。对于以红色显示的功能,覆盖率低于 100%。例如,函数“lights()”具有 75% 的多条件覆盖率和 83% 的语句覆盖率(TER 代表“测试有效性比率”)。(来源:Verifysoft Technology)
图 3:Testwell CTC++ 的执行配置文件显示了源代码中涵盖项目的详细信息。(来源:Verifysoft Technology)
9. 检查代码覆盖工具是否适合开发安全关键型软件
对于安全关键型软件的开发,不言而喻,代码覆盖工具必须支持相应标准要求的覆盖水平。
此外,标准要求对整个工具链进行鉴定。用于代码覆盖分析器的工具鉴定工具包的可用性大大简化了这项工作。在这种情况下,工具提供商是否在此提供适当的建议也很重要。
结论
测量代码覆盖率并非易事,但也不是太复杂。因此,几乎没有任何充分的理由放弃代码覆盖——即使在非关键领域也是如此。测试覆盖率在多个层面上有所帮助:可以优化测试和测试程序,从而带来显着的成本和时间优势。此外,代码覆盖率确保产品已经过充分测试,并以一定的最低质量到达客户手中。
嵌入式系统供应商不应该重蹈 IT 行业的覆辙:交付在客户现场成熟的“香蕉软件”。嵌入式设备的用户不会接受这一点——尤其是当涉及“关键”产品时,例如汽车行业的医疗设备或 ECU。
审核编辑 黄昊宇
全部0条评论
快来发表一下你的评论吧 !