Presentation is loading. Please wait.

Presentation is loading. Please wait.

梁文新 办公室:综合楼108 电 话: 87571625 wxliang@dlut.edu.cn 软件工程导论 梁文新 办公室:综合楼108 电 话: 87571625 wxliang@dlut.edu.cn.

Similar presentations


Presentation on theme: "梁文新 办公室:综合楼108 电 话: 87571625 wxliang@dlut.edu.cn 软件工程导论 梁文新 办公室:综合楼108 电 话: 87571625 wxliang@dlut.edu.cn."— Presentation transcript:

1 梁文新 办公室:综合楼108 电 话: 87571625 wxliang@dlut.edu.cn
软件工程导论 梁文新 办公室:综合楼108 电 话:

2 软件的生命周期 软件 定义 What? 需求分析 总体设计 How? 软件 开发 详细设计 Implementation 编码 测试 运行
问题定义 软件 定义 可行性分析 What? 需求分析 总体设计 How? 软件 开发 详细设计 Implementation 编码 测试 运行 维护 运行维护 2019/4/21

3 第七章 实现 (Implementation)
7.1 编码 7.2 软件测试基础 7.3 单元测试 7.4 集成测试 7.5 确认测试 7.6 白盒测试技术 7.7 黑盒测试技术 7.8 调试 7.9 软件可靠性 7.10 小结 2019/4/21

4 概述 Implementation = Coding + Testing
编码:把软件设计翻译成计算机可以理解的形式,即以某种程序设计语言书写的程序 编码是对设计的进一步具体化,程序的质量主要取决于软件设计的质量 所选用的程序设计语言的特点和编码风格也会对程序的可靠性、可读性、可测试性和可维护性产生深远的影响 2019/4/21

5 概述 软件测试对软件可靠性有着重要影响 人的主观认识不可能完全符合客观现实 与工程密切相关的各类人员之间的通信和配合也不可能完美无缺
在软件生命周期的每个阶段都不可避免地会产生差错 2019/4/21

6 软件缺陷 定义 特点 (1)软件未达到产品说明书中已经标明的功能; (2)软件出现了产品说明书中指明不会出现的错误;
(3)软件未达到产品说明书中虽未指出但应当达到的目标; (4)软件功能超出了产品说明书中指明的范围; (5)软件测试人员认为软件难以理解、不易使用,或者最终用户认为 该软件使用效果不良。 特点 “看不到” ——软件的特殊性决定了缺陷不易看到 “看到但是抓不到”: ——发现了缺陷,但不易找到问题发生的原因所在 2019/4/21

7 软件缺陷产生原因的分布 其他 10% 编写代码 7% 软件产品说明书(需求) 56% 设计27% 2019/4/21

8 概述 尽可能早地发现并纠正差错 在软件投入生产性运行之前,尽可能多地发现软件中的错误 经验表明阶段审查并不能发现所有差错
此外,在编码过程中还不可避免地会引入新的错误 在软件投入生产性运行之前,尽可能多地发现软件中的错误 软件测试是保证软件质量的关键步骤,它是对软件规格说明、设计和编码的最后复审 2019/4/21

9 概述 软件测试在软件生命周期中横跨编码和测试两个阶段 单元测试(编码阶段) 综合测试(测试阶段)
在编写出每个模块之后就对它做必要的测试 模块的编写者和测试者是同一个人 综合测试(测试阶段) 集成测试、系统测试、确认/验收测试 通常由专门的测试人员承担软件系统的测试工作 软件测试的工作量往往占软件开发总工作量的40%以上 在极端情况,测试那种关系人的生命安全的软件所花费的成本,可能相当于软件工程其他步骤总成本的3~5倍 2019/4/21

10 概述 测试的目标是发现软件中的错误,但并不能证明程序的正确性
软件工程的根本目标是开发出高质量的完全符合用户需要的软件,因此,通过测试发现错误之后还必须诊断并改正错误,这就是调试的目的。调试是测试阶段最困难的工作 在对测试结果进行收集和评价的时候,软件所达到的可靠性也开始明朗了。软件可靠性模型使用故障率数据,估计软件将来出现故障的情况并预测软件的可靠性 2019/4/21

11 7.1 编码 编码阶段的关键任务是写出正确的容易理解、容易维护的程序模块
7.1 编码 编码阶段的关键任务是写出正确的容易理解、容易维护的程序模块 程序员应该根据目标系统的性质和实际环境,选取一种适当的高级程序设计语言(必要时用汇编语言),把详细设计的结果翻译成用选定的语言书写的程序,并且仔细测试编写出的每一个模块 2019/4/21

12 程序设计语言 程序设计语言是指用于书写计算机程序的语言,是一种实现性的软件语言 包括以下三个方面 语法(Syntax)
语义(Semantics) 语用(Pragmatics) 2019/4/21

13 语法 (Syntax) 语法是用来表示构成语言的各个记号间的组织规则,是构成语言结构正确成分所需遵循的规则集合
语法中不涉及这些记号的含义和使用者 如C语言里for语句的构成规则是: for(表达式1;表达式2;表达式3)语句 2019/4/21

14 语义 (Semantics) 语义用来表示按照各种表示方式的各个记号的特殊含义,但不涉及使用者
如前述的“for(表达式1;表达式2;表达式3)语句”的语义为 计算表达式1 计算表达式2,若结果为0,则终止循环;否则,转3 执行循环体 计算表达式3 转向2 2019/4/21

15 语用 (Pragmatics) 语用用来表示构成语言的各个记号和使用者的关系,例如: 语言是否允许递归? 是否要规定递归层数的上限?
这种上限如何确定? 2019/4/21

16 程序设计语言的基本成分 数据成分:该语言能接受和处理的数据 运算成分:该语言允许执行的运算 控制成分:该语言允许的控制结构
各种类型的变量、数组、指针、记录等 运算成分:该语言允许执行的运算 如:算数运算符、逻辑运算符、指针运算符等 控制成分:该语言允许的控制结构 顺序结构、条件选择结构、循环结构 传输成分:指明该语言允许的数据传输方式 如Turbo C中的printf()和scanf() 2019/4/21

17 程序语言的特性 心理特性 工程特性 应用特性 程序员总希望选择简单易学、使用方便的语言 一致性、二义性、紧凑性、局部性、线形和传统性
将设计翻译成代码的便利程度、编译器的效率、源代码的可移植性、配套的开发工具、可复用性和可维护性等 应用特性 不同的程序设计语言满足不同的技术特征,可以用于不同的应用场合 如:SQL语言用于关系数据库; Matlab用于科学计算等 2019/4/21

18 7.1 编码 7.1.1 选择程序设计语言 选择一种适当的程序设计语言显得尤为重要 程序设计语言是人和计算机通信的最基本的工具
7.1 编码 7.1.1 选择程序设计语言 程序设计语言是人和计算机通信的最基本的工具 影响人的思维和解题方式 影响人和计算机通信的方式和质量 影响其他人阅读和理解程序的难易程度 选择一种适当的程序设计语言显得尤为重要 2019/4/21

19 7.1.1 选择程序设计语言 低级语言(Machine Language & Assembly Language, 1GL & 2GL)
低级语言表示成二进制形式的机器基本指令集,或者是操作码经过符号化的基本指令集,由于其依赖于特定的机器,其使用复杂、繁琐、费时、易出差错,因而程序编写也有一定的难度 高级语言 (High Level Language, 3GL) 高级语言的表示方法要比低级语言更接近于待解的问题,其特点是在一定程度上与具体机器无关,易学、易用、易维护。高级语言的实现极大的提高了软件的生产效率 2019/4/21

20 高级语言 1. 按应用范围分: 通用语言:PASCAL、C等 2. 按用户的要求分为: 过程式语言和非过程式语言 3. 按使用方式分:
面向对象语言:Smalltalk, C++、Java等 专用语言(Application-Specific):如APL, Matlab等 2. 按用户的要求分为: 过程式语言和非过程式语言 3. 按使用方式分: 交互式语言和非交互式语言 4. 按语言的内在特点分: 系统实现语言 静态高级语言 块结构高级语言 2019/4/21

21 7.1.1 选择程序设计语言 汇编语言应仅在以下特殊应用领域中使用 其他程序应该一律用高级语言书写
对程度执行时间和使用的空间都有很严格限制的情况 需要产生任意的甚至非法的指令序列 体系结构特殊的微处理机,以致在这类机器上通常不能实现高级语言编译程序 或者大型系统中执行时间非常关键的(或直接依赖于硬件的)一小部分代码 其他程序应该一律用高级语言书写 2019/4/21

22 7.1.1 选择程序设计语言 为了使程序容易测试和维护以减少生命周期的总成本 为了便于调试和提高软件可靠性 为了降低软件开发和维护的成本
选用的高级语言应该有理想的模块化机制,以及可读性好的控制结构和数据结构 为了便于调试和提高软件可靠性 语言特点应该使编译程序能够尽可能多地发现程序中的错误 为了降低软件开发和维护的成本 选用的语言应该有良好的独立编译机制 2019/4/21

23 选择程序设计语言应考虑的因素 1)软件的应用领域 2)算法和数据结构的复杂性 3)系统用户的要求 4)软件运行环境 5)软件开发的方法
6)可得到的软件工具 7)工程规模 8)软件的可移植性要求 9)程序员的知识水平 2019/4/21

24 7.1.2 编码风格 程序实际上也是一种供人阅读的文章,有一个文章的风格问题 编程风格包括以下五个方面 应该使程序具有良好的风格
力图从编码原则的角度提高程序的可读性,改善程序质量 编程风格包括以下五个方面 源程序文档化 数据说明 语句结构 输入输出 效率 2019/4/21

25 源程序文档化(Documentation)
标识符的命名 程序的注释 程序的视觉组织 2019/4/21

26 标识符的命名(Identifier Naming)
符号名即标识符,包括模块名、变量名、常量名、标号名、子程序名、 数据区名以及缓冲区名等 这些名字应能反映它所代表的实际东西,应有一定实际意义 例如,表示次数的量用Times,表示总量的用Total,表示平均值的用Average,表示和的量用Sum等 名字不是越长越好,应当选择精炼的意义明确的名字 必要时可使用缩写名字,但这时要注意缩写规则要一致,并且要给每一个名字加注释 不要用关键字做标识符 避免一词多义 不用相似的,容易混淆的名字,如edu, edv, epu等 名字中避免使用混淆的字符,如数字0和字母O,数字1和字母I或l 2019/4/21

27 程序的注释(Program Comments)
程序中的注释是程序员与日后的程序读者之间通信的重要手段 注释用来帮助人们理解程序,决不是可有可无的 一些正规的程序文本中,注释行的数量占到整个源程序的1/3到1/2,甚至更多 注释分为序言性注释和功能性注释 2019/4/21

28 序言性注释(Header Comments)
通常置于每个程序模块的开头部分(Header Section),它应当给出程序的整体说明,对于理解程序本身具有引导作用。有些软件开发部门对序言性注释做了明确而严格的规定,要求程序编制者逐项列出 主要包括: 程序标题 有关本模块功能和目的的说明 主要算法 接口说明:包括调用形式,参数描述,子程序清单 有关数据描述:重要的变量及其用途,约束或限制条件,以及其它有关信息 模块位置:在哪一个源文件中,或隶属于哪一个软件包 开发简历:模块设计者,复审者,复审日期,修改日期及有关说明等 2019/4/21

29 功能性注释(Functional Comments)
功能性注释嵌在源程序体中,用以描述其后的语句或程序段是在做什么工作,或是执行了下面的语句会怎么样。而不要解释下面怎么做 例如以下为一段不好的注释 /* ADD AMOUNT TO TOTAL */ TOTAL = AMOUNT+TOTAL 如果注明把月销售额计入年度总额,便使读者理解了下面语句的意图: /* ADD MONTHLY-SALES TO ANNUAL-TOTAL */ TOTAL = AMOUNT+TOTAL 要点 描述一段程序,而不是每一个语句 用缩进和空行,使程序与注释容易区别 注释要正确 应提供从程序本身难以得到的信息 2019/4/21

30 视觉组织 通过缩进技巧可清晰观察到程序的嵌套层次,同时还容易发现如“遗漏end”那样的错误 自然的程序段之间可以用空行隔开
可以通过添加空格使语句成分更清晰 可以通过添加括号突出运算的优先级 用适当的方式放置括号 2019/4/21

31 数据说明(Data Description)
在设计阶段已经确定了数据结构的组织及其复杂性。在编写程序时,则需要注意数据说明的风格 为了使程序中数据说明更易于理解和维护,必须注意以下几点 1.数据说明的次序应当规范化 2.说明语句中变量安排有序化 3.使用注释说明复杂数据结构 2019/4/21

32 数据说明次序规范化 数据说明次序规范化,使数据属性容易查找,也有利于测试,排错和维护。
原则上,数据说明的次序与语法无关,其次序是任意的。但出于阅读、理解和维护的需要,最好使其规范化,使说明的先后次序固定 2019/4/21

33 示例 在FORTRAN程序中数据说明次序 ① 常量说明 ② 简单变量类型说明 ③ 数组说明 ④ 公用数据块说明 ⑤ 所有的文件说明
在类型说明中还可进一步要求。例如, 可按如下顺序排列: ① 整型量说明 ② 实型量说明 ③ 字符量说明 ④ 逻辑量说明 2019/4/21

34 说明语句中变量安排有序化 当多个变量名在一个说明语句中说明时,应当对这些变量按字母的顺序排列。带标号的全程数据(如FORTRAN的公用块)也应当按字母的顺序排列 例如,把 integer size, length, width, cost, price 写成 integer cost, length, price , size, width 2019/4/21

35 使用注释说明复杂数据 如果设计了一个复杂的数据结构,应当使用注释来说明在程序实现时这个数据结构的固有特点
例如,对于用户自定义的数据类型,应当在注释中做必要的补充说明 2019/4/21

36 语句结构(Program Structure)
在设计阶段确定了软件的逻辑流结构,但构造单个语句则是编码阶段的任务 语句构造应力求简单,直接,不能为了片面追求效率而使语句复杂化 常用规则 一行内只写一条语句 首先考虑清晰性 直截了当说明程序员意图 其他规则 2019/4/21

37 一行内只写一条语句 在一行内只写一条语句,并且采取适当的移行格式,使程序的逻辑和功能变得更加明确
许多程序设计语言允许在一行内写多个语句,但这种方式会使程序可读性变差,因而不可取 2019/4/21

38 示例 例如,有一段排序程序 FOR I:=1 TO N-1 DO BEGIN T:=I;FOR J:=I+1 TO N DO IF A[J]<A[T] THEN T:=J;IF T≠I THEN BEGIN WORK:=A[T];A[T]:=A[I];A[I]:=WORK;END; END; 由于一行中包括了多个语句,掩盖了程序的循环结构和条件结构,使其可读性变得很差 FOR I:=1 TO N-1 DO BEGIN T:=I; FOR J:=I+1 TO N DO IF A[J]<A[T] THEN T:=J; IF T≠I THEN BEGIN WORK:=A[T]; A[T]:=A[I]; A[I]:=WORK; END; END; 2019/4/21

39 首先考虑清晰性 程序编写首先应当考虑清晰性,不要刻意追求技巧性,使程序编写得过于紧凑 例如,有一个用 C 语句写出的程序段:
a[i] = a[i]+a[t]; a[t] = a[i]-a[t]; a[i] = a[i]-a[t]; 此段程序可能不易看懂,有时还需用实际数据试验一下 实际上,这段程序的功能就是交换A[I]和A[T]中的内容。目的是为了节省一个工作单元。如果改一下: work = a[t]; a[t] = a[i]; a[i] = work; 就能让读者一目了然了 2019/4/21

40 直截了当说明程序员意图 程序编写得要简单,写清楚,直截了当地说明程序员的用意。例如, for ( i = 1; i <= n; i++ ) for ( j = 1; j <= n; j++ ) V[i][j] = ( i/j ) * ( j/i ) 除法运算(/)在除数和被除数都是整型量时,其结果只取整数部分,而得到整型量当 i<j 时, i / j = 0;当 j<i 时, j / i = 0 得到的数组 当i≠j时 V[i][j] = ( i/j ) * ( j/i ) = 0 当i=j时 V[i][j] = ( i/j ) * ( j/i ) = 1 这样得到的结果 V 是一个单位矩阵 2019/4/21

41 一目了然的书写方式 for ( i=1; i <= n; i++ ) for ( j=1; j <= n; j++ ) if ( i == j ) V[i][j] = 1.0; ELSE V[i][j] = 0.0; 2019/4/21

42 其他规则(1) 除非对效率有特殊的要求, 程序编写要做到清晰第一,效率第二。不要为了追求效率而丧失了清晰性。事实上,程序效率的提高主要应通过选择高效的算法来实现 首先要保证程序正确, 然后才要求提高速度。反过来说,在使程序高速运行时,首先要保证它是正确的 避免使用临时变量而使可读性下降。例如,有的程序员为了追求效率,往往喜欢把表达式A[I]+1/A[I]; 写成 AI=A[I]; X=AI+1/AI; 这样将一句分成两句写,会产生意想不到的问题 2019/4/21

43 其他规则 (2) 尽可能使用库函数 避免不必要的转移, 同时如果能保持程序可读性,则不必用 GO TO语句
尽量只采用三种基本的控制结构来编写程序 避免使用空的ELSE语句和IF… THEN IF…的语句。这种结构容易使读者产生误解避免采用过于复杂的条件测试 尽量减少使用“否定”条件的条件语句尽可能用通俗易懂的伪码来描述程序的流程,然后再翻译成必须使用的语言 数据结构要有利于程序的简化 要模块化,使模块功能尽可能单一化,模块间的耦合能够清晰可见 利用信息隐蔽,确保每一个模块的独立性 2019/4/21

44 输入和输出(Input & Output) 输入和输出信息是与用户的使用直接相关的。输入和输出的方式和格式应当尽可能方便用户的使用。一定要避免因设计不当给用户带来的麻烦 因此,在软件需求分析阶段和设计阶段,就应基本确定输入和输出的风格。系统能否被用户接受,有时就取决于输入和输出的风格 2019/4/21

45 输入输出方式应考虑的原则(1) 对所有的输入数据都要进行检验,识别错误的输入,以保证每个数据的有效性
检查输入项的各种重要组合的合理性,必要时报告输入状态信息 使得输入的步骤和操作尽可能简单,并保持简单的输入格式输入数据时,应允许使用自由格式输入 应允许缺省值 输入一批数据时,最好使用输入结束标志,而不要由用户指定输入数据数目 2019/4/21

46 输入输出方式应考虑的原则(2) 在交互式输入输入时,要在屏幕上使用提示符明确提示交互输入的请求,指明可使用选择项的种类和取值范围。同时,在数据输入的过程中和输入结束时,也要在屏幕上给出状态信息当程序设计语言对输入/输出格式有严格要求时,应保持输入格式与输入语句的要求的一致性 给所有的输出加注解,并设计输出报表格式 输入/输出风格还受到许多其它因素的影响。如输入/输出设备(例如终端的类型,图形设备,数字化转换设备等)、用户的熟练程度、以及通信环境等 2019/4/21

47 效率(Efficiency) 效率主要指处理机时间和存储器容量两个方面。虽然值得提出提高效率的要求,但是在进一步讨论这个问题之前应该记住三条原则: 首先,效率是性能要求,因此应该在需求分析阶段确定效率方面的要求。软件应该像对它要求的那样有效,而不应该如同人类可能做到的那样有效 其次,效率是靠好设计来提高的 第三,程序的效率和程序的简单程度是一致的。不要牺牲程序的清晰性和可读性来不必要地提高效率 2019/4/21

48 效率(Efficiency) 从三个方面考虑程序效率: 程序运行时间 存储器效率 输入输出的效率 直接由详细设计阶段确定的算法的效率决定
程序的风格也能产生影响 存储器效率 输入输出的效率 缓冲、二级存储器的使用 2019/4/21

49 7.2 软件测试基础 软件测试的定义: 软件测试就是在软件投入运行前,对软件需求分析、设计规格说明和编码实现的最终审查,它是软件质量保证的关键步骤。通常对软件测试的定义有两种描述: 定义1:软件测试是为了发现错误而执行程序的过程 定义2:软件测试是根据软件开发各阶段的规格说明和程序的内部结构而精心设计的一批测试用例(Test Cases),并利用这些测试用例运行程序以及发现错误的过程,即执行测试步骤 2019/4/21

50 软件测试的定义 WHO? WHAT? WHEN? HOW?
测试:所谓测试的含义,首先是一项活动,在这项活动中某个系统或组成的部分将在特定的条件下运行,结果将被观察和记录,并对系统或组成部分进行评价。测试活动有两种结果:找出缺陷和故障,或显示软件执行正确。测试是一个或多个测试用例的集合 测试用例:所谓测试用例是为特定的目的而设计的一组测试输入、执行条件和预期的结果;测试用例是执行测试的最小实体 测试步骤:测试步骤详细规定了如何设置、执行、评估特定的测试用例 WHO? WHAT? WHEN? HOW? 2019/4/21

51 7.2.1 软件测试的目标 基于两种不同立场的测试目标:
从用户的角度出发,普遍希望通过软件测试暴露软件中隐藏的错误和缺陷,以考虑是否可接受该产品 从软件开发者的角度出发,则希望测试成为表明软件产品中不存在错误的过程,验证该软件已正确地实现了用户的要求,确立人们对软件质量的信心 2019/4/21

52 7.2.1 软件测试的目标 G. J. Myers给出了关于测试的一些规则,这些规则也可以看作是测试的目标:
G. J. Myers, The Art of Software Testing, John Wiley and Sons, 1979 测试是为了发现程序中的错误而执行程序的过程 好的测试方案是极可能发现迄今为止尚未发现的错误的测试方案 成功的测试是发现了至今为止尚未发现的错误的测试 2019/4/21

53 7.2.1 软件测试的目标 由于测试的目标是暴露程序中的错误,从心理学角度看,由程序的编写者自己进行测试是不恰当的
因此,在综合测试阶段通常由其他人员组成测试小组来完成测试工作 测试决不能证明程序是正确的。即使经过了最严格的测试之后,仍然可能还有没发现的错误潜藏在程序中 测试只能查找出程序的错误,不能证明程序中没有错误 2019/4/21

54 7.2.2 软件测试准则 所有测试都应该能追溯到用户需求 应该远在测试开始之前就制定测试出计划
把Pareto原理(80-20法则)应用到软件测试中 应该从“小规模”测试开始,并逐步进行“大规模”测试:单元测试集成测试系统测试 不可能完成穷举测试 为了达到最佳的测试效果,应该由独立的第三方从事测试工作 2019/4/21

55 不可能完成穷举测试 对一个具有多重选择和循环嵌套的程序,不同的路径数目可能是天文数字。给出一个小程序的流程图,它包括了一个执行20次的循环
包含的不同执行路径数达520条,对每一条路径进行测试需要1毫秒,假定一年工作365×24小时,要想把所有路径测试完,需3170年! 2019/4/21

56 其他应遵循的测试准则 测试用例应当由测试数据和与之对应的预期结果这两部分组成 测试用例应包括合理的输入条件和不合理的输入条件
严格执行测试计划,排除测试的随意性 充分注意测试当中的群集现象 应对每一个测试结果做全面的检查 保存相关文档(测试计划、测试用例、出错统计和最终分析报告)为维护工作提供充分的资料 2019/4/21

57 7.2.3 测试方法 按照软件测试用例的设计方法来划分: 按照软件测试的策略和过程来分类,软件测试可分为
测试方法 按照软件测试用例的设计方法来划分: 白盒/结构测试(White-box/Structural Testing) 黑盒/功能测试(Black-box/Functional Testing) 按照软件测试的策略和过程来分类,软件测试可分为 单元/模块/部件测试(Unit/Module/Component Testing) 集成/接口/组装测试(Integration/Interface/Assembly Testing) 系统测试(System Testing) 确认/验收测试(Validation/Acceptance Testing) 2019/4/21

58 测试与各开发阶段的关系 需求 分析 说明书 详细 设计 源程序 代码 单元 测试 集成 确认 概要 2019/4/21

59 V字模型 2019/4/21

60 7.2.4 测试步骤 大型软件系统的测试过程基本上由下述几个步骤组成 1. 模块测试(单元、部件测试)
1. 模块测试(单元、部件测试) 每个模块作为一个单独的实体来测试,目的是保证每个模块作为一个单元能正确运行 单元测试大量使用白盒测试技术,检查模块控制结构中的特定路径,以确保做到完全覆盖并发现最大数量的错误 发现的往往是编码和详细设计的错误 2. 子系统测试(集成/组装/接口测试) 把经过单元测试的模块放在一起形成一个子系统来测试 着重测试模块间的协调和通信,即模块的接口 2019/4/21

61 7.2.4 测试步骤 3.系统测试 把经过测试的子系统装配(即集成)在一起形成完整的系统来测试
往往发现软件设计中的错误,也可能发现需求说明中的错误 不论是子系统测试还是系统测试,都兼有检测和组装两重含义,因此称为集成测试 集成测试同时解决程序验证和程序构造这两个问题 在集成过程中最常用的是黑盒测试用例设计技术,当然,为了保证覆盖主要的控制路径,也可能使用一定数量的白盒测试 2019/4/21

62 7.2.4 测试步骤 4.验收测试 (确认测试) 把系统作为单一的实体进行测试,测试内容与系统测试基本类似,但是是在用户积极参与下进行的,而且可能主要使用实际数据 发现的往往是系统需求说明书中的错误 是对软件满足所有功能的、行为的和性能的需求的最终保证 在确认测试过程中仅使用黑盒测试技术 2019/4/21

63 7.2.4 测试步骤 5.平行运行 同时运行新开发出来的系统和被它取代的旧系统,以便比较新旧两个系统的处理结果
(1)可以在准生产环境中运行新系统而又不冒风险 (2)用户能有一段熟悉新系统的时间 (3)可以验证用户指南和使用手册之类的文档 (4)能够以准生产模式对新系统进行全负荷测试,可以 用测试结果验证性能指标 2019/4/21

64 7.2.4 测试步骤 2019/4/21

65 测试阶段的信息流 2019/4/21

66 7.2.5 测试阶段的信息流 软件配置:软件需求规格说明、软件设计规格说明、源代码等 测试配置:测试计划、测试用例、测试程序等
测试阶段的信息流 软件配置:软件需求规格说明、软件设计规格说明、源代码等 测试配置:测试计划、测试用例、测试程序等 测试工具:测试数据自动生成程序、静态分析程序、动态分析程序、测试结果分析程序、以及驱动测试的测试数据库等 2019/4/21

67 测试阶段的信息流 2019/4/21

68 7.2.5 测试阶段的信息流 通过收集和分析测试结果数据,对软件建立可靠性模型 利用可靠性分析,评价软件质量:
测试阶段的信息流 通过收集和分析测试结果数据,对软件建立可靠性模型 利用可靠性分析,评价软件质量: 软件的质量和可靠性达到可以接受的程度 所做的测试不足以发现严重的错误 如果测试发现不了错误,可以肯定,测试配置考虑得不够细致充分,错误仍然潜伏在软件中 2019/4/21

69 7.3 单元测试 通常,单元测试和编码属于软件工程过程的同一个阶段
在编写出源程序代码并通过了编译程序的语法检查之后,可以应用人工测试和计算机测试这样两种类型的测试,完成单元测试工作 这两种类型的测试各有所长,互相补充 单元测试主要适用白盒测试技术,可以对多个模块进行并行测试 2019/4/21

70 7.3.1 测试重点 2019/4/21

71 模块接口测试 首先应对通过被测模块的数据流进行测试: 在做内外存交换时要考虑: 调用本模块的输入参数是否正确
本模块调用子模块时输入给子模块的参数是否正确 全局量的定义在各模块中是否一致 在做内外存交换时要考虑: 文件属性是否正确 OPEN与CLOSE语句是否正确 缓冲区容量与记录长度是否匹配 在进行读写操作之前是否打开了文件 在结束文件处理时是否关闭了文件 正文书写/输入错误 I/O错误是否检查并做了处理 2019/4/21

72 局部数据结构 主要目的是确保临时存储的数据在算法执行的整个过程中都能维持完整性,主要测试是否有如下情况: 不正确或不一致的数据类型说明
使用尚未赋值或尚未初始化的变量 错误的初始值或错误的缺省值 变量名拼写错或书写错 不一致的数据类型 全局数据对模块的影响 2019/4/21

73 重要执行通路 遍历所有的独立路径以确保模块中所有语句正确执行 选择适当的测试用例,对模块中重要的执行路径进行测试
应当设计测试用例查找由于错误的计算、不正确的比较或不正常的控制流而导致的错误 对基本执行路径和循环进行测试可以发现大量的路径错误 2019/4/21

74 出错处理通路 在错误发生时,能确保通过错误路径进行重定向处理或干净地终止处理 出错的描述是否难以理解 出错的描述是否能够对错误定位
显示的错误与实际的错误是否相符 对错误条件的处理正确与否 在对错误进行处理之前,错误条件是否已经引起系统的干预等 2019/4/21

75 边界条件 主要是确保程序单元在极限和严格条件下能否正常执行
注意数据流、控制流中刚好等于、大于或小于确定的边界值时出错的可能性。对这些地方要仔细地选择测试用例,认真加以测试 如规定输入0<=n<=100,则选0,100,-1,101作为测试数据 如果对模块运行时间有要求的话,还要专门进行关键路径测试,以确定最坏情况下和平均意义下影响模块运行时间的因素 2019/4/21

76 7.3.2 代码审查  人工测试源程序可以由编写者本人非正式地进行 也可以由审查小组正式进行,称为代码审查
它是一种非常有效的程序验证技术,对于典型的程序来说,可以查出30%~70%的逻辑设计错误和编码错误 审查小组最好由下述四人组成: 组长(没有直接参与工程,且能力很强的程序员) 程序的设计者 程序的编写者 程序的测试者 2019/4/21

77 7.3.2 代码审查  审查会 “预排” 小组成员事先研究设计说明书,可先由设计者概要介绍其设计 审查会上程序员逐句讲解其程序代码
发现错误时由组长进行记录 “预排” 一人扮演“测试者”,其他人扮演“计算机” 测试者实现准备好测试方案,“计算机”成员模拟计算机执行被测试的程序 测试数据和方案应尽可能简单 2019/4/21

78 7.3.2 代码审查  优点:一次审查可以发现多个错误,减少系统验证的总工作量
人工测试和计算机测试是互相补充,相辅相成的,缺少其中任何一种方法都会使查找错误的效率降低 2019/4/21

79 7.3.3 计算机测试 模块并不是一个独立的程序,因此必须为每个单元测试开发驱动软件(drivers)和(或)存根(stubs)软件
通常驱动程序也就是一个“主程序”,它接收测试数据,把这些数据传送给被测试的模块,并且印出有关的结果 存根程序代替被测试的模块所调用的模块。因此存根程序也可以称为“虚拟子程序” 使用被它代替的模块的接口,可能做最少量的数据操作,印出对入口的检验或操作结果,并且把控制和模拟结果归还给调用它的模块 2019/4/21

80 2019/4/21

81 图7.2 正文加工系统的层次图 2019/4/21

82 7.3.3 计算机测试 2019/4/21

83 7.3.3 计算机测试 驱动程序和存根程序代表开销 为了测试必须编写测试软件,但不作为软件产品的一部分 内聚程度影响单元测试的复杂性
高内聚可简化测试过程 2019/4/21

84 7.4 集成测试 集成测试是测试和组装软件的系统化技术,是把模块按照设计要求组装起来的同时进行测试,主要目标是发现与接口有关的问题
在把各个模块连接起来的时侯,穿越模块接口的数据是否会丢失; 一个模块的功能是否会对另一个模块的功能产生不利影响 各个子功能组合起来,能否达到预期要求的父功能; 全局数据结构是否有问题; 单个模块的误差累积起来,是否会放大,从而达到不能接受的程度 2019/4/21

85 7.4 集成测试 由模块组装成程序时有两种方法 一种方法是先分别测试每个模块,再把所有模块按设计要求放在一起结合成所要的程序,这种方法称为非渐增式测试方法或一次性组装(Big Bang) 另一种方法是把下一个要测试的模块同已经测试好的那些模块结合起来进行测试,测试完以后再把下一个应该测试的模块结合进来测试。这种每次增加一个模块的方法称为渐增式测试 2019/4/21

86 一次性组装(Big Bang) 2019/4/21

87 渐增式组装 7.4.1 自顶向下集成(Top-Down Integration)
从主控制模块(main control module)开始,沿着软件的控制层次向下移动,从而逐渐把各个模块结合起来 在把附属于(以及最终附属于)主控制模块的那些模块组装到软件结构中去时,可使用深度优先或宽度优先的策略 2019/4/21

88 渐增式组装 把模块结合进软件结构的具体过程由下述四个步骤完成 1. 对主控制模块进行测试,测试时用存根程序代替所有直接附属于主控制模块的模块
2. 根据选定的结合策略(深度优先或宽度优先),每次用一个实际模块代换一个存根程序(新结合进来的模块往往又需要新的存根程序) 3. 在结合进一个模块的同时进行测试 4. 为了保证加入模块没有引进新的错误,可能需要进行回归测试(即,全部或部分地重复以前做过的测试) 从第二步开始不断地重复进行上述过程,直到构造起完整的软件结构为止 2019/4/21

89 渐增式组装 2019/4/21

90 深度优先:M1->M2->M5->M8->M6->M3->S7->S4
图7.3 自顶向下结合 深度优先:M1->M2->M5->M8->M6->M3->S7->S4 宽度优先:M1->M2->M3->S4->M5->M6->S7->M8 2019/4/21

91 7.4 集成测试 7.4.2 自底向上集成(Bottom-up Integration)
从“原子”模块(在软件结构最低层的模块)开始组装和测试。因为是从底部向上结合,总能得到需要的下层处理功能,所以不需要存根程序 用下述步骤可以实现自底向上的结合策略: 1. 把低层模块组合成实现某特定软件子功能的族 2. 写一个驱动程序(用于测试的控制程序),协调测试数据的输入和输出 3. 对由模块组成的子功能族进行测试 4. 去掉驱动程序,沿软件结构自下向上移动,把子功能族组合起来形成更大的子功能族 上述第2步到第4步实质上构成了一个循环 2019/4/21

92 Bottom-up Integration
图7.4 自底向上结合 Bottom-up Integration 2019/4/21

93 Bottom-up Integration
2019/4/21

94 7.4.3 不同集成测试策略的比较 自顶向下 自底向上的优缺点与自顶向下的测试方法正好相反 优点 缺点 不需要测试驱动程序
能够在测试阶段的早期实现并验证系统的主要功能 能在早期发现上层模块的接口错误 缺点 需要存根程序 低层关键模块中的错误发现比较晚 不能充分展开人力 自底向上的优缺点与自顶向下的测试方法正好相反 2019/4/21

95 7.4.3 不同集成测试策略的比较 在测试实际的软件系统时,应该根据软件的特点以及工程进度安排,选用适当的测试策略。一般说来,纯粹自顶向下或纯粹自底向上的策略可能都不实用,人们在实践中创造出许多混合策略 混合法 较上层使用自顶向下方法 较下层使用自底向上方法 改进的自顶向下测试方法 基本上使用自顶向下测试方法,但是在早期使用自底向上的方法测试软件中的少数关键模块 2019/4/21

96 关键模块 在组装测试时,应当确定关键模块,对这些关键模块及早进行测试
关键模块的特征: ① 满足某些软件需求 ② 在程序的模块结构中位于较高的层次(高层控制模块) ③ 较复杂、较易发生错误 ④ 有明确定义的性能要求 2019/4/21

97 7.4.4 回归测试 每当一个新模块作为集成测试的一部分加进来的时候,软件就发生了变化:建立了新的数据流路径,可能出现了新的I/O操作,激活了新的控制逻辑 这些变化可能使原来工作正常的功能出现问题。在集成测试的范畴中,所谓回归测试是指重新执行已经做过的测试的某个子集,以保证上述这些变化没有带来非预期的副作用 2019/4/21

98 7.4.4 回归测试 回归测试集(已执行过的测试用例的子集)包括下述三种不同的测试用例 检测软件全部功能的代表性测试用例
专门针对可能受修改影响的软件功能的附加测试 针对被修改过的软件成分的测试 2019/4/21

99 7.5 确认测试 确认测试也称为验收测试,它的目标是验证软件的有效性
7.5 确认测试 确认测试也称为验收测试,它的目标是验证软件的有效性 使用了确认(Validation)和验证(Verification)这样两个不同的术语 验证指的是保证软件正确地实现了某一特定要求的一系列活动,而确认指的是保证软件的实现满足了用户需求的一系列活动 2019/4/21

100 7.5 确认测试 7.5.1 确认测试的范围 必须有用户积极参与,或者以用户为主进行
7.5 确认测试 7.5.1 确认测试的范围 必须有用户积极参与,或者以用户为主进行 用户应该参与设计测试方案,使用用户界面输入测试数据并且分析评价测试的输出结果 通常采用黑盒测试法 2019/4/21

101 7.5 确认测试 7.5.2 软件配置复查 7.5.3 Alpha和Beta测试 确认测试的一个重要内容是复查软件配置
7.5 确认测试 7.5.2 软件配置复查 确认测试的一个重要内容是复查软件配置 保证软件配置的所有成分都齐全,质量符合要求,文档与程序完全一致,具有完成软件维护所必须的细节,而且已经编好目录 7.5.3 Alpha和Beta测试 如果一个软件是为许多客户开发的(例如,向大众出售的盒装软件产品),那么让每个客户都进行正式的验收测试是不现实的 绝大多数软件开发商使用被称为Alpha测试和Beta测试的过程,来发现那些看起来只有最终用户才能发现的错误 2019/4/21

102 7.5 确认测试 α测试由用户在开发者的场所进行,并且在开发者对用户的“指导”下进行测试 β测试由最终用户在一(多)个客户场所进行
7.5 确认测试 α测试由用户在开发者的场所进行,并且在开发者对用户的“指导”下进行测试 开发者负责记录错误和使用中遇到的问题 Alpha测试是在受控的环境中进行的 经α测试后的软件称为β版软件 β测试由最终用户在一(多)个客户场所进行 Beta测试是软件在开发者不能控制的环境中的“真实”应用 用户记录下在Beta测试过程中遇到的一切问题(真实的或想像的),定期把这些问题报告给开发者 接收到Beta测试报告的问题后,软件开发者对产品进行修改,并准备向客户发布最终的软件产品 2019/4/21

103 2019/4/21

104 测试方案与技术 测试方案: 具体的测试目的 应该输入的测试数据 预期的结果 选用少量“最有效的”测试数据,做到尽可能完备的测试
设计测试方案的基本目标是,确定一组最可能发现某个错误或某类错误的预测数据 多种设计测试数据的技术(白盒、黑盒) 各自优缺点、应用场合(综合运用) 测试用例 2019/4/21

105 7.6 白盒测试技术 白盒测试法的前提是可以把程序看成装在一个透明的白盒子里,也就是完全了解程序的结构和处理过程
这种方法按照程序内部的逻辑测试程序,检验程序中的每条通路是否都能按预定要求正确工作 白盒测试又称为结构测试(Structural Testing) 2019/4/21

106 白盒测试的基本目标 对程序模块的所有独立的执行路径至少测试一次 对所有的逻辑判定,取“真”与取“假”的两种情况都至少测试一次
在循环的边界和运行界限内执行循环体 测试内部数据结构的有效性 2019/4/21

107 7.6.1 逻辑覆盖(Code Coverage) 有选择地执行程序中某些最有代表性的通路是对穷尽测试的唯一可行的替代办法
逻辑覆盖是对一系列测试过程的总称,这组测试过程逐渐进行越来越完整的通路测试 测试数据执行(或叫覆盖)程序逻辑的程度可以划分成哪些不同的等级,从覆盖源程序语句的详尽程度分析,有以下一些不同的覆盖标准: 1.语句覆盖 2019/4/21

108 1.语句覆盖(Statement Coverage)
语句覆盖的含义是,选择足够多的测试数据,使被测程序中每个语句至少执行一次 测试用例的设计格式如下【输入的(A, B, X),输出的(A, B, X)】 为图例设计满足语句覆盖的测试用例是: 【(2, 0, 4),(2, 0, 3)】  覆盖 sacbed 2019/4/21

109 2.判定覆盖(Decision/Branch Coverage)
判定覆盖又叫分支覆盖,它的含义是,不仅每个语句必须至少执行一次,而且每个判定的每种可能的结果都应该至少执行一次,也就是每个判定的每个分支都至少执行一次 2019/4/21

110 2.判定覆盖(Decision/Branch Coverage)
一组可用的测试用例: 【(2, 0, 4),(2, 0, 3)】覆盖 sacbed 【(1, 1, 1),(1, 1, 1)】覆盖 sabd 另一组可用的测试用例: 【(2, 1, 1),(2, 1, 2)】覆盖 sabed 【(3, 0, 3),(3, 1, 1)】覆盖 sacbd 2019/4/21

111 3 条件覆盖(Condition Coverage)
条件覆盖的含义是,不仅每个语句至少执行一次,而且使判定表达式中的每个条件都取到各种可能的结果 2019/4/21

112 3 条件覆盖(Condition Coverage)
为了做到条件覆盖,应该选取测试数据使得: 在a点有下述各种结果出现: A>1,A<=1,B=0,B!=0; 在b点有下述各种结果出现: A=2,A!=2,X>1,X<=1 使用下面两组测试数据就可以达到上述覆盖标准: A=2,B=0,X=4 (满足A>1,B=0,A=2,X>1的条件,执行路径sacbed) A=1,B=1,X=1 (满足A<=1,B!=0,A!=2,X<=1的条件,执行路径sabd) 2019/4/21

113 3 条件覆盖(Condition Coverage)
条件覆盖通常比判定覆盖强,因为它使判定达 式中每个条件都取到了两个不同的结果,判定 覆盖却只关心整个判定表达式的值。 但是,也可能有相反的情况: A=2,B=0,X=1 (满足A>1,B=0,A=2,X <= 1的条件,执行路径sacbed) A=1,B=1,X=2 (满足A<=1,B!=0,A!=2,X>1的条件,执行路径sabed) a=T; b=T a=F; b=T (b=F的情况未覆盖) 2019/4/21

114 4.判定/条件覆盖(Decision/Condition Coverage)
既然判定覆盖不一定包含条件覆盖,条件覆盖也不一定包含判定覆盖,自然会提出一种能同时满足这两种覆盖标准的逻辑覆盖,这就是判定/条件覆盖 它的含义是,选取足够多的测试数据,使得判定表达式中的每个条件都取到各种可能的值,而且每个判定表达式也都取到各种可能的结果 2019/4/21

115 4.判定/条件覆盖(Decision/Condition Coverage)
使用下面两组测试数据就可以达到上述覆盖标准: A=2,B=0,X=4 (满足A>1,B=0,A=2,X>1的条 件,执行路径sacbed,a=T; b=T) A=1,B=1,X=1 (满足A<=1,B!=0,A!=2,X<=1 的条件,执行路径sabd, a=F; b=F) 2019/4/21

116 5.条件组合覆盖(Multiple Condition Coverage)
条件组合覆盖是更强的逻辑覆盖标准,它要求选取足够多的测试数据,使得每个判定表达式中条件的各种可能组合都至少出现一次 2019/4/21

117 5.条件组合覆盖(Multiple Condition Coverage)
共有8中可能的条件组合: (1) A>1,B=0 (2) A>1,B!=0 (3) A<=1,B=0 (4) A<=1 ,B!=0 (5) A=2,X>1 (6) A=2,X <= 1 (7) A!=2,X>1 (8) A!=2 ,X <= 1 2019/4/21

118 5.条件组合覆盖(Multiple Condition Coverage)
【2,0,4】,针对(1)(5)两种组合,执行路径sacbed 【2,1,1】,针对( 2 )( 6)两种组合,执行路径sabed 【1,0,2】,针对( 3 )( 7)两种组合,执行路径sabed 【1,1,1】,针对( 4 )( 8)两种组合,执行路径sabd 前述几种覆盖标准中最强的,但是并不一定能使 程序中的每条路径都执行到(sacbd) 2019/4/21

119 6. 路径覆盖(Path Coverage) 【(2, 0, 4),(2, 0, 3)】覆盖 sacbed (a=T; b=T) 【(1, 1, 1),(1, 1, 1)】覆盖 sabd (a=F; b=F) 【(2, 1, 1),(2, 1, 2)】覆盖 sabed (a=F; b=F) 【(3, 0, 3),(3, 1, 1)】覆盖 sacbd (a=T; b=F) 2019/4/21

120 思考题1 (1,1,1) (20,40,60) 同时符合判定覆盖 2019/4/21

121 思考题2 2019/4/21

122 思考题2参考答案 判定覆盖用例 条件覆盖用例 判定/条件覆盖 (1,1,2,3) (-1,-1,-2,0) (1,1,2,2)
(-1,-1,-2,-2) 判定/条件覆盖 (1,1,2,0) 2019/4/21

123 思考题2参考答案 条件组合覆盖用例 ① A>0,B>0 ② A>0,B<=0 ③ A<=0,B>0
⑤ C>A,D<B ⑥ C>A,D>=B ⑦ C<=A,D<B ⑧ C<= A,D>= B 2019/4/21

124 思考题2参考答案 条件组合覆盖用例 条件组合覆盖用例 ① (1,1,2,0)实现① ⑤ ① A>0,B>0
② (1,0,2,1)实现② ⑥ ③ (0,1,-1,0)实现③ ⑦ ④ (0,0,-1,1)实现④ ⑧ 提醒:设计测试用例的时候别忘了预期输出 条件组合覆盖用例 ① A>0,B>0 ② A>0,B<=0 ③ A<=0,B>0 ④ A <= 0,B <= 0 ⑤ C>A,D<B ⑥ C>A,D>=B ⑦ C<=A,D<B ⑧ C<= A,D>= B 2019/4/21

125 7.6.2 控制结构测试 1 基本路径测试 Tom McCabe提出的一种白盒测试技术 使用基本路径测试技术设计测试用例的步骤如下:
控制结构测试 1 基本路径测试 Tom McCabe提出的一种白盒测试技术 使用这种技术设计测试用例时,首先计算过程设计结果的逻辑复杂度,并以该复杂度为指南定义执行路径的基本集合,从该基本集合导出的测试用例可以保证程序中每条语句至少执行一次,而且每个条件在执行时都将分别取true(真)和false(假)值 使用基本路径测试技术设计测试用例的步骤如下: 1.根据过程设计结果画出相应的流图 2019/4/21

126 2019/4/21

127 input 2019/4/21

128 图7.6 求平均值过程的流图 2.计算流图的环形复杂度 环形复杂度为6 2019/4/21

129 1.基本路径测试 3.确定线性独立路径的基本集合
所谓独立路径是指至少引入程序的一个新处理语句集合或一个新条件的路径,用流图术语描述,独立路径至少包含一条在定义该路径之前不曾用过的边 使用基本路径测试法设计测试用例时,程序的环形复杂度决定了程序中独立路径的数量,而且这个数是确保程序中所有语句至少被执行一次所需的测试数量的上界 对于图7.6所描述的求平均值过程来说,由于环形复杂度为6,因此共有6条独立路径 2019/4/21

130 1.基本路径测试 路径1:1-2-10-11-13 路径2:1-2-10-12-13 路径3:1-2-3-10-11-13
路径4:  路径5:  路径6:  路径4、5、6后面的省略号(...)表示,可以后接通过控制结构其余部分的任意路径( 或 ) 通常在导出测试用例时,识别出判定节点是很有必要的。本例中节点2、3、5、6和10是判定节点 2019/4/21

131 1.基本路径测试 4.设计可强制执行基本集合中每条路径测试用例 应该选取数据使得在测试每条路径时都适当地设置好了各个判定节点的条件
路径1的测试用例: value[k]=有效输入值,其中k<i (i的定义在下) value[i]=-999,其中2≤i≤n 预期结果:基于k的正确平均值和总数 注意: 路径1无法独立测试,必须作为路径4、5和6的一部分来测试 路径2的测试用例: value[1] =-999 预期结果:average=-999,其他都保持初始值 2019/4/21

132 input 2019/4/21

133 1.基本路径测试 路径3的测试用例: 路径4的测试用例: 试图处理超过n个数据 前n个数值为有效输入 预期结果:与测试用例相同
注意:路径3 也无法独立测试,必须作为路径4、5、6的一部分 路径4的测试用例: value[i]=有效输入值,其中i<n value[k] < minimum,其中k<i 预期结果:其于k的正确平均值和总数 2019/4/21

134 input 2019/4/21

135 1.基本路径测试 路径5的测试用例: 路径6的测试用例: value[i]=有效输入值,其中i<n 预期结果:正确的平均值和总数
value[k]>maximum,其中k<i 预期结果:其于k的正确平均值和总数 路径6的测试用例: value[i]=有效输入值,其中i<n 预期结果:正确的平均值和总数 2019/4/21

136 input 2019/4/21

137 测试用例实例 n=5, minimum=0, maximum=100 2019/4/21

138 思考题3 2019/4/21

139 思考题3参考答案 环形复杂度:V(G)=5 独立路径上限为5 1-2-3-4-6-7-9-11-12 1-2-5-6-7-9-11-12
2019/4/21

140 思考题3参考答案 ①1-2-3-4-6-7-9-11-12 (1,1,2,2),(2,0) ②1-2-5-6-7-9-11-12
(0,1,2,0),(-1,2) (1,0,2,0),(1,2) (1,1,0,-1),(2,1) (1,1,0,2),(2,2) 2019/4/21

141 2. 条件测试 基本路径测试简单高效,但是只有这样的技术还不够,为了进一步提高白盒测试的质量,还需要使用其他控制结构技术
条件测试技术设计出的测试用例,能够检查程序模块中包含的逻辑条件 条件测试基础 简单条件格式:一个布尔变量或一个关系表达式,在布尔变量或关系表达式之前还可能有一个NOT算符。关系表达式的形式如下: E1<关系算符>E 关系算符:>,<,≥≤≠= 复合条件:复合条件由两个或多个简单条件、布尔算符和括弧组成。布尔算符有OR,AND和NOT。不包含关系表达式的条件称为布尔表达式 条件成分类型:包括布尔算符、布尔变量、布尔括弧、关系算符及算术表达式 2019/4/21

142 条件错误类型 布尔算符错 (布尔算符不正确,遗漏布尔算符或有多余的布尔算符) 布尔变量错 布尔括弧错 关系算符错 算术表达式错
2019/4/21

143 条件测试的准则 条件测试的目的不仅是检测程序条件中的错误,而且是检测程序中的其他错误。如果程序P的测试集能有效地检测P中条件的错误,则它很可能也可以有效地检测P中的其他错误 域测试要求对一个关系表达式执行3个或4个测试。对于形式为 E1<关系算符>E2 的关系表达式来说,需要3个测试分别使E1的值大于、等于或小于E2的值。如果<关系算符>错误而E1和E2正确,则这3个测试能够发现关系算符的错误。为了发现E1和E2中的错误,让E1值大于或小于E2值的测试数据应该使这两个值之间的差别尽可能小(最好能在边界上取值) 2019/4/21

144 BRO条件测试 前提:在条件中所有布尔变量和关系算符都只出现一次而且没有公共变量,则该测试保证能发现该条件中的分支错和关系算符错
描述:包含n个简单条件的条件C的条件约束定义为(D1,D2,…,Dn),其中Di(0<i≤n)表示条件C中第i个简单条件的输出约束 如果在条件C的一次执行过程中,C中每个简单条件的输出都满足D中对应的约束,则称C的这次执行覆盖了C的条件约束D 2019/4/21

145 例子1 C1:B1&B2 其中,B1和B2是布尔变量。C1的条件约束形式为(D1,D2),其中D1和D2中的每一个都是“t”或“f”。值(t,f)是C1的一个条件约束,并由使B1值为真B2值为假的测试所覆盖。BRO测试策略要求,约束集{(t,t),(f,t),(t,f)}被C1的执行所覆盖。如果C1因布尔算符错误而不正确,则至少上述约束集中的一个约束将迫使C1失败。 2019/4/21

146 例子2 C2:B1&(E3=E4) 其中,B1是布尔变量,E3和E4是算术表达式。C2的条件约束形式为(D1,D2),其中D1是“t”或“f”,D2是>,=或<。除了C2的第二个简单条件是关系表达式之外,C2和C1相同,因此,可以通过修改C1的约束集{(t,t),(f,t),(t,f)}得出C2的约束集。注意,对于(E3=E4)来说,“t”意味“=”,而“f”意味着“<”或“>”,因此,分别用(t,=)和(f,=)替换(t,t)和(f,t),并用(t,<)和(t,>)替换(t,f),就得到C:的约束集{(t,=),(f,=),(t,<),(t,>)}。覆盖上述条件约束集的测试,保证可以发现C2中布尔算符和关系算符的错误 2019/4/21

147 例子3 C3:(E1>E2)&(E3=E4) 其中, E1,E2,E3和E4是算术表达式。C3的条件约束形式为(D1,D2),而D1和D2的每一个都是>,=或<。除了C3的第一个简单条件是关系表达式之外,C3和C2相同,因此,可以通过修改C2的约束集得到C3的约束集,结果为: {(>,=),(=, =),(<, =),(>,<),(>,>))覆盖上述条件约束集的测试,保证可以发现C3中关系算符的错误。 2019/4/21

148 3.循环测试 循环测试是一种白盒测试技术,它专注于测试循环结构的有效性 2019/4/21

149 3.循环测试 (1)简单循环 应该使用下列测试集来测试简单循环,其中n是允许通过循环的最大次数 跳过循环 只通过循环一次
通过循环两次 通过循环m次,其中m<n-1 通过循环n-1,n,n+1次 2019/4/21

150 3.循环测试 (2)嵌套循环 如果把简单循环的测试方法直接应用到嵌套循环,可能的测试数就会随嵌套层数的增加按几何级数增长,这会导致不切实际的测试数目。B. Beizer提出了一种能减少测试数的方法 从最内层循环开始测试,把所有其他循环都设置为最小值 对最内层循环使用简单循环测试方法,而使外层循环的迭代参数(例如,循环计数器)取最小值,并为越界值或非法值增加一些额外的测试 由内向外,对下一个循环进行测试,但保持所有其他外层循环为最小值,其内循环为“典型”值 继续进行下去,直到测试完所有循环 2019/4/21

151 3.循环测试 (3)串接循环 如果串接循环的各个循环都彼此独立,则可以使用前述的测试简单循环的方法来测试串接循环
但是,如果两个循环串接,而且第一个循环的循环计数器值是第二个循环的初始值,则这两个循环并不是独立的。当循环不独立时,建议使用测试嵌套循环的方法来测试串接循环 2019/4/21

152 7.7 黑盒测试技术 黑盒测试着重测试软件的功能需求,也就是说,黑盒测试让软件工程师设计出能充分检查程序所有功能需求的输入条件集
7.7 黑盒测试技术 黑盒测试着重测试软件的功能需求,也就是说,黑盒测试让软件工程师设计出能充分检查程序所有功能需求的输入条件集 黑盒测试并不能取代白盒测试技术,它是与白盒测试互补的方法,它很可能发现白盒测试不易发现的其他不同类型的错误 2019/4/21

153 7.7 黑盒测试技术 黑盒测试力图发现下述类型的错误: 白盒测试在测试过程的早期阶段进行,而黑盒测试主要用于测试过程的后期
7.7 黑盒测试技术 黑盒测试力图发现下述类型的错误: ① 功能不正确或遗漏了功能; ② 界面错误; ③ 数据结构错误或外部数据库访问错误; ④ 性能错误; ⑤ 初始化和终止错误。 白盒测试在测试过程的早期阶段进行,而黑盒测试主要用于测试过程的后期 黑盒测试故意不考虑程序的控制结构,而把注意力集中于信息域 2019/4/21

154 7.7 黑盒测试技术 黑盒测试方案应该考虑下述问题: ① 怎样测试功能的有效性; ② 哪些类型的输入将构成好测试用例;
7.7 黑盒测试技术 黑盒测试方案应该考虑下述问题: ① 怎样测试功能的有效性; ② 哪些类型的输入将构成好测试用例; ③ 系统是否对特定的输入值特别敏感; ④ 怎样划分数据类的边界; ⑤ 系统能够承受什么样的数据率和数据量; 数据的特定组合将对系统运行产生什么影响。 2019/4/21

155 7.7 黑盒测试技术 应该设计满足下述标准的测试用例集: ① 所设计出的测试用例能够减少为达到合理测试所需要设计的附加测试的数目
7.7 黑盒测试技术 应该设计满足下述标准的测试用例集: ① 所设计出的测试用例能够减少为达到合理测试所需要设计的附加测试的数目 ② 所设计出的测试用例能够告诉我们,是否存在某些类型的错误,而不是仅仅指出与特定测试相关的错误是否存在 2019/4/21

156 等价划分 等价划分(Equivalence Partitioning)是一种黑盒测试方法,这种方法把程序的输入域划分成数据类,据此可以导出测试用例 一个理想的测试用例能独自发现一类错误(例如,对所有字符数据的处理都不正确) 如果把所有可能的输入数据(有效的和无效的)划分成若干个等价类(Equivalence Sets),则可以合理地做出下述假定: 每类中的一个典型值在测试中的作用与这一类中所有其他值的作用相同 因此,可以从每个等价类中只取一组数据作为测试数据。这样选取的测试数据最有代表性,最可能发现程序中的错误 2019/4/21

157 等价划分 使用等价划分法设计测试方案首先需要划分输入数据的等价类,为此需要研究程序的功能说明,从而确定输入数据的有效(Valid)等价类和无效(Invalid)等价类 在确定输入数据的等价类时常常还需要分析输出数据的等价类,以便根据输出数据的等价类导出对应的输入数据等价类 划分等价类需要经验,下述几条启发式规则可能有助于等价类的划分 2019/4/21

158 等价划分 如果规定了输入值的范围,则可划分出一个有效的等价类(输入值在此范围内),两个无效的等价类(输入值小于最小值或大于最大值) 如果规定了输入数据的个数,则类似地也可以划分出一个有效的等价类和两个无效的等价类 如果规定了输入数据的一组值,而且程序对不同输入值做不同处理,则每个允许的输入值是一个有效的等价类,此外还有一个无效的等价类(任一个不允许的输入值) 如果规定了输入数据必须遵循的规则,则可以划分出一个有效的等价类(符合规则)和若干个无效的等价类(从各种不同角度违反规则) 如果规定了输入数据为整型,则可以划分出正整数、零和负整数等三个有效类 如果程序的处理对象是表格,则应该使用空表,以及含一项或多项的表 2019/4/21

159 7.7.1 等价划分 划分出等价类以后,根据等价类设计测试方案时主要使用下面两个步骤
等价划分 划分出等价类以后,根据等价类设计测试方案时主要使用下面两个步骤 设计一个新的测试方案以尽可能多地覆盖尚未被覆盖的有效等价类,复重这一步骤直到所有有效等价类都被覆盖为止 设计一个新的测试方案,使它覆盖一个而且只覆盖一个尚未被覆盖的无效等价类,重复这一步骤直到所有无效等价类都被覆盖为止 2019/4/21

160 7.7.1 等价划分 下面用等价划分法设计一个简单程序的测试方案
等价划分 下面用等价划分法设计一个简单程序的测试方案 假设有一个把数字串转变成整数的函数。运行程序的计算机字长16位,用二进制补码表示整数。这个函数是用PASCAL语言编写的,它的说明如下: function strtoint(dstr:shortstr):integer; 函数的参数类型是shortstr,它的说明是: type shortstr=array[1..6]of char; 被处理的数字串是右对齐的,也就是说,如果数字串比六个字符短,则在它的左边补空格。如果数字串是负的,则负号和最高位数字紧相邻(负号在最高位数字左边一位) 2019/4/21

161 等价划分 考虑到PASCAL编译程序固有的检错功能,测试时不需要使用长度不等于6的数组做实在参数,更不需要使用任何非字符数组类型的实在参数 分析这个程序的规格说明,可以划分出如下等价类 有效输入的等价类有 1~6个数字字符组成的数字串(最高位数字不是零) 最高位数字是零的数字串 最高位数字左邻是负号的数字串 2019/4/21

162 7.7.1 等价划分 无效输入的等价类有 合法输出的等价类有 空字符串(全是空格); 左部填充的字符既不是零也不是空格;
等价划分 无效输入的等价类有 空字符串(全是空格); 左部填充的字符既不是零也不是空格; 最高位数字右面由数字和空格混合组成; 最高位数字右面由数字和其他字符混合组成;  负号与最高位数字之间有空格。 合法输出的等价类有 在计算机能表示最小负整数和零之间的负整数; 零; 在零和计算机能表示最大正整数之间的正整数。 2019/4/21

163 7.7.1 等价划分 非法输出的等价类有 根据上面划分出的等价类,可以设计出下述测试方案(注意,每个测试方案由三部分内容组成)。
等价划分 非法输出的等价类有 比计算机能表示的最小负整数还小的负整数; 比计算机能表示的最大正整数还大的正整数。 因为所用的计算机字长16位,用二进制补码表示整数,所以能表示的最小负整数是-32768,能表示的最大正整数是32767。 根据上面划分出的等价类,可以设计出下述测试方案(注意,每个测试方案由三部分内容组成)。 1~6个数字组成的数字串,输出是合法的正整数。 输入:‘ ’ 预期的输出:1 2019/4/21

164 7.7.1 等价划分 最高位数字是零的数字串,输出是合法的正整数。 负号与最高位数字紧相邻,输出合法的负整数。
等价划分 最高位数字是零的数字串,输出是合法的正整数。 输入:‘000001’ 预期的输出:1 负号与最高位数字紧相邻,输出合法的负整数。 输入:‘-00001’ 预期的输出:-1 最高位数字是零,输出也是零。 输入:‘000000’ 预期的输出:0 太小的负整数。 输入:‘-47561’ 预期的输出:“错误——无效输入” 2019/4/21

165 7.7.1 等价划分 太大的正整数。 空字符串。 字符串左部字符既不是零也不是空格。 输入:‘132767’
等价划分 太大的正整数。 输入:‘132767’ 预期的输出:“错误——无效输入” 空字符串。 输入:‘ ’ 预期的输出:“错误——没有数字” 字符串左部字符既不是零也不是空格。 输入:‘╳ ╳ ╳ ╳ ╳ 1’ 预期的输出:“错误——填充错” 2019/4/21

166 7.7.1 等价划分 最高位数字后面有空格。 最高位数字后面有其他字符。 负号和最高位数字之间有空格。 输入:‘ 1 2’
等价划分 最高位数字后面有空格。 输入:‘ ’ 预期的输出:“错误——无效输入” 最高位数字后面有其他字符。 输入:‘1 ╳ ╳ 2’ 负号和最高位数字之间有空格。 输入:‘ ’ 预期的输出:“错误——负号位置错” 2019/4/21

167 7.7.2 边界值分析 经验表明,处理边界情况时程序最容易发生错误。
例如,许多程序错误出现在下标、纯量、数据结构和循环等的边界附近 因此,设计使程序运行在边界情况附近的测试方案,暴露出程序错误的可能性更大一些 使用边界值分析(Boundary Value Analysis)方法设计测试方案首先应该确定边界情况,这需要经验和创造性,通常输入等价类和输出等价类的边界,就是应该着重测试的程序边界情况 2019/4/21

168 7.7.2 边界值分析 选取的测试数据应该刚好等于、刚刚小于和刚刚大于边界值
按照边界值分析法,应该选取刚好等于、稍小于和稍大于等价类边界值的数据作为测试数据,而不是选取每个等价类内的典型值或任意值作为测试数据 2019/4/21

169 7.7.2 边界值分析 如规定输入输出条件范围,则选取的测试数据应该刚好等于、刚刚小于和刚刚大于边界值
如规定输入0<=n<=100,则选0,100,-1,101作为测试数据 如果规定了输入输出个数,则分别选最大个数,最小个数,比最大个数多1,比最小个数少1作为测试数据 如规定学生至少选5门课,至多选9门课,则选5, 9, 4, 10作为测试数据 如果输入输出为有序集合,如文件或表格,应将注意力集中在有序集的第一个和最后一个元素 如果程序中定义的数据结构有预定义的边界,如数组的上下界,则选择刚好打到边界和刚好超出边界的数据为测试数据 2019/4/21

170 7.7.2 边界值分析 用边界分析法补充上一小节测试方案: 使输出刚好等于最小的负整数 使输出刚好等于最大的正整数 输入:‘-32768’
预期输出: 使输出刚好等于最大的正整数 输入:‘32767’ 预期输出: 32767 2019/4/21

171 7.7.2 边界值分析 使输出刚好小于最小的负整数 使输出刚好大于最大的正整数 输入:‘-32769’ 预期输出: “错误——无效输入”
输入:‘32768’ 2019/4/21

172 思考题 根据下面的规格说明,利用等价类划分的方法,给出测试用例
"一个程序读入3个整数,它们分别代表一个三角形的3个边长。该程序判断所输入的整数是否构成一个三角形,以及该三角形是一般的、等腰的或等边的,并将结果打印出来。" 要求:设三角形的3条边分别为A、B、C,列出等价类,设计测试用例 2019/4/21

173 思考题参考答案 用例1 (3,4,5),输出构成三角形 用例2 (0,4,4),输出不构成三角形 用例3 (3,4,10),输出不构成三角形
用例4 (3,3,4),输出构成等腰三角形 用例6 (3,3,3),输出构成等边三角形 2019/4/21

174 7.7.3 错误推测 对于程序中可能存在哪类错误的推测,是挑选测试方案的一个重要因素
错误推测法在很大程度上靠直觉和经验进行。它的基本想法是列举出程序中可能有的错误和容易发生错误的特殊情况,并且根据它们选择测试方案 已经发现的错误数目往往和尚未发现的错误数目成正比,因此,在进一步测试时要着重测试那些已经发现了较多错误的程序段 例如测试一个排序程序 输入表为空表、输入表只有一个元素、输入表所有元素都相同、输入表已经排好序 2019/4/21

175 因果图 因果图的适用范围 因果图方法最终生成的就是判定表,它适合于检查程序输入条件的各种组合情况
如果在测试时必须考虑输入条件的各种组合,可使用一种适合于描述对于多种条件的组合,相应产生多个动作的形式来设计测试用例,这时就需要利用因果图 因果图方法最终生成的就是判定表,它适合于检查程序输入条件的各种组合情况 2019/4/21

176 基本步骤 分析软件规格说明描述中,哪些是原因 (即输入条件或输入条件的等价类),哪些是结果 (即输出条件),并给每个原因和结果赋予一个标识符
分析软件规格说明描述中的语义,找出原因与结果之间,原因与原因之间对应的是什么关系? 根据这些关系,画出因果图 由于语法或环境限制,有些原因与原因之间,原因与结果之间的组合情况不可能出现。为表明这些特殊情况,在因果图上用一些记号标明约束或限制条件 把因果图转换成判定表 把判定表的每一列拿出来作为依据,设计测试用例 2019/4/21

177 因果图中的基本符号 通常在因果图中用Ci (cause)表示原因,用Ei (effect)表示结果,各结点表示状态,可取值“0”或“1”。“0”表示某状态不出现,“1”表示某状态出现 2019/4/21

178 因果图中的约束条件符号 互斥:至多有一个为1 包含:至少有一个为1 唯一:有且仅有一个为1 要求:若a=1,则b必须为1
2019/4/21

179 示例:饮料自动售货机 若投入5角钱或1元钱的硬币,押下〖橙汁〗或〖啤酒〗的按钮,则相应的饮料就送出来
若售货机没有零钱找,则一个显示〖零钱找完〗的红灯亮,这时在投入1元硬币并押下按钮后,饮料不送出来而且1元硬币也退出来 若有零钱找,则显示〖零钱找完〗的红灯灭,在送出饮料的同时退还5角硬币 2019/4/21

180 示例分析 (1) 原因: 1. 售货机有零钱找 2. 投入1元硬币 3. 投入5角硬币 4. 押下橙汁按钮 5. 押下啤酒按钮
中间结点,表示处理中间状态 投入1元硬币且押下饮料按钮 押下〖橙汁〗或〖啤酒〗的按钮 应当找5角零钱并且售货机有零钱找 钱已付清 2019/4/21

181 示例分析 (2) 结果 21. 售货机〖零钱找完〗灯亮 22. 退还1元硬币 23. 退还5角硬币 24. 送出橙汁饮料
25. 送出啤酒饮料 画出因果图: 所有原因结点列在左边,所有结果结点列在右边 由于 2 与 3 ,4 与 5 不能同时发生,分别加上约束条件E 将因果图转换成判定表 2019/4/21

182 示例因果图 2019/4/21

183 判定表 2019/4/21

184 7.8 调试 调试(也称为纠错, Debug)作为成功的测试的后果而出现,即调试是在测试发现错误之后排除错误的过程 7.8.1 调试过程
调试过程 调试不是测试,但是它总是发生在测试之后 调试过程从执行一个测试用例开始,评估测试结果 如果发现实际结果与预期结果不一致,则这种不一致就是一个症状,它表明在软件中存在着隐藏的问题 调试过程试图找出产生症状的原因,以便改正错误 2019/4/21

185 图7.8 调试过程 7.8 调试 2019/4/21

186 调试途径 无论采用什么方法,调试的根本目标都是寻找软件错误的原因并改正之。这个目标是通过把系统地评估、直觉和运气组合起来实现的。一般来说,有下列三种调试途径可以采用: 蛮干法:打印内存数据、关键输出、断点 回溯法:由症状回推可能的原因 原因排除法:对分查找、归纳、演绎等方法 2019/4/21

187 7.8.2 调试途径 对分查找法 归纳法 演绎法 知道关键点的正确值,在程序中点“注入”变量的正确值,然后运行程序检查输出
调试途径 对分查找法 知道关键点的正确值,在程序中点“注入”变量的正确值,然后运行程序检查输出 归纳法 从个别现象推断出一般性结论的思维方法。把和错误有关的数据组织起来进行分析,以便发现可能的错误原因。利用假设证明或排除可能的错误原因 演绎法 从一般原理或前提出发,经过排除和精化的过程推导出结论 2019/4/21

188 2019/4/21

189 7.8.2 调试途径 在修改错误之前需要考虑: 是否同样的错误也存在于程序的其他地方? 将要进行的修改可能会引入的“下一个错误”是什么?
调试途径 在修改错误之前需要考虑: 是否同样的错误也存在于程序的其他地方? 将要进行的修改可能会引入的“下一个错误”是什么? 为防止今后出现类似的错误,应该做什么? 2019/4/21

190 7.9 软件可靠性 7.9.1 基本概念 软件可靠性的定义 对于软件可靠性有许多不同的定义,其中多数人承认的一个定义是:
7.9 软件可靠性 基本概念 软件可靠性的定义 对于软件可靠性有许多不同的定义,其中多数人承认的一个定义是: 软件可靠性是程序在给定的时间间隔内,按照规格说明书的规定成功地运行的概率。 2019/4/21

191 基本概念 软件的可用性 通常用户也很关注软件系统可以使用的程度。一般来说,对于任何其故障是可以修复的系统,都应该同时使用可靠性和可用性来衡量它的优劣程度 软件可用性的一个定义是: 软件可用性是程序在给定的时间点,按照规格说明书的规定,成功地运行的概率 可靠性:0到t这段时间间隔内,系统没有失效 可用性:t时刻,系统是正常运行的 2019/4/21

192 基本概念 如果在一段时间内,软件系统故障停机时间分别为td1,td2…,正常运行时间分别为tu1,tu2,…,则系统的稳态可用性为: 其中 Tup = ∑tui, Tdown = ∑tdi 如果引入系统平均无故障时间MTTF和平均维修时间MTTR的概念,则上式可以变成 2019/4/21

193 基本概念 平均维修时间MTTR(Mean Time To Repair/Recover)是修复一个故障平均需要用的时间,取决于维护人员的技术水平和对系统的熟悉程度,也和系统的可维护性有重要关系 平均无故障时间MTTF(Mean Time To Failure)是系统按规格说明书规定成功地运行的平均时间,它主要取决于系统中潜伏的错误的数目,因此和测试的关系十分密切 2019/4/21

194 7.9.2 估算平均无故障时间的方法 软件的平均无故障时间MTTF是一个重要的质量指标,往往作为对软件的一项要求由用户提出
估算平均无故障时间的方法 软件的平均无故障时间MTTF是一个重要的质量指标,往往作为对软件的一项要求由用户提出 估算MTTF使用下述符号表示有关的数量: ET——测试之前程序中错误总数; IT ——程序长度(机器指令总数); τ——测试(包括调试)时间; Ed(τ)——在0至τ期间发现的错误数 Ec(τ)——在0至τ期间改正的错误数 2019/4/21

195 7.9.2 估算平均无故障时间的方法 根据经验数据,可以作出下述假定: 0.5 × 10-2 ≤ ET / IT≤2×10-2
估算平均无故障时间的方法 根据经验数据,可以作出下述假定: 在类似的程序中,单位长度里的错误数ET/IT近似为常数。美国的一些统计数字表明,通常 0.5 × 10-2 ≤ ET / IT≤2×10-2 也就是说,在测试之前每1000条指令中大约有5~20个错误 失效率正比于软件中剩余的(潜藏的)错误数,而平均无故障时间MTTF与剩余的错误数成反比 2019/4/21

196 εr(τ)=ET/IT -Ec(τ)/IT
7.9.2 估算平均无故障时间的方法 此外,为了简化讨论,假设发现的每一个错误都立即正确地改正了(调试过程没有引入新的错误)。因此 Ec(τ)=Ed(τ) 剩余的错误数为 Er(τ)=ET-Ec(τ) 单位长度程序中剩余的错误数为 εr(τ)=ET/IT -Ec(τ)/IT 2019/4/21

197 7.9.2 估算平均无故障时间的方法 估算平均无故障时间 经验表明,平均无故障时间与单位长度程序中剩余的错误数成反比,即 
其中K为常数,它的值应该根据经验选取。美国的一些统计数字表明,K的典型值是200 2019/4/21

198 7.9.2 估算平均无故障时间的方法 估算平均无故障时间的公式,可以评价软件测试的进展情况。此外,由上式可得
因此,也可以根据对软件平均无故障时间的要求,估计需要改正多少个错误之后,测试工作才能结束 2019/4/21

199 7.9.2 估算平均无故障时间的方法 估计错误总数的方法 植入错误法
在测试之前由专人在程序中随机地植入一些错误,测试之后,根据测试小组发现的错误中原有的和植入的两种错误的比例,来估计程序中原有错误的总数ET。 假设人为地植入的错误数为Ns,经过一段时间的测试之后发现ns个植入的错误,此外还发现了n个原有的错误。如果可以认为测试方案发现植入错误和发现原有错误的能力相同,则能够估计出程序中原有错误的总数为: N’= *Ns 其中N’即是错误总数ET的估计值 2019/4/21

200 7.9.2 估算平均无故障时间的方法 分别测试法 随机地给一部分错误加标记,分别测试法使用两个测试员(或测试小组),彼此独立地测试同一个程序的两个副本,把其中一个测试员发现的错误作为有标记的错误。具体做法是,在测试过程的早期阶段,由测试员甲和测试员乙分别测试同一个程序的两个副本,由另一名分析员分析他们的测试结果。用τ表示测试时间,假设 τ= 0 时错误总数为B0; τ=τ1时测试员甲发现的错误数为B1; τ=τ1时测试员乙发现的错误数为B2; τ=τ1时两个测试员发现的相同错误数为bc。 2019/4/21

201 7.9.2 估算平均无故障时间的方法 如果认为测试员甲发现的错误是有标记的,即程序中有标记的错误总数为B1,则测试员乙发现的B2个错误中有bc个是有标记的。假定测试员乙发现有标记错误和发现无标记错误的概率相同,则可以估计出测试前程序中的错误总数为 使用分别测试法,在测试阶段的早期,每隔一段时间分析员分析两名测试员的测试结果,并且用上式计算B0。如果几次估算的结果相差不多,则可用B0的平均值作为ET的估计值。此后一名测试员可以改做其他工作,由余下的一名测试员继续完成测试工作,因为他可以继承另一名测试员的测试结果,所以分别测试法增加的测试成本并不太多 2019/4/21

202 思考题 在测试一个长度为48000条指令的程序时,第一个月由甲、乙两名测试员各自独立测试这个程序。经过一个月测试后,甲发现并改正了20个错误,使MTTF达到8h。与此同时,乙发现24个错误,其中的6个错误甲也发现了。以后由甲一个人继续测试这个程序。问: (1)刚开始测试时,程序总过有多少个潜藏的错误? (2)为使MTTF达到240h,必须再改正多少个错误? 2019/4/21

203 思考题参考答案 (1)本题采用了分别测试法 (2)根据公式 即,甲还需要再测试出58个错误,才能使MTTF为240h 2019/4/21


Download ppt "梁文新 办公室:综合楼108 电 话: 87571625 wxliang@dlut.edu.cn 软件工程导论 梁文新 办公室:综合楼108 电 话: 87571625 wxliang@dlut.edu.cn."

Similar presentations


Ads by Google