0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

边聊安全 | 软件单元测试的设计方法

上海磐时 ? 2025-09-05 16:18 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

软件单元测试的设计方法

写在前面:

软件单元测试的设计是一个系统化的过程,旨在验证代码的最小可测试部分(通常是函数或方法)是否按预期工作。软件单元测试的设计是确保代码正确性和可靠性的关键步骤。在软件单元测试中,等价类测试是一种很重要的测试设计方法,它通过将输入数据划分为若干个等价类,并从每个等价类中选取代表性的数据进行测试,以提高测试的全面性和效率。

01.

等价类划分法

在设计测试用例的时候,我们通常采用等价类划分法。等价类划分法的原理就是将无穷多数据缩减到有限个等价区域中,通过测试等价区域完成穷尽测试。

等价类划分要满足3个原则:

1. 互斥性:各个等价类之间应该是互斥的,即没有交集,确保每个输入数据只属于一个等价类。

2. 全面性:所有等价类的并集仍然是原始的输入域,即所有划分的等价类应该覆盖所有可能的输入条件,确保没有遗漏。

3. 以一代全:任意一个等价类中,所有数据相互“等价”,指一组输入数据,这些数据在程序的某个特定功能上被认为是等价的,即它们对程序的执行结果产生的影响是相同的。

等价类分为有效等价类和无效等价类

有效等价类:指那些在正常操作条件下预期程序能够正确处理的输入数据集合,对应有效输入域的数据,用以检测被测系统能否正确完成指定功能。

无效等价类:指那些预期程序无法正确处理或应该拒绝的输入数据集合,对应无效输入域中的数据,用以考察被测系统的容错性。

02.

如何划分等价类

那么如何划分等价类呢?

1. 识别输入条件:确定软件的输入条件,包括用户输入、系统参数、外部接口等。

2. 确定输入域:对于数值型输入,确定其取值范围;对于枚举型输入,列出所有可能的枚举值。

3. 划分有效等价类:识别那些符合软件规格说明的输入条件,这些构成了有效等价类。根据业务逻辑和规则,将输入条件分组,每组构成一个有效等价类。

4. 划分无效等价类:识别那些不符合软件规格说明的输入条件,这些构成了无效等价类。考虑软件如何处理错误输入,例如空值、非法字符、超出范围的数值等。

5. 考虑边界值:对于每个等价类,特别是处于边界的等价类,识别边界值。这些值往往是错误发生的高发区。

如输入条件规定了取值范围时,应划分一个有效等价类和两个无效等价类(一个低于范围,一个高于范围)。如果输入条件是一个布尔量,可以划分一个有效等价类(真)和一个无效等价类(假)。当输入数据有多个可能的值时,为每个值划分一个有效等价类,并考虑一个无效等价类来覆盖不符合任何有效值的输入。

例如Year变量需满足条件:1920<=year<=2012,范围内数值为有效等价类,<1920为一个无效等价类,>2012为一个无效等价类。

e3daf968-8a30-11f0-8ce9-92fbcf53809c.png

为有效等价类设计测试用例:

e3fa536c-8a30-11f0-8ce9-92fbcf53809c.png

为无效等价类设计测试用例:

e408624a-8a30-11f0-8ce9-92fbcf53809c.png

03.

边界值分析

在许多情况下,边界值往往是错误容易发生的地方,因此应特别注意边界条件的处理。对于每个等价类,特别是有效等价类,考虑其边界值,并可能将其视为单独的测试用例。

在进行边界值分析的时候,首先要确定边界值。根据需求规格,识别所有可能的边界条件,如最大值、最小值、上界、下界等,确定每个输入或输出参数的边界值。对于数值型数据,通常需要考虑其最大值、最小值和紧邻这些值的几个点。对于非数值型数据(如字符串长度、颜色选择等),也要确定其边界条件。

在设计测试用例的时候,要针对每个边界值,设计相应的测试用例。测试用例应包括正常范围内的值、刚好在边界上的值以及稍微超出边界的值。特别注意那些“刚好”达到边界条件的情况,因为这些问题在实际应用中往往更容易出现。

按照设计的测试用例执行测试,观察系统在边界条件下的行为是否符合预期,是否存在错误、异常或性能下降等问题。

通过遵循这些步骤,可以在软件单元测试中有效地应用等价类测试方法,以确保软件的功能安全性能得到充分验证。

04.

软件单元测试环境

在软件单元测试中,常见的测试环境有SIL、MIL、PIL和HIL,它们分别对应不同的测试阶段和目的:

1. MIL(Model in the Loop)模型在环测试

MIL测试是在模型开发阶段进行的,通过纯软件仿真的形式验证控制模型是否满足功能需求。它通常发生在系统工程师为了验证算法,使用控制算法模型控制被控对象模型的场景下,或者软件工程师做模型级别的集成测试。

2. SIL(Software in the Loop)软件在环测试

SIL测试是在MIL之后进行的,目的是验证自动生成的代码与算法模型的一致性。它使用与MIL相同的测试用例,检查自动生成的代码的输出是否与MIL阶段的模型输出一致。SIL测试通过运行系统环境中的车辆模型和虚拟ECU中的I/O模型来模拟控制器所需的各种传感器信号,并能接收台架传感器的信号和虚拟ECU发出的控制信号。

3. PIL(Processor in the Loop)处理器在环测试

PIL测试是将自动生成的代码编译为目标处理器需要的形式,并下载到目标处理器上运行,以防止编译过程引入新的错误。PIL测试也是等效性测试,其方式与SIL类似,不同之处是编译好的算法运行在目标处理器上,而SIL测试是在算法开发环境进行的。

4. HIL(Hardware in the Loop)硬件在环测试

HIL测试通常在开发出完整的控制器后进行,有时被控对象(如整车)还未完成开发,或者使用真实被控对象进行测试太危险或成本高。在HIL测试中,采用真实控制控制器和虚拟被控对象,以进行全面的功能验证和性能评估。HIL测试尤其适用于那些对实时响应、外部设备交互要求严苛的嵌入式系统,它能真实反映出软件在实际运行条件下的表现,有效暴露系统在软硬件集成层面可能出现的问题。

这四种测试方法各自的特点如下:

◆ MIL关注模型层面的功能实现及测试覆盖度情况。

◆ SIL关注的是生成的代码与模型间的一致性。

◆ PIL关注的是代码在目标处理器上的运行情况。

◆ HIL关注的是软硬件集成后的整体系统表现。

05.

软件单元测试覆盖率

ISO26262 part6的表9—软件单元级别的结构覆盖度指标如下表所示:

e41b7ea2-8a30-11f0-8ce9-92fbcf53809c.png

1. 语句覆盖:它关注的是程序中每个可执行语句是否至少被执行过一次。这是代码覆盖率分析中最基本的形式,其目的是确保测试用例能够覆盖到程序中的所有代码行。

由于其简单性,语句覆盖通常容易实现和维护。语句覆盖并不保证程序的逻辑路径被完全测试。例如,它不能保证所有的条件分支都被测试,或者所有的循环边界都被触及。为了达到100%的语句覆盖,测试用例需要设计得能够触发程序中的每一个语句。语句覆盖并不保证程序的质量,因为即使所有语句都被执行,也可能存在逻辑错误未被发现。

例:

e4282d00-8a30-11f0-8ce9-92fbcf53809c.pnge43efc56-8a30-11f0-8ce9-92fbcf53809c.png

2. 分支覆盖:它要求测试用例能够覆盖程序中所有可能的分支路径。分支覆盖关注的是程序中的控制流,特别是条件语句(如 if, else, switch 等)的真假分支是否都被执行过至少一次。

分支覆盖是路径覆盖的一个子集,它确保了程序中的每个分支都被测试。通过确保每个分支都被测试,分支覆盖有助于发现那些只在特定条件下才会触发的缺陷。为了达到分支覆盖,测试用例需要设计得能够触发每个分支的真假条件。分支覆盖比语句覆盖更严格,因为它要求测试每个条件的真假分支。分支覆盖并不保证所有可能的执行路径都被测试,特别是当存在多个条件时。

3. MC/DC覆盖:要求测试用例能够覆盖程序中所有可能的条件组合,并且每个条件都能独立影响决策的结果。这是一种高级的白盒测试技术,主要用于验证软件中的逻辑条件和决策路径。

MC/DC要求每个条件在决策中都能独立地影响决策的结果。这意味着,当改变一个条件的值时,决策的结果也会随之改变,而其他条件保持不变。MC/DC覆盖了所有条件的所有可能结果,以及每个决策的所有可能结果。实现MC/DC可能需要更多的测试用例,因为每个条件都需要独立地影响决策的结果。

MC/DC与其他覆盖标准的区别:

与语句覆盖的区别:语句覆盖关注于代码的行,而MC/DC关注于条件和决策的独立影响。

与分支覆盖的区别:

分支覆盖要求测试每个分支的真假路径,而MC/DC进一步要求每个条件都能独立地影响决策的结果。

让我们通过一个具体的C语言函数例子来展示如何为语句覆盖、分支覆盖和MC/DC覆盖设计测试用例。假设我们有以下函数:

e45132d6-8a30-11f0-8ce9-92fbcf53809c.png

语句覆盖测试用例:

语句覆盖要求覆盖函数中的每个语句至少一次。我们需要以下测试用例:

1. get_value(1,1)——覆盖语句1(x和y都大于0)

2. get_value(1,-1)——覆盖语句2(x大于0,y小于等于0)

3. get_value(-1,1)——覆盖语句3(x小于等于0,y大于0)

分支覆盖测试用例:

分支覆盖要求覆盖每个条件的每个可能分支。我们需要以下测试用例:

1. get_value(1,1)——条件1真,条件2真。

2. get_value(1,-1)——条件1真,条件2假。

3. get_value(-1,1)——条件1假,条件2不可达(因为我们已经知道x小于等于0,所以不会检查y)

4. get_value(-1,-1)——条件1假,条件2假。

MC/DC覆盖测试用例:

MC/DC覆盖要求每个条件在决策中都能独立地影响决策的结果。我们需要以下测试用例:

1. get_value(1,1)——条件1真,条件2真,覆盖语句1。

2. get_value(1,-1)——条件1真,条件2假,覆盖语句2。

3. get_value(-1,1)——条件1假,条件2不可达,覆盖语句3。

4. get_value(-1,-1)——条件1假,条件2假,再次覆盖语句3,但这次是为了证明条件1的独立影响。

为了满足MC/DC的要求,我们需要确保改变任何一个条件的值都能独立地影响函数的返回值。这意味着我们需要额外的测试用例来证明条件1和条件2可以独立地影响决策:

5. get_value(2, 0)——条件1真,条件2真,但y的值改变不影响决策,因为x大于0。

6. get_value(0, 1)——条件1假,条件2真,但x的值改变不影响决策,因为x不大于0。

通过这些测试用例,我们可以看到MC/DC覆盖比语句覆盖和分支覆盖更为严格,它要求每个条件都能独立地影响决策的结果。这有助于发现那些可能在条件组合中被隐藏的错误。

许多现代的集成开发环境(IDE)和测试工具都支持语句覆盖和分支覆盖,可以自动收集和报告覆盖率数据。一些自动化测试工具可以辅助实现MC/DC,通过分析代码逻辑并生成相应的测试用例。

e468d648-8a30-11f0-8ce9-92fbcf53809c.png

作者

边俊

磐时创始人/首席安全专家

汽车安全社区SASETECH发起人;智能网联预期功能安全工作组核心成员;国内最早从事汽车功能安全、预期功能安全的专家之一

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 测试
    +关注

    关注

    8

    文章

    5817

    浏览量

    129777
  • 软件
    +关注

    关注

    69

    文章

    5207

    浏览量

    89897
  • 汽车安全
    +关注

    关注

    4

    文章

    310

    浏览量

    35202
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    ISO26262汽车功能安全-单元测试软件

    嵌入式软件单元测试/集成测试工具-WINAMS
    发表于 04-18 14:45

    MCU进行单元测试方法

    背景MCU软件不同于常规的PC机或基于SOC的嵌入式软件,其一般情况下,与底层硬件耦合度高,资源有限,如何进行单元测试的问题困扰我很久。解决方案根据目前已知如下3种类型的方案:在目标板上运行此方案下,在程序代码中加入
    发表于 11-01 06:58

    单元测试/集成测试自动化工具--WinAMS

    为单位的自动化单元测试工具作为能够检验出仅凭系统测试以及整体测试无法发现的[潜在错误]的检测方法,[单元测试]在嵌入式开发领域受到广泛重视。
    发表于 06-17 18:26

    如何提高嵌入式软件单元测试效率

    在本指南中,您将学习如何通过在更短的时间内运行更多的测试来增加您的单元测试吞吐量。 这种效率的提高来自于使用虚拟平台而不是物理硬件作为开发平台。 本指南对任何开发或运行嵌入式软件单元测试
    发表于 08-28 06:31

    系统测试单元测试、集成测试、验收测试、回归测试

    系统测试单元测试、集成测试、验收测试、回归测试 单元测试
    发表于 10-22 12:38 ?1975次阅读

    单元测试常用的方法

    单元测试,是指对软件中的最小可测试单元进行检查和验证。对于单元测试单元的含义,一般来说,要根据
    发表于 12-21 10:17 ?3.8w次阅读
    <b class='flag-5'>单元测试</b>常用的<b class='flag-5'>方法</b>

    什么是单元测试_单元测试的目的是什么

    工厂在组装一台电视机之前,会对每个元件都进行测试,这,就是单元测试单元测试是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言,一个单元测试是用于判
    发表于 12-21 13:44 ?3.4w次阅读

    java单元测试的好处

    单元测试是编写测试代码,应该准确、快速地保证程序基本模块的正确性。好的单元测试的标准,JUnit是Java单元测试框架,已经在Eclipse中默认安装。许多开发者都有个习惯,常常不乐意
    发表于 12-21 14:24 ?4140次阅读

    什么是单元测试,为什么要做单元测试

    。 什么是单元测试单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。通常而言,一个
    的头像 发表于 04-28 17:21 ?1w次阅读

    MCU如何进行单元测试

    背景MCU软件不同于常规的PC机或基于SOC的嵌入式软件,其一般情况下,与底层硬件耦合度高,资源有限,如何进行单元测试的问题困扰我很久。解决方案根据目前已知如下3种类型的方案:在目标板上运行此方案下,在程序代码中加入
    发表于 10-26 10:06 ?35次下载
    MCU如何进行<b class='flag-5'>单元测试</b>

    RT-Thread上的单元测试:什么是单元测试单元测试的作用是什么?

    RT-Thread上的单元测试:什么是单元测试单元测试的作用是什么? ? ? ? ? ? 审核编辑:彭静
    的头像 发表于 05-27 16:06 ?2105次阅读
    RT-Thread上的<b class='flag-5'>单元测试</b>:什么是<b class='flag-5'>单元测试</b>?<b class='flag-5'>单元测试</b>的作用是什么?

    软件单元测试真的有必要吗?(上)

    本文着重探讨单元测试的重要性及其正面临的困境,并介绍功能安全标准中罗列的单元测试方法
    的头像 发表于 11-03 14:58 ?1351次阅读
    <b class='flag-5'>软件</b><b class='flag-5'>单元测试</b>真的有必要吗?(上)

    嵌入软件单元测试工具的作用

    嵌入软件单元测试工具是现代软件开发过程中不可或缺的一环。它的作用在于帮助开发人员对软件中的各个单元进行
    的头像 发表于 04-23 15:31 ?786次阅读
    嵌入<b class='flag-5'>软件</b><b class='flag-5'>单元测试</b>工具的作用

    严格的单元测试造就完美的软件

    关键系统时,更是对软件质量提出了极高的要求。而单元测试作为软件开发过程中的核心环节,其重要性不言而喻。 单元测试的作用 单元测试是指对
    的头像 发表于 11-26 13:22 ?624次阅读

    嵌入式软件单元测试的必要性、核心方法及工具深度解析

    一、为什么嵌入式软件必须重视单元测试? ?嵌入式系统的特殊性? 在汽车 ECU、医疗设备控制器等场景中,软件直接操控硬件,?单比特错误可能导致刹车失灵或呼吸机故障?。不同于 PC?软件
    的头像 发表于 03-21 14:53 ?688次阅读