基于VectorCAST平台的铁路信号软件动态测试方法
2022-11-10武中奇赵雅囡李凤娇
武中奇,赵雅囡,李凤娇
(北京和利时系统工程有限公司,北京,100176)
1 铁路信号安全软件测试覆盖率的要求
随着中国高速铁路的迅速发展,铁路信号控制系统的自动化程度和复杂程度也成倍增长。其中,对铁路信号安全相关软件的质量属性提出了更高要求。除了满足功能性、可靠性、易用性、效率、可维护性、可移植性等要求外,特别强调软件安全完整性的特有属性。软件测试是保证这些属性得到实现的重要手段。对不同安全完整性等级(SIL)要求的铁路信号系统软件,其代码测试覆盖率及类型有不同的要求。SIL1/2等级的软件要求做语句覆盖(Statement),SIL3等级的软件要求做语句+分支覆盖(Statement + Branch),SIL4等级的软件要求做语句+修正条件判定覆盖(Statement+MC/DC)。《铁路信号安全软件测试暂行技术要求》(TJ/DW 231-2020)中对需达到SIL4级安全产品软件测试覆盖率的要求:
(1)软件源代码的每条语句都被至少一个测试用例覆盖,语句100%覆盖;
(2)软件源代码的每个分支都被至少一个测试用例覆盖,分支100%覆盖;
(3)软件源代码的每个分支的每个条件都被独立起作用的测试用例覆盖,即MC/DC100%覆盖。
通常的覆盖率统计在单元测试中完成,例如使用C++TEST工具进行单元测试,得到该单元的覆盖率。不同单元的测试覆盖率数据综合在一起,得到系统软件的总体覆盖率。但是单元测试不同于系统动态测试,模块的接口和行为在系统功能中的表现不同于其单独作为被测对象的表现。例如,该模块在当前系统功能的测试用例中不会被调用到,或者其中部分分支由于条件不具备而无法执行到。出现此类情况的可能原因包括:
(1)该模块执行了非预期的行为或者与软件功能需求规格书的要求不一致。
(2)测试案例设计不够充分,没能覆盖到该模块。
(3)测试环境或条件限制当前模块被调用。
与之对应的解决方法是:
(1)该模块是非必要的,因而删除。
(2)分析该模块的功能和接口,丰富动态测试用例集,使其得到完全执行。
(3)基于分析的测试可以作为对测试用例无法执行到的模块代码覆盖率的补充。
单元测试无法判断在系统动态测试过程中某个特定模块的执行情况,因而无从判断该模块语句覆盖率、分支覆盖率以及MC/DC代码覆盖率的具体度量数值。这里,引入一种自动测试的工具-VectorCAST,是由第三方开发的商用自动测试平台。它可以执行单元测试,亦可对动态测试的代码覆盖率进行分析和统计(QA)。支持的测试覆盖类型包括语句覆盖,语句+分支覆盖,语句+MC/DC覆盖,函数覆盖,函数调用覆盖,代码执行路径覆盖等。
2 VectorCAST QA(以下简称VCAST QA)应用方法
VCAST QA对软件的测试覆盖率度量有很好的支持,主要包括的测试覆盖率类型有:
(1)语句覆盖(Statement):用于描述特定动态测试用例运行时每个可执行语句占整个单元语句总数的比例。
(2)分支覆盖(Branch):用于描述特定动态测试用例运行时每个可执行分支占整个单元分支总数的比例。
(3)函数覆盖(Function):用于描述特定动态测试用例运行时所执行到的函数。
(4)修正条件判定覆盖(MC/DC,Modified Condition/Decision Coverage):一个MC/DC对是一对真值向量,这对真值向量使得判定语句有不同的结果,但结果的不同是由于真值向量中一个条件值的变化引起的。
另外还包括由以上覆盖类型组合而成的覆盖类型,这些组合覆盖类型的执行结果会统一合成在一份测试报告中。主要的组合覆盖类型有:
(5)函数+函数调用覆盖(Function + Function Call)。
(6)语句 +MC/DC覆盖(Statement + MC/DC)。
(7)语句+分支覆盖(Statement + Branch)。
通常的动态测试对语句执行覆盖率以及函数调用情况很难做出定量的描述,更为困难的是对MC/DC覆盖率有要求的系统动态测试,尤其难以测量。这是因为对于具有 N 个条件的布尔表达式,其完备的测试用例有2N组。很难针对具体的条件判定设计出符合MC/DC要求的100%代码覆盖率的测试用例集。即便设计出来,执行成本也会很大。VCAST QA提供了一种可行的方法,在软件系统动态集成测试中同步统计MC/DC测试覆盖率,进而分析没有达到100%MC/DC代码覆盖率是由于什么原因导致的。根据经验,可能的原因包括但不限于:
(1)动态测试用例集不完备。
(2)当前的测试环境受限导致无法执行到相应的真值对。
第2)种情况可以使用基于分析的测试(CBA)作为动态测试的补充实现MC/DC100%覆盖率。
通过VCAST QA分析系统动态测试覆盖率,首先需要对被测软件做一系列预处理。被测软件可以是嵌入式软件,也可以是运行在Windows系统的上位机软件。一致的处理流程大致可以概括为:
(1)在VCAST QA环境中新建工程。
(2)对新建的工程进行适当地配置,例如选择编译器、选择嵌入式CPU类型(Windows程序无需做此操作)等。
(3)加载被测源代码文件。
(4)对源文件进行插桩,插桩指以某种测试覆盖率类型对源文件进行预处理,但不会影响源文件的内部逻辑。插桩会导致源文件发生膨胀,这对内存较小的嵌入式软件会有较大影响,甚至导致编译后的可执行程序无法烧写进目标板。并且插桩后的源文件由于增加了VCAST QA的附加代码,可能会影响到嵌入式软件的时序。因此,对嵌入式软件进行插桩处理时要综合考虑哪些代码需要插桩。例如对变更的代码进行插桩会显著减小代码的膨胀率。需要说明的是对于嵌入式软件插桩后的源代码应进行处理。不同于Windows软件,动态测试结果数据可以自动保存在被测软件的工程目录下。嵌入式软件则需要修改部分源代码。目的是在特定时刻或条件下,利用嵌入式目标板的对外接口,例如串口或者网口,将内存区域内VCAST QA数据发送到PC机接收端,接收方式可以是超级终端或者Wireshark等。如果嵌入式系统有记录卡,也可将VCAST QA数据存放在记录卡内,通过读卡器读取。
(5)对经过插桩的源代码进行编译,运行,采集输出数据并存储为*.DAT格式。
(6)将*.DAT数据导入到VCAST QA环境中,观察并分析系统动态测试代码覆盖率。
3 VCAST QA应用举例(以Windows环境中C++程序为例)
对C++例程进行Function + Function Call插桩和Statement + MC/DC插桩,并对结果进行分析。
3.1 例程进行Function+Function Call插桩后用例动态测试的运行结果
图1说明:
图1 运行结果
(1)Unit显示了被测文件的名称,本例为brass.cpp。
(2)Subprogram列举本文件的所有函数模块。
(3)Complexity显示了对应模块的代码复杂度。
(4)Functions显示了函数被调用的状态,100%为被调用,0%为未被调用。
(5)Function Calls显示了特定函数被执行的语句数量占该函数可执行语句总数的比例。例如BrassPluss::withdraw函数的执行比例是85%,14条可执行语句中2条未被执行。
(6)TOTALS是对总体的统计,Functions列90%是由于BrassPluss类的另一个重载构造函数未被执行导致。
函数及函数调用覆盖率统计可以显示某个文件中函数被执行的情况。实际系统动态测试中,关注的焦点是软件功能是否满足系统功能需求规格说明书,发现并消除软件BUG,以证明软件产品是否具备发布条件。而往往忽视了代码的简洁,模块功能的安全防护,是否能被执行到等维度。Function+Function Call覆盖率对此问题进行了定量描述,为代码优化指明了方向。体现在:
(1)动态执行全部测试用例集后分析哪些函数未被执行到。若此函数对应了软件需求规格说明书,则说明测试用例集不够完备,需补充。若此函数未对应软件需求功能规格说明书,也未对应软件隐含需求,此函数需删除。
(2)由于铁路信号软件的高度复用性,通用模块经常对应于实际运营场景中的某种逻辑场景。若没被用例集执行到,则可反推软件设计规格说明书对软件功能描述是否有遗漏,即作为验证软件设计规格说明书的一种方法。
3.2 例程进行Statement+MC/DC插桩以及CBA分析后,用例动态测试的运行结果
图2说明(图1介绍过的内容不再重复):
图2 运行结果
(1)Statements列显示了对应函数模块被执行语句占该函数可执行语句的比例。Brass::Withdraw方法的可执行语句为7条,且全部被执行。覆盖率为100%。
(2)Branches列显示了被执行到的分支占该函数总分支数的比例。
(3)Pairs列显示了MC/DC真值对的统计描述,点击图3第32行左侧的红色箭头,出现如图4的界面。
图3
图4
图4显示了图3条件判定3.1中所有的MC/DC真值对,其中3、4真值对被测试用例执行,未被执行的真值对是2、4。因而MC/DC覆盖率是50%。
3.3 基于分析的用例覆盖(Covered By Analysis(CBA))
图4中Row 2红色表示Ca条件没有被执行到,由于例程中实际变量amt取值不可能为负数,因而这个条件不会被执行到。CBA提供一种基于分析的测试,作为测试覆盖率的补充。若经人工确认此条件为真时,函数的行为符合预期,则认为这个测试通过。CBA执行结果如图5所示。此时真值对的覆盖率是100%。图6展示了结合CBA结论的测试覆盖率报告。
图5
图6
Statement+MC/DC测试实现100%覆盖,是安全级软件产品满足SIL4要求的必要条件。实际动态测试中,动态测试用例集执行往往以黑盒测试的方式的为主,关注软件功能的实现以及软件缺陷的消除。没有有效途径深入软件结构内部分析软件动态执行的情况。VCAST QA提供了这样一种有效方法。通过对源代码进行插桩,实现对软件结构内部执行情况的追踪和测量。用于帮助开发和测试人员分析:
(1)哪些语句没有执行到,原因是什么,进而采取相应措施。
(2)哪些分支没有执行到,这些分支是否存在执行到的可能?若有可能被执行到,则通过丰富用例集或借助CBA进行补充测试。若任何场景都无法执行到,则此分支属于无用代码,应予以删除,以减小软件规模。
(3)哪些MC/DC真值对没有被执行到,这些真值对是否存在执行到的可能?分析过程同2)。
(4)Statement+MC/DC测试是优化软件系统的重要手段。尤其对于嵌入式系统,目标板资源有限,精简后的软件代码执行效率更高,安全性和可靠性可得到进一步提升。
4 总结
VCAST QA是铁路信号系统软件集成测试代码覆盖率测量的有效工具,对动态测试用例的完备性提供了间接的量化描述。同时,也为代码的复杂程度及有效性评估提供了重要依据,尤其适合在Windows环境中运行的C或者C++程序。对于嵌入式软件,由于目标板资源的限制,需要综合考虑代码插桩的类型以及被插桩代码的数量,防治插桩后的代码因体量太大而无法烧写进目标板的情况出现或者严重影响到目标程序的执行效率。