软件测试技术实战:设计、工具及管理
上QQ阅读APP看书,第一时间看更新

1.1 软件测试的基本理论

软件测试的基本理论是软件测试的基础。在本书的开始,我们先学习和回顾一下软件测试的基本术语,这样可便于更深入地探讨软件测试的其他知识。

1.1.1 软件测试的定义

关于软件测试的定义有很多,这里主要介绍以下几个。

● 定义一:“软件测试是为了证明程序有错,通过运行程序发现其中存在的问题。”这个定义是在软件测试的第一部权威书籍《软件测试的艺术》中定义的,参见参考文献【1】。

从这个定义中可以看出。

➢ 软件测试可以证明软件有错。

这是显而易见的。通过测试,可以发现软件中的缺陷,这也证明了软件中存在错误。

➢ 软件测试不能证明软件没有错。

没有一个软件是不存在缺陷的,通过软件测试,我们可以找到软件中的错误,但是不可以找到软件中的所有错误。

● 定义二:“软件测试是根据软件开发各阶段的规格说明和程序内部结构而精心设计的一批测试用例(即输入数据及其预计输出结果),并利用这些测试用例来执行测试程序,以及发现错误的过程,即执行软件测试步骤。”

这个定义是目前比较流行的软件测试定义。

● 定义三:“软件测试是验证软件产品是否满足用户显性或者隐性需求的活动。”

这个定义是基于质量的定义而延伸出来的。质量的定义为“满足用户显性或者隐性需求的活动”,所以这个定义可以简化为“软件测试是验证软件产品是否满足质量的活动”。另外,这里定义中的“隐性需求”是指用户需求规格说明书中没有写出来的,如软件的易用性、可靠性、可维护性、效率等。

● 定义四:“软件测试包括验证(Verification)和确认(Validation)两种类型。”验证是指后一步是否满足前一步的需求,在软件开发过程中可以理解为需求分析是否满足用户需求,设计是否满足需求分析,开发是否满足设计。而确认是指最终产品是否满足用户的最初需求,如图1-1所示。

图1-1 验证与确认

1.1.2 软件测试术语

1.冒烟测试(Smoking Testing)

在大部分软件测试工作中,单元测试与集成测试是由开发工程师完成的,而系统测试是由软件测试工程师完成的。为了提高软件测试工程师测试的有效性,当软件测试工程师拿到开发工程师提交的版本后,就需要进行一次冒烟测试。冒烟测试主要指测试软件版本中的主要功能是否实现,速度很快,一般一到两个小时即可完成。夸张地说,抽一根香烟的时间就可以完成测试。还有一个说法来源于硬件测试,一般硬件组装完毕,上电后,如果电路出现冒烟故障,则不必进行更深入的测试。在软件测试中,如果冒烟测试没有通过,就需要返回给开发工程师重新修改后再测试。

2.回归测试(Regression Testing)

图1-2 修改部分与新功能对原有功能的影响

回归测试又称衰竭性测试。为了确保修改或增加的功能没有给软件其他未改变的(或者以前测试通过的)部分带来影响,软件测试工程师进行每轮测试时,需要对先前测试过的模块再进行测试,这种测试称为回归测试。回归测试最好使用自动化软件测试工具来实现。关于回归测试,如图1-2所示。

3.白盒测试(White Box Testing)

白盒测试是通过分析组件/系统的内部结构进行的软件测试。白盒测试用例分析方法包括语句覆盖、分支覆盖、条件覆盖、条件/分支覆盖和路径覆盖等技术。白盒测试也可以在系统测试中进行(关于白盒测试的方法,本篇2.6节会详细介绍)。

4.黑盒测试(Black Box Testing)

黑盒测试是基于系统功能或非功能规格说明书来设计或者选择测试用例的技术,它不涉及软件内部结构。也就是说,测试工程师不需要了解程序内部是如何实现的,只需考虑输出内容的特性对应输入内容的要求。黑盒测试也可以基于代码来实现,如通过输入函数的参数和返回值来了解被测函数的功能是否得到实现。

案例1-1:函数级别黑盒测试。

函数float calcualteSimilty(String a, String b),返回0.00~1.00小数点精度为两位的浮点数。比较字符串a, b的相似程度,0.00表示一点不相似,1.00表示完全相似。可以用下面的测试用例来实现函数级别的黑盒测试,特别声明,这里不需要了解函数内部是如何实现的,只关心函数输入与输出的对应关系。测试用例如下:

● calcualteSimilty("a", "a"); //1.00

● calcualteSimilty("a", "z"); //0.00

● calcualteSimilty("azza", "zaaz"); //0.00

● calcualteSimilty("", ""); //1.00

● calcualteSimilty(null, null); //1.00

● String s="this is a very long string, include 100 words…"calcualteSimilty(s, s); //1.00

● calcualteSimilty("中国人", "外国人"); //0.67

● calcualteSimilty("@", "@"); //1.00

● calcualteSimilty("", " "); //1.00

● …

图1-3 单元测试

5.单元测试(Unit Testing)

单元测试又称组件测试,是对单个软件组件进行的软件测试【与IEEE610一致】。单元测试一般采用软件测试驱动与桩的技术。

案例1-2:单元测试。

对图1-3的模块B进行单元测试如下。

B模块的代码可能如下:

    int B (int a, int b){
        …
        int x= D (a);
        ….
        int y= E(b);
        ….
        return x+y;
    }

B的驱动函数是指通过页面或者编译器可以调用的函数,通常设置为主函数,即main()函数。

    main (){
        int a=3;
        int b=5;
        int c=B(a, b);
    }

StubD, StubE为B的桩函数。桩函数为模拟被测单元的调用模块,由于测试的是模块B,所以桩函数可以简单地返回一个符合要求类型的变量。

    int  StubD(int x){
        return x+5;
    }
    int  StubE(int x){
        return x+6;
    }

这样,B函数就可改为:

    int B (int a, int b){
        ….
        int x= StubD (a);
        ….
        int y= StunE(b);
        ….
        return x+y;
    }

这里,单元测试主要验证模块B的功能,在验证过程中可以采用等价类、边界值、错误输入等方法来实现。

对于软件测试桩,现在有许多新的技术,如图1-4所示。

图1-4 软件测试桩

这些新技术的介绍不在本书的范畴中,有兴趣的读者可以自己查找相关的文献。

6.集成测试(Integration Testing)

集成测试是一种暴露接口以及集成组件/系统间交互时存在缺陷的软件测试方法。集成方法有自上而下测试法、自下而上测试法、自上而下和自下而上混合(又称三明治)测试法3种。

案例1-3:集成测试。

下面来看一个程序架构,如图1-5所示。

图1-5 集成测试案例

可以采取如下方法对此进行集成测试。

● 自下而上集成:

(1)模块6与模块7集成,模块6与模块8集成;

(2)模块3与模块5集成,模块3与模块6集成;

(3)模块2与模块4集成,模块2与模块5集成;

(4)模块1与模块2集成,模块1与模块3集成。

● 自上而下集成:

(1)模块1与模块2集成,模块1与模块3集成;

(2)模块2与模块4集成,模块2与模块5集成;

(3)模块3与模块5集成,模块3与模块6集成;

(4)模块6与模块7集成,模块6与模块8集成。

● 三明治集成:

(1)模块6与模块7集成,模块6与模块8集成;

(2)模块3与模块5集成,模块3与模块6集成;

(3)模块1与模块2集成,模块1与模块3集成;

(4)模块2与模块4集成,模块2与模块5集成;

(5)模块3与模块5集成,模块3与模块6集成。

7.系统测试(System Testing)

系统测试是软件测试的主要部分,是利用各种方法验证软件是否满足产品显性或者隐形需求的活动。

8.验收测试(Accept Testing)

验收测试一般由用户/客户或者运维人员进行确认是否可以接受一个系统的验证性的软件测试。可根据用户需求、业务流程进行的正式的软件测试,以确保系统符合所有验收准则(与IEEE 610一致)。验收测试可以分为Alpha测试和Beta测试。

(1)Alpha测试

Alpha测试是由潜在用户或者独立的软件测试团队在开发环境下或者模拟实际操作环境下进行的软件测试,通常在开发组织外进行,是对现货软件(off-the-shelf software)进行内部验收测试的一种方式。

(2)Beta测试

Beta测试是潜在现有用户/客户在开发组织外的场所,没有开发工程师参与的情况下进行的软件测试,检验软件是否满足客户及业务需求。这种软件测试经常是为了获得市场反馈对现货软件进行外部验收测试的一种形式。

9.静态测试(Static Testing)

静态测试是对组件/系统进行规格或实现级别的测试,但并不执行这个软件,如代码评审或静态代码分析等。

10.动态测试(Dynamic Testing)

动态测试通过运行软件的组件或系统来测试软件。

更多的软件测试术语,请参见参考文献【33】。

1.1.3 软件工程模型

讨论软件测试学,不得不涉及软件工程模型,因为软件测试学与软件工程学的发展是依依相关、相辅相成的。根据目前比较先进的软件测试理念,软件测试应该贯穿于软件工程的整个过程中。下面介绍几种软件工程模型。

图1-6 瀑布模型

1.瀑布模型

图1-6为瀑布模型。这个模型是最经典的软件工程模型,包括“计划”->“需求分析”->“设计”->“编码”->“测试”->“运行维护”这几个阶段。

但是,这个模型存在比较严重的缺点。

(1)不可反复及不适用于需求变更比较频繁的情况。由于瀑布模型从业务建模到运行维护一脉相承,不可以反复。而现代软件项目中,需求变更是无处不在的:“唯一不变的是需求变更”。若运用这种模型,只要项目需求发生变化,就要把原有的设计打翻,重新进行系统分析,概要设计,详细设计等。

(2)用户很难在项目初期了解项目状态:由于用户在项目初期很难提出明确的需求,而利用瀑布模型只有到编码结束,软件测试工程师才可介入软件测试,客户才可以看到是否是他们需要的产品,在此之前这些产品他们不完全了解,有时需要补充,有时客户也有可能推翻他们原本的需求,提出新的需求,这样往往会给客户方、开发方带来很多麻烦。

2.迭代模型和螺旋模型

图1-7为迭代模型。瀑布模型和迭代模型往往在概念上区别不明显。事实上,这两个模型在思想本质上是一致的。它将客户的需求按照用户的重要等级和模块自身的等级进行安排,从最开始进行分析、设计、编码、测试,然后再进入下一轮迭代。用户只要在每一轮结束后,就可以看到产品的一些雏形,从而可以进行需求变更和提出下一轮建议。该模型初期开发工作比较少,用户又可以及时提出下一轮更详细的需求和变更,所以这样的模型往往利于软件公司产品的研发。这类模型有著名的RUP模型、快速开发模型以及现在比较流行的敏捷开发等,它们都遵循迭代的思想。

图1-7 迭代模型

注:本书中扩展阅读大部分来自于百度百科,请见参考文献【21】。

1.1.4 软件测试模型

1.V模型

图1-8所示为V模型测试。

图1-8 V模型测试

● 单元测试相对于编码进行,这一步往往由开发工程师执行。

● 集成测试相对于详细设计,将模块以由上到下、由下到上或混合方式进行逐步集成。测试软件模块与模块、类与类之间的关联性。

● 系统测试相对于概要设计,软件测试工程师站在整体的立场上对系统进行全面的软件测试工作。

● 验收测试是用户对产品进行的测试,一般分为Alpha测试和Beta测试。验收测试往往由系统维护人员或者用户来完成,需要完全站在用户的立场上进行测试,测试环境也要尽可能与用户的实际环境保持一致,大多数时候,需要到用户现场去进行验收测试工作。

2.W模型

图1-9所示为W模型测试。W模型其实是V模型的变种,它提倡的主要思想是软件前置测试理念(即软件测试需要贯穿软件研发的始终)。所以,W模型又称双V模型或前置模型。在需求、设计和编码阶段对产生的工件进行文档评审,一个目的是提出自己的建议和意见,另外一个目的是尽可能理解产品的需求和实现方式。使用前置软件测试法,Bug在软件前期就可以发现,从而降低软件开发的成本。

图1-9 W模型测试

3.X模型

图1-10为X模型测试。X模型将软件系统分为若干模块,对每个模块进行单元测试、集成测试以及系统测试,然后统一对模块进行集成测试。事实上,这里已经提出了“探索式软件测试”的概念,在本书第3章会详细介绍探索式测试。

图1-10 X模型测试

1.1.5 软件测试方法

软件测试方法见表1-1。

表1-1 软件测试方法

代码评审中有一个部分是对编码规范的检查。另外,代码评审可以通过人工的方式来实现,也可以借助代码评审工具,如在本书第二篇7.1.1节“普通软件测试工具推荐”提及的Checkstyle、Findbugs、PMD、Android Lint等工具。

扩展阅读:阿丽亚娜五型运载火箭的爆炸-代码静态测试的重要性

程序员在编程的时候必须定义程序用到的变量,以及这些变量所需的计算机内存,这些内存用比特位来定义,如int16、int32、double、float等。

一个16位的整数变量可以代表-32.768到32.767中间的值。而一个64位的整数变量可以代表-9.223.372.036.854.775.808到9.223.372.036.854.775.807中间的值。

1996年6月4日上午9时33分59秒,随着5、4、3、2、1、0的倒计时,阿丽亚娜五型运载火箭的首次发射点火后,火箭开始偏离路线,最终被逼引爆自毁,整个过程只有短短的30s。阿丽亚娜五型运载火箭是基于前一代四型火箭开发的。在四型火箭系统中,对一个水平速率的测量值使用了16位的变量及内存,因为在四型火箭系统中反复验证过,这一值不会超过16位的变量,而五型火箭的开发工程师简单复制了这部分程序,而没有对新火箭进行数值的验证,结果发生了致命的数值溢出。发射后这个64位带小数点的变量被转换成16位不带小数点的变量,引发了一系列的错误,从而影响了火箭上所有的计算机和硬件,瘫痪了整个系统,因而不得不选择自毁。

阿丽亚娜五型载火箭使用Ada语言开发,出问题的代码如下:

    L_M_BV_32:=TBD.T_ENTIER_32S  ((1.0/C_M_LSB_BV) * (G_M_INFO_DERRIVE());
    if L_M_BV_32 >32767 then
    P_M_DERIVE(T_ALG.E_BV) :=16#7FFF#;
    elseif L_M_BV_32 <-32767 then
    P_M_DERIVE(T_ALG.E_BV) :=16#8000#;
    else
    P_M_DERIVE(T_ALG.E_BV):=UC_16S_EN_16NS(TDB.T_ENTIER_16S(L_M_BV_32));
    end if;
    P_M_DERIVE(T_ALG.E_BH):=UC_16S_EN_16NS(TDB.T_ENTIER_16S(1.0/C_M_LSB_BH)*G_M_INFO_DRIVER(T_ALG.E_GH)));

在这个代码中导致最终问题的是最后一句。在这一段语句中共有7个变量运算符出现了问题,仅有4个做了异常处理的保护,而其他3个没有进行。但是这也是由于运行的机器SRI计算机中设定最大负荷目标值为80%,如果要进行异常处理,计算机的CPU要处理的代码会增多。

教训:软件设计和Code Review的重要性。另外阿丽亚娜五型运载火箭在倒计时阶段、飞行阶段以及进入轨道阶段都未经过测试验证。

1.1.6 软件测试步骤

图1-11描述了软件测试步骤,具体如下。

图1-11 软件测试步骤

(1)软件测试计划。

(2)软件测试分析。

(3)软件测试设计。

(4)软件测试实施。

(5)软件测试执行。

(6)评估出口准则和报告。

(7)软件测试结束活动。

具体内容读者可以参见参考文献【13】第二章进行更深入的学习。

1.1.7 软件缺陷管理

1.缺陷管理流程

根据SEI TSP国际标准,缺陷管理流程可以定义如下。

研发计算机必须分为开发机、测试机和发布机。开发工作在开发机上进行,软件测试工作(系统测试)在测试机上运行,最后产品验收和运行在发布机上运行,发布机器可能在客户处。

(1)每轮测试开始,开发部门提出本次测试重点,开发机上的版本同步到软件测试机上(或通过配置管理工具实现同步)。

(2)软件测试工程师进行冒烟软件测试,如果冒烟测试没有通过,则退回给开发部门,等待开发部门重新提交软件测试任务,返回第(1)步。

(3)冒烟测试通过,测试工程师继续执行测试活动,包括传统正规测试和基于经验的测试,如探索式软件测试等。发现Bug,记录在缺陷管理工具中。

(4)开发工程师修改被确认的Bug(状态为Assigned)。

(5)当软件测试工程师认为软件测试结束,大部分Bug都发现完毕,开发机上版本再一次同步到软件测试机上。

(6)软件测试工程师对Bug进行复测,如果问题仍旧存在,则标记为Reopen,否则标记为Closed。此时还要对以前测试过的功能进行回归测试。

(7)开发工程师对于Reopen的缺陷进行修改。

(8)当一轮软件测试达到出口标准,软件测试机上的版本同步到发布机上,软件测试任务完成;否则返回第(5)步。

在本书第三篇第13.9节“软件缺陷管理流程”会给出更为详细的描述。

2.缺陷严重等级

由于采用的缺陷管理工具不同,缺陷严重等级的级别也会有差异。

Blocker:(阻碍的)

➢ 阻碍开发和/或软件测试工作,冒烟测试没有通过,不能进行正常的软件测试工作。

Critical:(紧急的)

➢ 系统无法测试,或者系统无法继续操作,应用系统异常中止。

➢ 对操作系统造成严重影响,系统死机,被测程序挂起,不响应等情况。

➢ 造成重大安全隐患情况,如机密性数据的泄密。

➢ 功能没有实现,无法进行某一功能操作,影响系统使用。

Major:(重大的)

➢ 功能基本上能实现,但在特定情况下导致功能失败。

➢ 导致输出的数据错误,如:数据内容出错、格式错误、无法打开。

➢ 导致其他功能模块无法正常执行。

➢ 功能不完整或者功能实现不正确。

➢ 导致数据最终操作结果错误。

Normal:(普通的)

➢ 功能部分失败,对整体功能的实现基本不造成影响。

Minor:(较小的)

➢ 链接错误、系统出错提示或没有捕获系统出错信息、数据的重要操作(增删查改)没有提示、出现频率极低,会对功能实现造成非致命性的影响。

Trivial:(外观的)

➢ 产品外观上的问题或一些不影响使用的小毛病,如菜单或对话框中的文字拼写或字体问题等。

Enhancement(改进的)

➢ 对系统产品的建议或意见。

3.缺陷修改优先级

由于缺陷管理工具的差异,缺陷修改优先级别也会有差异。

P5:严重级别比较高,影响软件测试进行或者系统无法继续操作。

P4:对系统操作有影响,但不需要马上修改。

P3:页面缺陷(不属于定义的缺陷范围)或者建议。

P2:准备在下一轮软件测试前修改完毕。

P1:准备在下一版本中修改。

4.缺陷书写规则

缺陷编号:【一般缺陷管理工具自动生成】

缺陷简要描述:【一句话描述】

发现者:【一般从下拉框中选择】

修改者:【一般从下拉框中选择】

最早发现所在版本号:【一般从下拉框中选择】

最早发现日期:【一般由日期框选择】

最早修改日期:【一般由日期框选择】

缺陷当前所在模块:【一般从下拉框中选择】

缺陷当前状态:【一般系统自动生成】

缺陷发现时系统环境:【文本框输入或者下拉框选择】

缺陷重现步骤:【由缺陷发现者填写】

实际得到结果:【由缺陷发现者填写】

期望得到结果:【由缺陷发现者填写】

修复描述:【由缺陷修复者填写】

相关文件:【由缺陷发现者填写】

延迟/不修改/修复/回退原因说明:【由缺陷负责人填写】

历史信息:【由缺陷管理系统自动生成,包括状态迁移,所经过的人,各阶段描述等信息】

附件:【由缺陷发现者上传文件】

关于缺陷管理工具将在本书第二篇第10章“缺陷管理工具”进行详细描述。

扩展阅读:世界上第一个Bug

1947年9月9日下午3点45分,Grace Murray Hopper在她的记录本上记下了第一个计算机Bug——在Harvard Mark II计算机里找到的一只飞蛾,她把飞蛾贴在日记本上,并写道First actual case of Bug being found”。这个发现奠定了Bug这个词在计算机世界的地位,变成无数程序员的噩梦。从那以后,Bug这个词在计算机世界表示计算机程序中的错误或者疏漏,它们会使程序计算出莫名其妙的结果,甚至引起程序的崩溃。Grace Murray Hopper是历史上最早一批程序员,而且还是个女程序员。

Hopper的记录连同那只飞蛾现在存在美国历史博物馆。

1.1.8 测试用例

1.测试用例格式

测试用例格式见表1-2。

表1-2 测试用例格式

● 编号:“Chinafi_”+***+“_”+XXX。

➢ Chinafi:固定的开始字符。

➢ ***:模块名。

➢ XXX:3位0~9的数字。

● 前置条件:完成此项测试,需要达到的前提条件。如测试登录,前置条件为注册的基本功能必须实现。

● 说明:测试项目的描述。

● 项目编号:一个测试中可包括几个项目,每个项目的编号。

● 测试步骤:完成测试的具体步骤描述。

● 期待结果:对于一些重要步骤的页面期待的显示结果,每一项最后一步的期待结果是必须书写的。

● 概要说明:对于测试过程中的一些说明注解。

2.测试用例案例

案例1-4:测试用例的书写。

环境:浏览器、Web服务器(Tomcat)、MySQL数据库。

需求:一个表单信息,用于网站用户注册个人信息,主要包括姓名、登录名、密码(大于5个字符,必须包含数字和特殊字符)、确认密码、Email信息、手机、地址,其中登录名、密码、确认密码、Email信息是必填的,其他信息可以选填。请根据需求书写测试用例(不考虑长度测试)。用户注册界面如图1-12所示,用户注册测试用例见表1-3。

图1-12 用户注册界面

表1-3 用户注册测试用例

续表

当然,要写好测试用例,首先要学好如何进行测试设计,后续章节中会进行详细介绍。

1.1.9 软件测试类型

关于软件测试类型,可以参照ISO 225000(替代ISO 9126)软件质量模型,如图1-13所示。

图1-13 ISO225000(替代ISO 9126)软件质量模型

1.功能测试

功能测试对测试对象侧重于所有可直接追踪到用例或业务功能和业务规则的软件测试需求。这种软件测试的目标是核实数据的接收、处理和检索是否正确,以及业务规则的实施是否恰当。此类软件测试可以通过黑盒测试技术或白盒测试技术来实现,该技术通过图形用户界面(GUI)或其他方式与应用程序进行交互,并对交互的输出或结果进行分析,以此核实应用程序及其内部功能。

案例1-5:功能测试。

图1-14所示是电子商务计价系统界面。随着电子商务网站越来越多,某些商品在节假日可以打折,会员可以享受会员价,购买物品达到一定数量或金额后,也可以打折或者免运费。这些条件给计价系统的准确性带来很复杂的功能,软件测试工程师应该设计好各种测试用例,来检测系统的功能。

图1-14 电子商务计价系统界面

2.易用性测试(用户体验性测试)

易用性测试指的是在指定条件下使用时,软件产品被理解、学习、使用和吸引用户的能力。

● 这里的用户包括。

(1)操作人员。

(2)最终用户。

(3)受该软件的使用影响或者依赖于该软件的间接用户。

● 易用性质量特性。

➢ 易理解性。

➢ 易学性。

➢ 易操作性。

➢ 吸引性。

● 易用性测试采取技术。

➢ 人工检查 审查或者评审。

➢ 问卷调查 通过问卷调查方式得到用户使用软件的反馈。

➢ 验证和确认 针对软件产品的实现,进行验证和确认。

➢ A/B软件测试法。

案例1-6:易用性测试。

如图1-15所示,对于安卓系统卸载APP软件,必须进入设置界面,找到软件,再单击【卸载】按钮才可以卸载;而苹果系统只要在界面上长按APP软件图标3s,点左上角的叉,即可删除。由此可见,苹果系统的卸载APP的软件易用性明显优于安卓系统。另外,现在我们给易用性测试起了一个更好听的名字,叫“软件用户体验性测试”。

图1-15 安卓系统与苹果系统的卸载APP功能

3.可靠性测试

可靠性测试的目的之一是对软件成熟度在时间上的统计度量指标进行监控,并将其与既定目标比较。可靠性对应3个指标,如图1-16所示。

(1)平均失效间隔时间MTBF(这次失效到下次失效的时间)。

(2)平均修复时间MTTR(本次失效修复的时间)。

(3)平均失效前时间MTTF(修复完毕到下次失效的时间)。

图1-16软件可靠性

通过图1-16所示,可以看出:MTBF=MTTR+MTTF。

另外,可靠性失效指标的一般公式:可靠性失效指标=MTTR/MTBF×100%

案例1-7:电信系统软件的可靠性。

在电信领域,可靠性失效指标要达到著名的5个9,即99.999%,也就是说一年中允许设备故障的时间为:365×(1-99.999%)天=8760×(1-99.999%)小时=525600×(1-99.999%)分钟=5.256分钟。

4.性能测试

性能测试的类型比较多,这里主要考虑以下3种类型。

(1)基本性能测试:正常情况下软件的响应速度。

(2)负载测试(LOAD测试):通过增加负载(一般为并发用户或数据库容量)来评估组件或系统性能的软件测试方法。

测试方法:以一定的负载作为起点,观察系统吞吐率,不断加大负载个数,直到吞吐率达到饱和,这时负载为该产品这个功能的最大负载。

(3)压力测试:评估系统处于一定的负载下(最大负载乘以一定百分比),让系统运行一段时间,观察系统各项指标是否正常。

案例1-8:Web系统的性能测试。

在Web页面对用户登录功能进行负载测试,获取最大负载数,并以最大负载的80%,持续运行48小时进行压力测试,观察系统各项指标是否正常运行。

关于性能测试,本篇第5.1节将会详细讲解。

5.安全性测试

软件安全性包括功能安全性和信息安全性,本节只考虑信息安全性。

信息安全性:指的是软件产品保护信息和数据的能力,及未授权的人员或者系统不能阅读或者修改这些信息和数据,而不拒绝授权人员或者系统对它们进行访问。信息安全性测试的关注点:

● 对应用程序/数据进行未授权的复制;

● 未授权的访问控制;

● 出入域溢出导致的缓存区溢出;

● 服务拒绝,阻止用户与应用程序的交互;

● 在网络上窃听数据传输获取敏感信息;

● 破解保护敏感信息的加密代码;

● 逻辑炸弹/复活节彩蛋。

信息安全性分类:

● 与用户接口相关;

● 与文件系统相关;

● 与操作系统相关;

● 与外部软件相关。

信息安全性测试方法:

● 使用工具创建系统概况或网络图;

● 使用多种工具进行漏洞扫描;

● 获得信息研制“攻击方案”;

● 根据安全专家(白帽子黑客)的建议进行多种攻击。

案例1-9:黑客侵入。

某公司开发一套网上答题系统,题目均为单项选择题,可以选择A、B、C、D中的任意一项,每一周评选最高得分者,可以在电视节目中参加一个益智类的栏目。为了防止网友对所有题选择某个相同的答案(如对所有题都选择D),或者有规律的选择(如选题都是A、C、D、B、A、C、D、B…)在前端JavaScript程序里做了控制:如果连续5次选择同一个答案或者有规律地选择的答题者将被答题系统自动踢出。该程序经过严格测试后上线使用。可是,上线不到4周,发现每周最高得分者均为一个姓张的先生,查看其答案,竟然所有题目都答成B,这让开发工程师感到很奇怪。两周后,公司的开发经理在网站群聊中找到这位张先生,张先生告诉开发经理,系统在前端JavaScript做了控制,但是在后端JavaBean中没进行控制,所以他自己写了个程序绕过前端,这个程序是一个死循环,7×24小时一直发送答案B给后端系统。

案例1-10:XSS注入。

如果没有对HTML特殊字符进行处理(HTML特殊字符见附录A),在浏览页面时会运行JavaScript代码,如果输入的JavaScript代码具有恶意获得用户信息的功能,就会产生安全问题,如输入:“ <script type="text/javascript">var sys = getBrowserInfo(); document.write (sys.browser + "的版本是:" + sys.ver); </script>”,页面在显示时就会把用户当前的浏览器版本和型号都显示出来。这样,黑客就可以根据获取的信息采取进一步攻击。

案例1-11:SQL注入。

SQL注入比XSS注入更加危险。下面的例子可以造成用户不注册就能登录系统:下面是登录系统的SQL语句:select count(*) from user where name='$name' and password='$password'。上面是用户登录的SQL语句,如果count(*)不为零,用户即可进入系统。$name, $password为用户在界面中输入的值,这里作为一个变量存储。$name可以任意输入,如输入“Jerry”, $password输入类似于“2222' or 1=1; -- '”,由于这样SQL语句变为select count(*) from user where name='Jerry' and password='2222' or 1=1; -- ', where语句后的条件永远为真,所以判断语句count(*)一定不为零。

6.相容性测试

相容性测试又称兼容性测试,指的是软件产品与一个或者多个规定的系统之间进行交互的能力。该项测试用于验证软件产品或者应用程序在各种指定的目标环境下是否可以正常工作,主要包括:

(1)硬件;

(2)软件;

(3)中间件;

(4)操作系统;

(5)其他。

兼容性测试包括:输入的兼容性、输出的兼容性以及自适应性。

案例1-12:设备接口兼容性。

图1-17 北向接口和南向接口

某些设备厂商生产出的产品需要被其他厂商调用,或者调用其他厂商的接口。在这些厂商中,北向接口与南向接口经常被提及。北向接口和南向接口如图1-17所示。

● 北向接口:我的设备使用其他设备的功能,这个接口为北向接口。

● 南向接口:其他设备使用我的设备的功能,这个接口为南向接口。

可以看出,如果用单元测试做一个比喻,北向接口设备相当于驱动函数,而南向接口设备相当于桩函数。

案例1-13:屏幕分辨率测试。

屏幕分辨率测试属于兼容性测试的范畴,要求测试在不同屏幕分辨率下。界面的美观程度,可分为800×600、1024×768、1152×864、1280×768、1280×1024、1200×1600等,不同字号下的测试。

7.可移植性测试

可移植性测试通常和软件移植到某个特定的运行环境中的难易程度相关,包括第一次建立或从现有环境移植到另一个环境。这种测试类型包括:

(1)可安装性测试;

(2)适应性测试;

(3)可替换性测试。

案例1-14:网络设备移植测试。

某软件从网络设备A移植到网络设备B中,发生了错误。后经过排查,结论是网络设备A的IP地址用的是用户地址序列(高位在前,低位在后)。而网络设备B的IP地址用的是网络地址序列(低位在前,高位在后)。如IP地址是192.168.0.8,转化为十六进制为C0.A8.00.08,在设备A上是用户地址序列为C0A80008。在设备B上是网络地址序列为0800A8C0。

故障转移和恢复测试属于可移植性测试范畴,它可确保软件测试对象能成功完成故障转移,并能从意外数据损失或数据完整性破坏的各种硬件、软件或网络故障中恢复。

故障转移测试可确保对于必须持续运行的系统,一旦发生故障,备用系统就将不失时机地“顶替”发生故障的系统,以避免丢失任何数据或事务。

恢复测试是一种对抗型测试过程。在这种软件测试中,将把应用程序或系统置于极端(或者是模拟的极端)的条件下,使其产生故障(如设备输入/输出(I/O)故障或无效的数据库指针和关键字)。然后调用恢复进程,并监测和检查应用程序和系统,核实应用程序或系统以及数据已得到正确恢复。

安装、卸载测试也属于移植性测试,安装测试有两个检查点。

(1)确保该软件在正常情况和异常情况的不同条件下(如进行首次安装、升级、完整的或自定义的安装)都能进行安装。异常情况包括磁盘空间不足、缺少目录创建权限等。

(2)核实软件在安装后可立即正常运行。

卸载测试有4个检查点:

(1)卸载是否正常、卸载后的软件是否能够运行;

(2)核实卸载软件的数据与文件都删除干净;

(3)卸载后的软件重新安装是没有问题的;

(4)卸载后的软件不影响其他软件的工作。

8.可维护性测试

可维护性测试指的是软件产品可被修改的能力,包括纠正、改进或者软件对环境、需求和功能规格说明变化的适应能力。

案例1-15:代码可维护性测试。

某公司生产了ERP产品给A企业,3年后由于公司ERP流程发生变化,需要在原来基础上进行更新,但是由于3年来近一半的开发工程师发生了变动,代码注释又不规范,给新功能开发带来很大困难,这就产生了代码可维护性的问题。为了解决这个问题,软件工程师把代码进行了如下优化,如图1-18所示。

图1-18 代码的可维护性

要做好代码的可维护性,最好是在编码后期做好严格的代码审核(Code Review)工作。

案例1-16:产品的可测试性。

某B/S产品决定采用WebDriver进行测试,由于HTML代码中的元素都没有id、name或者class属性,如:

    <input type="button" value="点击">

如果采用手工测试,是没有关系的,但是采用自动化测试,就带来很大困难,于是把HTML代码改为:

    <input type="button" value="点击" name="click" id="my_click">

关于WebDriver的介绍参看本书第二篇第11.2节“Selenium和WebDriver工具入门”介绍。

在软件测试工作中除了关注ISO 22500标准外,我们还经常用到以下测试方法。

9.数据和数据库完整性测试

在项目名称中,数据库和数据库进程应该作为一个子系统来进行软件测试。测试这些子系统时,不应将测试对象的用户界面用作数据的接口。对于数据库管理系统(DBMS),需要进行深入研究,以确定可以支持以下测试的工具和技术。数据库测试包括以下几个方面。

● 数据库设计测试。

● SQL代码规范测试:可使用工具为SQL BPA。

● SQL语句效率测试。

● SQL语句兼容性测试:SQL语句标准FIPS 127-2,基于SQL-92标准。

扩展阅读:FIPS标准和SQL-92标准

1.FIPS标准

FIPS(Federal Information Processing Standards)即(美国)联邦信息处理标准。它是批准技术与标准国家协会(National Institute of Standards and Technology),为联邦计算机系统制定标准和指南。

2.SQL-92标准

SQL-92,是数据库的一个ANSI/ISO标准。

SQL92标准有4个层次

● 入门级

这是大多数开发商符合的级别。这一级只是对前一个标准SQL89稍做修改。所有数据库开发商都不会有更高的级别,实际上,美国国家标准和技术协会NIST(National Institute of Standards and Technology,这是一家专门检验SQL合规性的机构)除了验证入门级外,甚至不做其他的验证。Oracle 7.0于1993年通过了NIST的SQL92入门级合规性验证,那时我也是小组中的一个成员。如果一个数据库符合入门级,它的特性集则是Oracle 7.0的一个功能子集。

● 过渡级

这一级在特性集方面大致介于入门级和中间级之间。

● 中间级

这一级增加了许多特性,包括(以下所列并不完整):

➢ 动态SQL;

➢ 级联DELETE以保证引用完整性;

➢ DATE和TIME数据类型;

➢ 域;

➢ 变长字符串;

➢ CASE表达式;

➢ 数据类型之间的CAST函数。

● 完备级

增加了以下特性(同样,这个列表也不完整):

➢ 连接管理;

➢ BIT串数据类型;

➢ 可延迟的完整性约束;

➢ FROM子句中的导出表;

➢ CHECK子句中的子查询;

➢ 临时表。

入门级标准不包括诸如外联结(outer join)和新的内联结(inner join)语法等特性。过渡级则指定了外联结语法和内联结语法。中间级增加了更多的特性,当然,完备级就是SQL-92全部。有关SQL-92的大部分书都没有区别这些级别,这就会带来混淆。这些书只是说明了一个完整实现SQL-92的理论数据库会是什么样子。所以无论你拿起哪一本书,都无法将书中所学直接应用到任何SQL-92数据库上。关键是,SQL-92最多只达到入门级,如果你使用了中间级或更高级里的特性,就存在无法“移植”应用的风险。

10.本地化测试

本地化测试是指为各个地方开发产品的软件测试,如英文版、中文版等,包括程序是否能够正常运行,界面是否符合当地习俗,快捷键是否正常起作用等,特别要测试在A语言操作系统环境下运行B语言软件(如在英文版的Windows操作系统下试图运行中文版的程序),运行是否正常。

11.文字测试

文字测试主要测试文字是否拼写正确、是否易懂、不存在二义性、没有语法错误;文字与内容(包括图片、文字)是否有出入等。

12.发布测试

主要在产品发布前对一些附带产品,如说明书、广告稿等进行软件测试。发布测试在验收测试中进行。

说明书测试

说明书测试主要为语言检查、功能检查、图片检查。

● 语言检查:检查说明书语言是否正确,用词是否易于理解。

● 功能检查:功能是否描述完全,或者描述了并没有的功能等。

● 图片检查:检查图片是否正确。

宣传材料测试

主要测试软件产品中附带的宣传材料中的语言、描述功能、图片。

产品说明书的测试

产品说明书是用户(特别是一些新用户)了解产品的一个有力工具。所以,软件测试工程师应该对产品说明书中的每一条功能进行严格核实。除此之外,还应从用户的角度思考,考虑是否将注意事项告诉了用户,产品说明书是否便于阅读,产品说明书的书写逻辑是否合理以及说明书中章节的前后顺序是否需要进行调整。

产品广告

产品广告往往是由市场人员为了推销产品而书写的,对于广告中提及的功能,我们要与市场和销售人员进行及时沟通,弄清楚每条语句是在哪个模块的哪个功能点上实现的,然后在产品上具体操作一下,看是否是那么一回事。广告具有一定的夸大性,这在所难免。但是,对于夸大过份的内容,软件测试工程师有提出修改建议的责任。

1.1.10 软件测试曲线

众所周知软件的Bug不可能为零,但一般随着时间的推移,Bug数逼近于零。软件测试曲线如图1-19所示。

图1-19 软件测试曲线

这里,横坐标是时间,纵坐标是还没有发现的Bug数。项目开始前,Bug为无穷大,随着时间的推移,Bug趋于零,但是不会等于零。

另外一条曲线的横坐标是时间,纵坐标是已经发现的Bug数。项目开始前,Bug为零,随着时间的推移,Bug趋于一个固定值,但是不会等于这个值。

一般来说,两条曲线的交汇处为产品发布的最好时候,避免过度软件测试,也避免软件测试不够。

1.1.11 软件的杀虫剂现象

由于每个软件测试工程师的思路不同,测试的侧重点也可能不同,所以,不同的测试工程师即使执行相同的测试用例,发现的Bug也可能不同。例如,A测试某个模块,第一天到第四天测到许多Bug,但是从第五天开始几乎报不出Bug了。第七天换了B, B又测试出许多Bug,但不能简单地说A的水平差,B的水平高。其实,这是由于A对这个模块产生了抗药性造成的,这就是软件测试学中的杀虫剂现象,可用图1-20表示。

图1-20 软件测试的杀虫剂现象

为避免杀虫剂现象,建议每次进行轮流测试,最好安排不同的工程师进行不同模块的测试工作。

案例1-17:根据软件杀虫剂现象进行测试计划调整。

某软件项目有测试员甲、乙、丙、丁4人,项目模块为A、B、C、D、E、F、G七个模块,测试周期为3周,为了避免软件杀虫剂现象,测试经理做了分工,见表1-4。这样保证了每一个模块至少有两个人经过测试。

表1-4 工作任务的分工