870 likes | 1.06k Views
第 7 章 实现. 7.1 编码 7.2 软件测试基础 7.3 单元测试 7.4 集成测试 7.5 确认测试 7.6 白盒测试技术 7.7 黑盒测试技术 7.8 调试 7.9 软件可靠性. 7.1 编码. 这一阶段主要工作是什么呢?. 在这个阶段的任务是 : 把软件设计的结果翻译成计算机可以 “ 理解 ” 的形式 ----- 用计算机语言表示的程序。. 7.1 编码. 程序设计语言 : 人与计算机通信的基本工具,指挥计算机按人的意志工作。
E N D
第7章 实现 7.1 编码 7.2 软件测试基础 7.3 单元测试 7.4 集成测试 7.5 确认测试 7.6 白盒测试技术 7.7 黑盒测试技术 7.8 调试 7.9 软件可靠性
7.1 编码 这一阶段主要工作是什么呢? 在这个阶段的任务是: 把软件设计的结果翻译成计算机可以“理解”的形式 -----用计算机语言表示的程序。
7.1 编码 • 程序设计语言:人与计算机通信的基本工具,指挥计算机按人的意志工作。 • 1946—1954: 机器语言和汇编语言,与计算机硬件操作一一对应。 • 1954: 第一个高级语言 FORTRAN 语言。 • 高级语言的种类: • 基 础 语 言----Fortran, Basic,Cobol,Algol • 结构化语 言----Pl/1, Pascal, C, Ada • 专 用 语 言----特殊应用如 LISP, Prolog.
选择程序设计语言的原则 • 系统用户的要求 • 可以使用的编译程序 • 可以使用的软件工具 • 工程规模 • 程序员的知识 • 软件可移植要求 • 软件的应用领域
2.程序设计途径 • 写程序的风格 • 程序内部的文档----恰当的意义明确的标识符,注解,程序的视觉组织(语句布局). • 数据说明----次序标准化,归类化. • 语句构造----每个语句的构造应该简单、直接和易于理解。 • 一般不要为了节省纸张多个语句写在一行; • 避免复杂的条件测试; 减少对“非”条件的测试; • 避免大量使用循环嵌套和条件嵌套; • 利用括号使逻辑表达式或算术表达式的运算次序清晰直观。 • 输入/输出---- • 效率----程序运行时间、存储器效率、输入和输出的效率 。
程序设计途径 • 程序设计方法论 • 程序设计自动化----三种途径(用户需求形式化精确定义,组件技术,范型) • 程序设计工具---- 编译程序 代码管理系统
7.2 测 试 • 基本概念 • 软件测试的目标或定义(G.Myers): • 1)测试是为了发现程序中的错误而执行程序的过程。 • 2)好的测试方案是极可能发现迄今为止尚未发现的错误的测试方案。 • 3)成功的测试是发现了至今为止尚未发现的错误的测试。
7.2.2 软件测试准则 • 所有测试都应该能追溯到用户需求。 • 应该远在测试开始之前就制定出测试计划。 • 把Pareto原理应用到软件测试中。 • 应该从“小规模”测试开始,并逐步进行“大规模”测试。 • 穷举测试是不可能的。 • 为了达到最佳的测试效果,应该由独立的第三方从事测试工作。
黑盒测试和白盒测试 • 黑盒测试:已经知道了软件产品应该具有的功能,通过测试来检验是否每个功能都能正常使用。这种测试方法又称功能测试。 • 白盒测试:知道软件产品内部的工作过程,通过测试来检验产品内部动作是否按照规格说明书的规定正常进行。这种测试方法又称结构测试。
例二:白盒测试 循环20次 各种组合,约520种 • 注意:不论是每个功能或每个逻辑控制通路,如果对所有的情况都进行测试,这样的测试称为穷尽测试。穷尽测试在一般情况下是实际不可行的。 例一、Sum(int a, int b, int c) { return (a+b+c); } 假定 int 类型为16位整数, 需要测试216* 216* 216次。 每次1ms, 约要1万年
软件测试的步骤 • 集成测试、组装测试、联合测试; • 重点在于测试模块之间的接口; 模块测试 子系统测试 目的:保证每个模块作为一个单元能够正确运行,又称为单元测试 系统测试 • 有用户参加的系统测试; • 验证是否满足用户的需要。 • 将经过测试的子系统装配成一个完整的系统来测试; • 发现设计和编码的错误,验证系统是否满足需求说明所定义的功能及其动态特性; • 也称为集成测试。 验收测试 平行运行 同时运行新旧两个系统,并且对处理的结果进行比较,以确定新系统是否满足相关性能指标。
正确 调试 包括需求说明书、设计说明书、源程序清单等 错误 软件配置 评价 测试结果 测试 可靠性预测 可靠性 模型 错误率数据 预期结果 测试配置 包括测试计划和测试方案 • 测试阶段的信息流:
测试与软件开发各个阶段的关系 • 软件开发过程是一个自顶向下,逐步细化的过程 • 软件计划阶段定义软件作用域 • 软件需求分析建立软件信息域、功能和性能需求、约束等 • 软件设计 • 把设计用某种程序设计语言转换成程序代码 • 测试过程是依相反顺序安排的自底向上,逐步集成的过程。
7.2 基本概念(3) 测试与软件开发各个阶段的关系 (示意图)
7.3 单元测试(1) • 单元测试又称模块测试,是针对软件设计的最小单位 ─ 程序模块,进行正确性检验的测试工作。其目的在于发现各模块内部可能存在的各种差错。 • 单元测试需要从程序的内部结构出发设计测试用例。多个模块可以平行地独立进行单元测试。 1. 单元测试的内容 • 模块接口 • 局部数据结构 • 重要的执行通路 • 出错处理通路 • 影响上述各方面特性 • 的边界条件 • 在单元测试时,测试者需要依据详细设计说明书和源程序清单,了解该模块的I/O条件和模块的逻辑结构,主要采用白盒测试的测试用例,辅之以黑盒测试的测试用例,使之对任何合理的输入和不合理的输入,都能鉴别和响应。
(1) 模块接口测试 • 在单元测试的开始,应对通过被测模块的数据流进行测试。测试项目包括: • 调用本模块的输入参数是否正确; • 本模块调用子模块时输入给子模块的参数是否正确; • 是否修改了只作输入用的变元 • 全局量的定义在各模块中是否一致;
7.3 单元测试(2) • 在做内外存交换时要考虑: • 文件属性是否正确; • OPEN与CLOSE语句是否正确; • 缓冲区容量与记录长度是否匹配; • 在进行读写操作之前是否打开了文件; • 在结束文件处理时是否关闭了文件; • 正文书写/输入错误, • I/O错误是否检查并做了处理。
(2) 局部数据结构测试 • 不正确或不一致的数据类型说明 • 使用尚未赋值或尚未初始化的变量 • 错误的初始值或错误的缺省值 • 变量名拼写错或书写错 • 不一致的数据类型 • 全局数据对模块的影响
(3) 路径测试 • 选择适当的测试用例,对模块中重要的执行路径进行测试。 • 应当设计测试用例查找由于错误的计算、不正确的比较或不正常的控制流而导致的错误。 • 对基本执行路径和循环进行测试可以发现大量的路径错误.
(4) 错误处理测试 • 出错的描述是否难以理解 • 记下的错误是否与实际遇到的错误相同 • 对错误条件的处理正确与否 • 在对错误进行处理之前,错误条件是否已经引起系统的干预等 • 描述错误的信息不足以帮助确定造成错 误的位置
(5) 边界测试 • 注意数据流、控制流中刚好等于、大于或小于确定的比较值时出错的可能性。对这些地方要仔细地选择测试用例,认真加以测试。 • 如果对模块运行时间有要求的话,还要专门进行关键路径测试,以确定最坏情况下和平均意义下影响模块运行时间的因素
7.3 单元测试(3) 2. 单元测试方法 • 代码审查:组长+程序设计、编写、测试者 • 计算机测试:模块并不是一个独立的程序,在考虑测试模块时,同时要考虑它和外界的联系,用一些辅助模块去模拟与被测模块相联系的其它模块。 • 驱动模块 (driver) :调用测试单元的“主程序”,它接受测试数据,把这些数据传送给被测试的模块并打印有关结果。 • 桩模块 (stub) ── 存根模块:是被测试模块单元所调用模块的代替模块,在模块调用接口、相关数据处理、控制返回等方面对被代替模块进行“模拟”。
单元测试的测试环境 测试用例 测试结果 驱动模块 被测模块 桩模块 桩模块 桩模块
Ⅰ. TEST STUB(*测试正文编辑模块用的存根程序*) 初始化; 输出信息“进入了正文编辑程序”; 输出“输入的控制信息是”CFUNCT; 输出缓冲区中的字符串; IF CFUNCT=CHANGE THEN 把缓冲区中第二个字改为*** ELSE 在缓冲区的尾部加??? END IF; 输出缓冲区中的新字符串; END TEST STUB
Ⅱ. TEST DRIVER(*测试正文编辑模块用的驱动程序*) 说明长度为2500个字符的一个缓冲区; 把CFUNCT置为希望测试的状态; 输入字符串; 调用正文编辑模块; 停止或再次初启; END TEST DRIVER
7.4 集成测试(1) • 集成测试是组装软件的系统技术;组装测试 、联合测试 • 通常,在单元测试的基础上,需要将所有模块按照设计要求组装成为系统。这时需要考虑的问题是: • 在把各个模块连接起来的时侯,穿越模块接口的数据是否会丢失; • 一个模块的功能是否会对另一个模块的功能产生不利的影响; • 各个子功能组合起来,能否达到预期要求的父功能; • 全局数据结构是否有问题; • 单个模块的误差累积起来,是否会放大,从而达到不能接受的程度。
在单元测试的同时可进行组装测试,发现并排除在模块连接中可能出现的问题,最终构成要求的软件系统。在单元测试的同时可进行组装测试,发现并排除在模块连接中可能出现的问题,最终构成要求的软件系统。 • 子系统的组装测试特别称为部件测试,它所做的工作是要找出组装后的子系统与系统需求规格说明之间的不一致。 • 通常,把模块组装成为系统的方式有两种 • 一次性组装方式:又称为非渐增式测试; • 增殖式组装方式:其中又分为自顶向下、自底向上和两种方法混合测试方式。
7.4 集成测试(2) 1.一次性组装方式(big bang) 整体组装 • 它是一种非增殖式组装方式。也叫做整体拼装。 • 使用这种方式,首先对每个模块分别进行模块测试,然后再把所有模块组装在一起进行测试,最终得到要求的软件系统。 单元测试 系 统结构图
7.4 集成测试(3) 2. 增殖式组装方式 • 这种组装方式又称渐增式组装 • 首先对一个个模块进行模块测试,然后将这些模块逐步组装成较大的系统 • 在组装的过程中边连接边测试,以发现连接过程中产生的问题 • 通过增殖逐步组装成为要求的软件系统。
(1) 自顶向下的增殖方式 • 这种组装方式将模块按系统程序结构,沿控制层次自顶向下进行组装。 • 自顶向下的增殖方式在测试过程中较早地验证了主要的控制和判断点。 • 选用按深度方向组装的方式,可以首先实现和验证一个完整的软件功能。
(2) 自底向上的增殖方式 • 这种组装的方式是从程序模块结构的最底层的模块开始组装和测试。 • 因为模块是自底向上进行组装,对于一个给定层次的模块,它的子模块(包括子模块的所有下属模块)已经组装并测试完成,所以不再需要桩模块。在模块的测试过程中需要从子模块得到的信息可以直接运行子模块得到。 • 自顶向下增殖的方式和自底向上增殖的方式各有优缺点。 • 一般来讲,一种方式的优点是另一种方式的缺点。
7.4 集成测试 • 非渐增式和渐增式测试方法的优缺点比较: • 非渐增式方法要对每个模块编写驱动模块和桩模块,工作量较大;而渐增式方法可以利用部分已测试过的模块作为测试软件; • 非渐增式方法发现模块间的接口错误较晚,而渐增式方法则要早一些; • 非渐增式方法发现错误后较难定位;而渐增式方法则要容易一些; • 非渐增式方法可以并行测试所有模块,可充分利用人力,加快工程进度; • 渐增式方法接近全真运行环境,需要较多的测试运行时间,但对程序模块的测试较为彻底。
7.5 确认测试 —验证软件的有效性 • 软件的有效性:如果软件的功能和性能满足用户的需求,则软件是有效的; • 软件有效性的标准:需求分析阶段所产生的准确的系统需求文档; • 测试方法:一般用黑盒方法; • 结果:功能和性能均与用户要求一致,软件是可以接受的;否则软件是不可接受的。 • Alpha和Beta测试
语句覆盖 判定覆盖 条件覆盖 判定-条件覆盖 条件组合覆盖 路径覆盖。 7.6 白盒测试 测试方案:包括预定要测试的功能,应该输入的测试数据和预期的结果。其中最困难的 设计测试用的输入数据。 测试用例设计技术:黑盒测试的等价划分、边界值分析、错误推测法; 白盒测试的逻辑覆盖法; 1. 逻辑覆盖 逻辑覆盖是以程序内部的逻辑结构为基础的设计测试用例的技术。它属白盒测试。
PROCEDURE Example(A,B:real; X:real ); Begin IF (A>1) AND (B=0) THEN X:= X / A; IF ( A=2 ) OR (X>1) THEN X:=X+1 END; 语句覆盖 S 1 a T 4 (A>1)and(B=0) c F X = X / A 2 5 b I. A=2, B= 0, X=4 ---- sacbed (A=2)or(X>1) T 6 e F X=X+1 3 语句覆盖 所有的语句至少执行一次! 7 d
判定覆盖 判定覆盖 每个判定的每种可能都至少执行一次! 即每个判定的每个分支都至少执行一次! S 1 a T 4 (A>1)and(B=0) c F X = X / A 2 I: A=3, B=0,X=3: sacbd 5 b II: A=2, B=1,X=1: sabed (A=2)or(X>1) T 6 e F X=X+1 满足判定覆盖的测试用例一定满足语句覆盖:判定覆盖比语句覆盖强。 3 7 d
条件覆盖 每个语句至少执行一次,而且判定表达式中的每个条件都要取得各种可能的结果。 条件覆盖 S 1 a T 4 (A>1) (A≤1) (A>1)and(B=0) c (B=0) (B≠0) F X = X / A 2 5 (A=2) (A≠2) b (X>1) (X≤1) (A=2)or(X>1) T 6 e I: A=2, B=0,X=4: sacbed F X=X+1 7 3 II: A=1, B=1,X=1: sabd d I: A=2, B=0,X=1: sacbed 条件覆盖一般情况下比判定覆盖要强,但是也有满足条件覆盖但不能满足判定覆盖的情况。 II: A=1, B=1,X=2: sabed
判定覆盖不一定包含条件覆盖,条件覆盖也不一定包含判定覆盖;事实上同时满足这两种标准的判定/条件覆盖也不会比条件覆盖更强。判定覆盖不一定包含条件覆盖,条件覆盖也不一定包含判定覆盖;事实上同时满足这两种标准的判定/条件覆盖也不会比条件覆盖更强。 判定/条件覆盖 S 1 a (A>1) (A≤1) T 4 (A>1)and(B=0) c (B=0) (B≠0) F X = X / A 2 (A=2) (A≠2) 5 b (X>1) (X≤1) (A=2)or(X>1) T 6 e I: A=2, B=0,X=4: sacbed F X=X+1 7 II: A=1, B=1,X=1: sabd 3 d 测试用例I,II既满足判定覆盖也满足条件覆盖的要求。严格来讲,合适的条件覆盖测试用例设计应该作到满足判定/条件覆盖的标准:判定/条件覆盖并不比条件覆盖更强。
条件组合覆盖要求选取足够多的测试数据,使得每个判定表达式中条件的各种可能组合都至少出现一次。条件组合覆盖要求选取足够多的测试数据,使得每个判定表达式中条件的各种可能组合都至少出现一次。 条件组合覆盖 S 1 a (A>1) (B=0) I. A=2,B=0,X=4 T 4 (A>1)and(B=0) (A≤1) (B≠0) II. A=2,B=1,X=1 F X = X / A 2 覆盖路径 I: sacbed II: sabed III: sabed IV: sabd 5 (A=2) (X>1) b (A=2)or(X>1) T (A≠2) (X≤1) 6 F X=X+1 III. A=1,B=0,X=2 7 3 IV. A=1,B=1,X=1 d 满足条件组合覆盖标准的测试数据,也一定满足判定覆盖、条件覆盖和判定/条件覆盖标准。
点覆盖: • 如果连通图 G 的子图G´是连通的,而且包含G的所有节点,则称G´是G的点覆盖。 • 与语句覆盖标准相同。 • 边覆盖: • 如果连通图 G 的子图G´是连通的,而且包含G的所有边,则称G´是G的边覆盖。 • 通常与判定覆盖标准相同。
1 4 2 5 6 3 (A>1)and(B=0) 7 • 路径覆盖: • 选取足够多的测试数据,使程序的每条 • 可能路径都至少执行一次(如果程序图 • 中有环,则要求每个环至少经过一次)。 • 路径覆盖是较强的逻辑覆盖标准。 I: A=1,B=1,X=1 (1-2-3) ; II: A=1,B=1,X=2 (1-2-6-7) III: A=3,B=0,X=1 (1-4-5-3); IV: A=2,B=0,X=4 (1-4-5-6-7) (A=2)or(X>1)
控制结构测试 1.基本路径测试 • 其主要思想是根据软件详细设计的过程性描述或源代码中的控制流程求出程序的环形复杂性度量,然后用此度量确定程序的基本路径集合,并由此导出一组测试用例来覆盖该集合中的每一个独立的路径,从而可以保证每个语句至少执行一次。
【例】试用基本路径测试法对如下的PDL描述成如图1所示的程序流程图设计测试用例。该例子描述了最多输入50个值(以–1作为输入结束标志),计算其中有效的学生分数的个数、总分数和平均值。【例】试用基本路径测试法对如下的PDL描述成如图1所示的程序流程图设计测试用例。该例子描述了最多输入50个值(以–1作为输入结束标志),计算其中有效的学生分数的个数、总分数和平均值。
PROCEDURE average INTERFACE RETURNS average,sum,n1;*n1为有效成绩的个数。* INTERFACE ACCEPTS score; TYPE score[1,50] IS SCALAR ARRAY; TYPE average,n1,n2,sum IS SCALAR;*n2为输入值的个数。* TYPE i IS INTEGER; i = 1;n1=n2=0;sum=0; DO WHILE (score[ i ]<> – 1)AND(n2<50) n2 加 1; IF (score[ i ]>=0)AND(score[ i ]<=100) THEN n1 加 1; sum = sum + score[ i ]; END IF; i 加 1; END DO; IF n1> 0 THEN average = sum/n1; ELSE average = – 1; END IF; END average
开始 1 i =1,n1=n2=0,sum=0 2和3 F Score[ i ]<>-1 AND n2<50 4 T n2=n2+1 5和6 F Score[ i ]>0 AND score[i]<100 7 T n1=n1+1,sum=sum+score[i] 8 i = i +1 9 F T n1>0 11 10 average= – 1 average=sum/n1 12 返回 图1 过程average的程序流程图
1 2 R4 9 3 4 R5 11 10 R3 5 12 6 R1 R6 R2 7 8 【例】 解:可按如下步骤设计测试用例: 步骤1:根据详细设计或代码导出过程average的流图。
【例】 步骤2:据流图确定环形复杂性度量V(G): 1)V(G)=E – N +2 = 16 – 12 + 2 = 6 ; 其中E为流图中的边数,N为结点数; 2)V(G)= 6 (个区域); 3)V(G)= P + 1 = 5 + 1 = 6 ; 其中P为判定结点的个数。在流图中,结点2、3、5、6、9是判定结点。