APP下载

单元测试码重构方法在安全相关软件中的应用

2019-12-06上官霞南蒋剑沈昕

科技风 2019年32期

上官霞南 蒋剑 沈昕

摘 要:结合目前软件单元测试技术的研究现状,本文对提高软件单元测试质量和效率的测试模式及方法进行了深入的分析和研究,提出了包括如何命名单元测试用例以便交流出其测试意图、如何更有效地进行单元测试组件之间的依赖隔离及如何验证被测单元的间接输出以提高代碼行为覆盖率等测试码重构方法,并给出了相应的技术措施和具体应用。

关键词:模块依赖;代码行为覆盖率;硬编码测试替身;可配置的测试替身

一、绪论

软件代码行为的自动验证是最近几十年开发方法方面最大的进展之一,单元测试是软件测试过程中最基本的测试,其能够尽早暴露大量软件缺陷,降低软件工程整体开发成本,是前期测试中公认的、最有效的保证软件质量的活动之一。

测试不光只能运行,还需要对其进行后期维护。然而目前很多公司级软件测试项目中的测试坏味道包括模糊测试、缓慢测试、脆弱测试、甚至在产品代码中包含测试逻辑等,[1]由此问题导致的高维护成本表明如果缺少正确的方法,引入单元测试不一定能提高生产力,因此如何识别及排除这些坏味道并重构测试,让测试变得更易理解和维护、更健壮及可复用成为目前亟待解决的问题。

二、测试码重构方法

本文我们将以嵌入式C语言为例,测试工具使用C++Test,阐述下面提出的几种测试码重构方法是如何在安全相关软件的单元测试实践中运用的。

(一)测试用例命名应该能交流出其测试的意图

一个好的用例名称至少需要传达以下几方面信息,包含被测代码函数/方法名、与被测代码执行相关的所有输入值的重要特征及本用例预期输出的抽象描述。这样我们通过测试工具IDE的用例浏览器中可以很清楚的看到每个用例测试的不同场景,达到良好交流其测试的意图的目的,比较好的命名方案如下:

test___

其中:

:被测函数/方法的名称;

:被测试功能场景的描述;

:被测试场景下的期望行为。

(二)测试中应尽可能设计可配置的测试替身,而不是硬编码的测试替身

测试替身是出于运行测试这一明确目的而安装代替实际组件的任何对象或组件,对依赖组件DOC的调用通常返回某个值、更新其它参数或抛出异常。[2]

硬编码的测试替身由测试人员将依赖组件每个用例的返回值直接编码进替身组件中,而可配置的测试替身它将返回值或异常在用例运行时实时传递,这样我们可以以更简单的方式控制被测代码的间接输入,并使测试核心逻辑在用例体可见从而避免出现“神秘访客”,下面为可配置的测试替身的实现。

staticE_SysBool s_IsReceived = e_FALSE;

/*可配置的测试替身 */

void SetReceiveMsgDataStatus(E_SysBool inReciveStatus)

{

s_IsReceived = inReciveStatus;

}

E_SysBool IsReceiveMsgData(void)

{

retrun IsReceived;

}

(三)应能验证被测代码的间接输出以减少未测试的代码行为

很多时候,被测代码SUT产生的行为在其自身组件中存储,通过直接访问组件状态可以验证该行为,但是有时也会产生一些预期的副作用,比如有一个组件里有一个函数,该函数什么也没返回,或者至少没有什么可以用来确定它是否正确实现了其功能,在这种情况下,我们别无选择,只能从“后门测试”,通常程序对记录故障代码的调用没有返回表示正确完成的信息,确定其是否正常运行的唯一方法是,通过其它某个接口(一个允许检索故障类型的接口)与它交互。

static UINT32 s_FaultCode = 0UL;

/*一个允许检索故障代码的接口 */

UINT32GetFaultCode(void)

{

return s_FaultCode;

}

/*记录故障代码接口实现 */

UINT32RecordFalutCode(UINT32 inFaultCode)

{

s_FaultCode = inFaultCode;

}

/*测试用例中验证了记录故障代码的行为 */

voidtest_CheckLinkStatus_NotReceivedCycleOverMaxNum_LinkFalut(void)

{

/* Pre-condition initialization */

SetReceiveMsgDataStatus(e_FAlSE);

s_CommErrorCount =c_MaxCommErrorNum;

{

/* Tested function call */

E_SysBool IsLinkNormal = CheckLinkStatus();

UINT32 vFaultCode = GetFaultCode();

/* Post-condition check */

CPPTEST_ASSERT_EQUAL(e_FAlSE,IsLinkNormal);

CPPTEST_ASSERT_EQUAL(c_CommFalut,vFaultCode);

}

}

三、结语

本文选择的几种测试码重构方法经公司LKJ-15C安全认证项目中应用,证明其可以帮组开发人员在进行自动化单元测试实践时在几种可选项之间做出正确的选择,最终使我们设计的测试用例能够达到帮助理解被测代码、提高设计质量及降低代码缺陷引入风险等目标。

参考文献:

[1]Gerard Meszaros.xUnit Test Patterns:Refactoring Test Code.Addison-Wesley,Reading,MA,2007.

[2]James W.Grenning.Test Driven Development for Embedded C.Pragmatic Programmers.2011.

作者简介:上官霞南(1982-),男,汉族,江西吉水人,硕士,中级职称,研究方向:安全相关软件自动化测试。