《嵌入式软件自动化测试》阅读笔记

题记

近几年的工作主要在嵌入式软件方面,有幸经历了需求-设计-开发-测试等主要过程,但由于各种现实原因,例如体系未形成等,所以,对测试过程的了解并不透彻,更不用说有效实践。偶遇《嵌入式软件自动化测试》一书,如醍醐灌顶,帮助我厘清了不少疑问,特此摘抄重要部分。

1.1 软件测试的定义及发展

         软件测试不应该专注于验证软件是工作的,相反,应该用逆向思维去发现尽可能多的错误。从心理学角度看,如果将“验证软件是工作的”作为测试的目的,非常不利于测试人员发现软件错误。应该将验证软件是不工作的作为重点,假定软件总是有错误的,测试就是为了发现缺陷,而不是证明程序无错误。如果发现了问题则说明程序有错,但如果没有发现问题,也不能说明问题就不存在,而是至今未发现软件中所潜在的问题。

        有必要将软件测试延伸到需求、设计阶段,即对软件半成品(阶段性成果)——需求定义文档、设计技术文档进行验证,从而将动态测试延伸到静态测试,尽早地发现问题,把问题消灭在萌芽之中,将每个阶段产生的缺陷及时清除,以极大地提高产品的质量,有效的降低企业的成本。

1.5 软件测试的分类

基于是否关注软件结构与算法,分为:黑盒测试和白盒测试。

基于是否执行被测试软件,分为:动态测试和静态测试。

基于测试对象划分的不同测试级别,包括:

单元测试:依据详细设计说明,对软件基本组成单元进行的测试,以检查代码实现是否符合设计目标,以白盒测试为主,黑盒测试为辅,静态测试和动态测试相结合。

集成测试:依据概要设计说明,将已分别通过测试的单元按设计要求以某种集成的策略对组合成的部件进行的测试,检查部件是否符合设计目标,以白盒测试为主,黑盒测试为辅,静态测试和动态测试相结合。

配置项测试:依据软件需求规格说明,测试配置项是否符合所有需求,包括功能性需求与非功能性需求,通常采用黑盒测试和动态测试方法

系统测试:依据系统/子系统需求规格说明,以验证系统的功能和性能等指标是否满足系统规格说明所指定的要求,通常采用黑盒测试和动态测试方法

单元测试,需要关注的主要内容:

1、目标:确保模块被正确地编码

2、依据:详细设计描述

3、过程:包含设计、脚本开发、执行、调试和分析结果的完整过程

4、执行:有程序开发人员和测试人员共同完成

5、采用方法:以白盒测试为主,以黑盒测试为辅

6、评估方法:通过所有单元测试用例,代码没有严重缺陷

单元测试的基本过程由以下5个步骤组成:

1、在详细设计阶段完成单元测试计划

2、建立单元测试环境,完成测试设计和开发

3、执行单元测试用例,并且详细记录测试结果

4、判定测试用例是否通过

5、提交单元测试报告

概括来讲,单元测试是对单元代码的规范性、正确性、安全性、性能等进行验证

通过单元测试,还需要验证一下内容:

1、数据或信息能否正确地流入和流出单元

2、在单元工作过程中,内部数据能否保持其完整性,包括内部数据的形式、内容及相互关系不发生错误,也包括全局变量在单元中的处理和影响

3、在数据处理的边界处能否正常工作

4、单元的运行能否做到满足特定的逻辑覆盖

5、单元中发生了错误,其中的出错处理措施是否有效

6、指针是否被错误引用、内存是否被及时释放

7、是否存在安全隐患,是否使用了不恰当的字符串处理函数等

单元测试实施的特点是:

1、实施效果非常好,但实施阻力比较大,阻力主要来源于人员和管理因素,一般只在关键的程序单元中实施

2、有比较系统的理论和方法,但也依赖于系统的特殊性和开发人员的经验

3、有大量的辅助工具,并且开发人员自身也会开发适用于特定场景的测试代码和测试工具

集成测试主要依据概要设计说明,检查与概要设计相关的程序结构、模块接口等方面的问题。集成测试是将已分别通过测试的单元按设计要求组合起来再进行的测试,其主要功能或目标是测试单元或模块之间的接口

对软件进行集成测试前,需要首先完成以下工作:

1、需要对构成软件部件的每个软件单元的单元测试情况进行检查

2、若需要对软件部件进行必要的静态测试,则应先于动态测试进行

3、需要建立相应的部件测试环境,如桩模块和驱动模块,且测试环境应通过评审

在集成测试过程中,需要满足以下几点要求:

1、需要对软件设计文档规定的所有各软件部件的功能、性能等特性进行逐项测试,且每个特性应至少被一个正常的测试用例和一个被认可的异常测试用例覆盖,测试用例的输入应至少包括有效等价类值、无效等价类值和边界值

2、应对软件单元和软件部件之间的所有调用进行测试,以达到要求的测试覆盖率

3、软件部件的输出数据及其格式、软件部件之间、软件部件和硬件之间的所有接口均需被测试

4、当运行条件(如数据结构、输入/输出通道容量、内存空间、调用频度等)在边界状态下,进而在人为设定的状态下时,对软件部件的功能和性能进行测试

5、按照设计文档的要求,对软件部件的功能、性能进行强度测试

6、对安全性关键的软件部件,需对其进行安全性分析,明确每一个危险状态和导致危险的可能原因,并对此进行针对性的测试

集成测试基本可以概括为以下两种模式:

1、非渐增式集成测试模式:先分别测试每个模块,再把所有模块按设计要求放在一起结合成所要的程序

2、渐增式集成测试模式:把下一个要测试的模块与已经测试好的模块结合起来进行测试,测试完以后再把下一个应该测试的模块结合进来测试

两种模式的优缺点:

1、渐增式需要编写的软件较多,工作量较大,非渐增式开销较小

2、渐增式发现模块间接口错误较早,而非渐增式较晚

3、非渐增式发现错误后,较难诊断,而使用渐增式,如果发现错误,则该错误往往和最近加入的那个模块有关

4、渐增式测试更彻底

5、渐增式需要较多的设备和时间

6、使用非渐增式,可以并行测试

测试类型

1、文档审查

对委托方提交文档的完整性、一致性和准确性进行的检查。文档审查应确定审查所用的检查单,不同文档需要用不同的检查单,检查单的设计需要经过委托方确认。

2、代码审查

检查代码和设计的一致性;检查代码执行标准的情况;检查代码逻辑表达的正确性;检查代码结构的合理性;检查代码的可读性。代码审查可由软件自动或人工完成,审查的重点是文档错误、编程语言错误、逻辑错误、接口错误、数据使用错误、编程风格不当、软件多余物等。

3、代码走查

代码走查的测试内容与代码审查的内容基本一样,但在过程上有差别,在代码走查中,根据事先设计的测试用例,人工执行测试用例、游历程序以发现错误。

4、静态分析

静态分析一般包括控制流分析、数据流分析、接口分析、表达式分析、语法/语义分析等。静态分析常使用软件工具进行。

5、逻辑测试

逻辑测试时测试程序逻辑结构合理性、实现的正确性。一般需要进行语句覆盖、分支覆盖、条件覆盖、条件组合覆盖、路径覆盖逻辑测试。

6、功能测试

7、性能测试

8、接口测试

9、人机交互界面测试

10、强度测试

强制软件运行在异常乃至发生故障的情况下(设计的极限状态甚至超出极限),检查软件可以运行到何种程度的测试。

11、余量测试

对软件是否达到规格说明中要求的余量的测试。若无明确要求,一般至少保留20%的余量。

12、可靠性测试

13、安全性测试

14、恢复性测试

对有恢复或重置功能的软件的每一类导致恢复或重置的情况逐一进行的测试,以验证其恢复或重置功能。恢复性测试是要证实在克服硬件故障后,系统能否正常的继续进行工作,且不对系统造成任何损害。

15、边界测试

对软件处在边界或端点情况下运行状态的测试。一般需进行输入/输出域、状态转换、功能界限、性能界限与容量界限的边界或端点测试。

16、数据处理测试

对完成专门数据处理功能所进行的测试,一般需要进行数据采集功能、数据融合功能、数据转换功能、删除坏数据功能、数据解释功能的测试。

17、安装性测试

18、容量测试

检测软件的能力最高能达到什么程度的测试。容量测试一般应测试在正常情况下软件所具备的最高能力,如响应时间或并发处理个数等能力。

19、互操作性测试

为验证不同软件之间的互操作能力而进行的测试。一般需进行同时运行两个或多个不同的软件、软件之间发生互操作的测试。

20、敏感性测试

为发现有效输入中可能引起某种不稳定性的数据组合、可能引起某种不正常处理的数据组合的测试。

21、标准符合性测试

22、兼容性测试

验证被测软件在不同版本之间的兼容性。有两类基本的兼容性测试:向下兼容性测试和交错兼容性测试。向下兼容性测试是测试软件新版本保留早期版本的功能的情况;交错兼容性测试是要验证共同存在的两个相关但不同的产品的兼容性。验证软件在规定条件下与共同使用若干实体或实现数据格式转换时能满足有关要求能力的测试。

23、中文本地化测试

4.1 等价类划分测试

        基本目标是在满足某种覆盖率的前提下大量减少测试用例数量。测试过程很简单,分为两步:一是合理地划分等价类;二是为每个等价类选取一个输入值来生成测试用例。不同的输入类型需要不同的等价类划分方法。大体来讲有3种等价类划分过程,而且在划分等价类时要考虑到合法的输入与不合法的输入,不合法的输入通常更容易发现缺陷。

        情况一:如果是连续的值域,那么等价类可以划分为一个合法的等价类与两个不合法的等价类。比如中国的地理经度,最东端在黑龙江和乌苏里江的主航道中心线的相交处(东经135度),最西端在帕米尔高原附近(东经73度)。在东经范围内可以设计一个合法的输入东经130以及两个非法的输入东经140和东经70。

        情况二:输入时不连续的离散值,比如要求输入一个人的工作小时数(整数)。根据国家的法律,合法的取值是0~8之间的任意整数。在划分非法等价类时,我们要选取两个域,一个是小于0的域,一个是大于8的域,可以取-2与12。

        情况三:输入是枚举类型的值,比如某市的税务系统要求,没有收入的人可以免税,人的身份有几种:学生、家庭主妇、教师、军人、工人、商人、公务员。在这种情况下,学生和家庭主妇都是合法的输入,其余都是非法的输入。通常在时间和经费有限的情况下,在合法与非法的等价类中先取一个即可,在条件允许的情况下,可以考虑其他因素以选取更多的值进行测试。

4.2 边界值测试

对应等价类测试情况一:选取东经73和东经135

对应等价类测试情况二:选取-1,0,1,7,8,9

4.3 因果图测试

4.4 决策表测试

4.5 逻辑覆盖测试

1、语句覆盖

        语句覆盖的基本思想是设计足够的测试用例,使得每个可执行语句都至少由一个测试用例执行一次。语句覆盖用于计算和度量在源代码中可执行的语句数,但它仅仅针对程序逻辑中显式存在的语句,对隐藏的条件是无法测试的,因此语句覆盖也是最弱的逻辑覆盖。语句覆盖率=至少被执行一次的语句数量/可执行的语句总数。

2、判定覆盖

        判定覆盖的基本思想是设计一系列测试用例,运行待检测的程序,使得程序中每个判断中取真和取假的分支被至少执行一次。由于一个判断即代表程序的一个分支,因此判定覆盖也被称为分支覆盖。判定覆盖率=至少被执行一次的判定结果的数量/判定结果的总数。

        判定覆盖的优点在于具有比语句覆盖更强的测试能力,同时判定覆盖也具有和语句覆盖一样的简单性,无须细分每个判定就可以得到测试用例。判定覆盖的缺点在于,其大部分的判定语句由多个逻辑条件组成,在运行过程中,往往仅能够判断出最终的整个结果,而忽略每个条件的取值情况,在很大程度上会遗漏部分测试路径。因此,判定覆盖仍是较弱的逻辑覆盖。

3、条件覆盖

        条件覆盖的基本思想是设计一系列测试用例,运行待测试的程序,使得程序每个判断中每个条件的可能取值至少被执行一次。条件覆盖率=至少被执行一次的条件结果的数量/条件结果的总数。

        条件覆盖通常比判断覆盖强,因为它使判定表达式中的每个条件都取到了两个不同的结果,而判定覆盖却只关心整个判定表达式的值但是,也可能由相反的情况:虽然每个条件都取到了两个不同的结果,但判定表达式却始终只取一个值,往往会使测试用例无法覆盖整个程序的全部分支。

4、判定-条件覆盖

        既然判定覆盖不一定包含条件覆盖,条件覆盖也不一定包含判定覆盖,自然会提出一种能同时满足这两种覆盖标准的逻辑覆盖,这就是判定-条件覆盖,判定-条件覆盖实际上是把(2)和(3)覆盖方式结合起来的一种设计方式,本质上是判定和条件覆盖设计方法的交集。其基本思想是设计足够多的测试用例,使得判断条件中所有条件的可能取值至少被执行一次,同时,所有判断的可能结果也至少被执行一次。判定-条件覆盖率=条件结果或判定结果至少被执行一次的数量/(条件结果的总数+判定结果的总数)。

5、条件组合覆盖

        与条件覆盖的不同之处在于,条件组合覆盖不是简单的要求每个条件都出现“真”与“假”两种判定结果,其基本思想是,设计足够多的测试用例,使得判断中每个条件所有可能的组合都至少出现一次。条件组合覆盖率=至少被执行一次的条件组合数量/总的条件组合数。

        显然,满足“条件组合覆盖”的测试用例是一定满足“判定覆盖”和“条件覆盖”和“判定-条件覆盖”的。仔细分析后,可能会发现条件组合测试的思路有些冗余和浪费,在测试过程中出现一些无意义的测试。因此,在原有的条件组合覆盖的基础上,由一种修该的条件组合覆盖(MC/DC),MC/DC测试覆盖思路如下:

1、每一个判断的所有可能结果都至少出现一次

2、每一个判断中所有条件的取值都至少出现一次

3、每一个进入点与结束点都至少被执行一次

4、判断中每一个条件都可以独立的影响判断的最终结果

事实上,条件组合覆盖属于极强的逻辑覆盖,但尽管如此,该覆盖依然无法覆盖全部路径,因此其测试也非足够充分,所以,更充分的测试不仅要求覆盖所有条件和所有判定,而且还要覆盖基本路径。

6、基本路径覆盖

        基本路径覆盖的思想就是在程序控制流图的基础上,通过分析控制结构的环路复杂性,设计足够多的测试用例,执行的路径满足基本路径集合,如果程序中有循环,则要求每个循环被至少执行一次。

        其基本步骤如下:

        1、设计程序流程图。用程序流程图描述程序控制流,利用顺序、分支、循环等基本图元,来描述任意程序结构。

        2、计算程序复杂度。实际上,通过对程序流程图分析得到的独立路径数目就是该程序的复杂度。

        3、确定基本路径。通过分析程序流程图的基本路径来导出程序的基本路径集合。

        4、准备测试用例。要确保基本路径组中的每一条路径都至少被执行一次。

        基本路径覆盖的前提是事先清楚有多少条基本路径,对于比较简单的小程序来说,实现基本路径覆盖是可能的,但是如果程序中出现了多个判断和多个循环,则可能的基本路径数目将会急剧增长,导致实现基本路径覆盖几乎是不可能的。因此,计算程序中的基本路径数即圈复杂度,是进行基本路径覆盖的必要条件。计算公式如下:V(G)=e-n+2。其中,V(G)是区域数,是由边界和节点包围起来的图,计算时应包含其外部区域。e为边数,n为节点数。基本路径覆盖率=至少被执行一次的线性无关的路径数/基本路径数。

        其中,线性无关的路径是指将程序转换为程序控制流图后,执行的路径线性无关。

逻辑覆盖测试举例

以如下代码为例,说明上述几种逻辑覆盖测试。

int foo(int a, int b, int c, int x)
{
    if(a>1 && b==0) {
        b = x+a;
    }
    if(c==2 || x>1) {
        x = x+1;
    }
    return x+b;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值