软 件 工 程.

Slides:



Advertisements
Similar presentations
第五节 函数的微分 一、微分的定义 二、微分的几何意义 三、基本初等函数的微分公式与微分运算 法则 四、微分形式不变性 五、微分在近似计算中的应用 六、小结.
Advertisements

练一练: 在数轴上画出表示下列各数的点, 并指出这些点相互间的关系: -6 , 6 , -3 , 3 , -1.5, 1.5.
证券投资技术分析.
第 5 章 软 件 测 试 5.1 软件测试概述 5.2 测试方法 5.3 测试用例的设计 5.4 测试过程 5.5 调试
常用逻辑用语复习课 李娟.
第7章 实现 7.1 编码 7.2 软件测试基础 7.3 单元测试 7.4 集成测试 7.5 确认测试 7.6 白盒测试技术
第3章 软件工程基础.
基于解释性语言的手机跨平台架构 Sloan Yi. Qt MTK.
Oracle数据库 Oracle 子程序.
§5 微分及其应用 一、微分的概念 实例:正方形金属薄片受热后面积的改变量..
§5 微分及其应用 一、微分的概念 实例:正方形金属薄片受热后面积的改变量..
全国计算机等级考试 二级基础知识 第二章 程序设计基础.
在PHP和MYSQL中实现完美的中文显示
程序的形式验证 - 简介 中国科学院软件研究所 张文辉 1.
学习前的准备工作 讲师:burning.
SOA – Experiment 3: Web Services Composition Challenge
走进编程 程序的顺序结构(二).
辅导课程六.
网络常用常用命令 课件制作人:谢希仁.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
数 控 技 术 华中科技大学机械科学与工程学院.
Windows网络操作系统管理 ——Windows Server 2008 R2.
第十章 IDL访问数据库 10.1 数据库与数据库访问 1、数据库 数据库中数据的组织由低到高分为四级:字段、记录、表、数据库四种。
课程设计.
第二章 Java语言基础.
化学品清单 类型.
单元测试工具XUnit 任课老师:黄武 下午2时20分 25.
第六章 编码与测试.
第12章 系统实施.
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
宁波市高校慕课联盟课程 与 进行交互 Linux 系统管理.
宁波市高校慕课联盟课程 与 进行交互 Linux 系统管理.
程序设计工具实习 Software Program Tool
内容摘要 ■ 课程概述 ■ 教学安排 ■ 什么是操作系统? ■ 为什么学习操作系统? ■ 如何学习操作系统? ■ 操作系统实例
C语言程序设计 主讲教师:陆幼利.
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
顺序表的删除.
VisComposer 2019/4/17.
WPT MRC. WPT MRC 由题目引出的几个问题 1.做MRC-WPT的多了,与其他文章的区别是什么? 2.Charging Control的手段是什么? 3.Power Reigon是什么东西?
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年11月13日.
工业机器人知识要点解析 (ABB机器人) 主讲人:王老师
用计算器开方.
成绩是怎么算出来的? 16级第一学期半期考试成绩 班级 姓名 语文 数学 英语 政治 历史 地理 物理 化学 生物 总分 1 张三1 115
第4章 Excel电子表格制作软件 4.4 函数(一).
Harvard ManageMentor®
8 [学习目标] 了解管理信息系统的物理实施过程;掌握程序设计的任务和方法,能根据实际需要选择恰当的程序语言进行程序设计;掌握 MIS 的系统测试、切换、运行及维护等的方法与内涵;掌握项目管理与系统评价的方法与内涵。 [学习重点] 系统测试方法、系统切换方式.
定理21.9(可满足性定理)设A是P(Y)的协调子集,则存在P(Y)的解释域U和项解释,使得赋值函数v(A){1}。
iSIGHT 基本培训 使用 Excel的栅栏问题
用穷举法设计程序 南京师范大学 教育技术系 倪佳慧
§6.7 子空间的直和 一、直和的定义 二、直和的判定 三、多个子空间的直和.
3.16 枚举算法及其程序实现 ——数组的作用.
第4课时 绝对值.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
魏新宇 MATLAB/Simulink 与控制系统仿真 魏新宇
1.非线性规划模型 2.非线性规划的Matlab形式
敏捷开发下 问题驱动的软件测试设计 郑文强 测试架构师 阿尔卡特-朗讯.
GIS基本功能 数据存储 与管理 数据采集 数据处理 与编辑 空间查询 空间查询 GIS能做什么? 与分析 叠加分析 缓冲区分析 网络分析
第二节 C语言的特点.
第六章 Excel的应用 五、EXCEL的数据库功能 1、Excel的数据库及其结构 2、Excel下的数据排序 (1)Excel的字段名行
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
第四章 UNIX文件系统.
第十七讲 密码执行(1).
FVX1100介绍 法视特(上海)图像科技有限公司 施 俊.
《偏微分方程》第一章 绪论 第一章 绪论 1.1.
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
任课教师:戴开宇 TA:时均帅、谭肖、王安华 程序设计B班 :20-16:50(90分钟)
实验六、COM类型病毒分析实验 实验开发教师: 刘乃琦 谌黔燕.
质量控制(QC)模式 BrookFIELD.
§2 自由代数 定义19.7:设X是集合,G是一个T-代数,为X到G的函数,若对每个T-代数A和X到A的函数,都存在唯一的G到A的同态映射,使得=,则称G(更严格的说是(G,))是生成集X上的自由T-代数。X中的元素称为生成元。 A变, 变 变, 也变 对给定的 和A,是唯一的.
Presentation transcript:

软 件 工 程

第7章 编码+测试=实现 7.1 编码 7.2 软件测试基础 7.3 单元测试 7.4 集成测试 7.5 确认测试 7.6 白盒测试技术 第7章 编码+测试=实现 7.1 编码 7.2 软件测试基础 7.3 单元测试 7.4 集成测试 7.5 确认测试 7.6 白盒测试技术 7.7 黑盒测试技术 7.8 调试

重要性: 通常把编码和测试统称为实现。 编码是对设计的进一步具体化,因此,程序的质量主要取决于软件设计的质量。 所选用的程序设计语言的特点及编码风格也将对程序的可靠性、可读性、可测试性和可维护性产生深远的影响。

程序设计方法与技术 算法 + 数据结构 = 程序 + 经验 + 技巧

§7.1 编码 §7.1.1 选择程序设计语言 注重需求和实现,离不开技术 广泛的行业知识 编程经验与技巧 用户至上 §7.1 编码 §7.1.1 选择程序设计语言 注重需求和实现,离不开技术 广泛的行业知识 编程经验与技巧 用户至上 虽然好的程序设计语言有助于写出可靠而又容易维护的程序。但是,事在人为,工具再好,使用不当也不会达到预期的效果。按照软件工程方法论,程序是软件设计的自然结果,程序的质量基本上取决于设计的质量。此外,编写程序的途径和编程经验也很大程度上决定着程序的质量。

选择语言的主要标准: (1) 系统用户的要求。如果所开发的系统由用户负责维护,用户通常要求用他们熟悉的语言书写程序。 (2) 可以得到的软件工具。如果某种语言有支持程序开发的软件工具可以利用,则目标系统的实现和验证都变得比较容易。 (3) 工程规模。如果工程规模很庞大,现有的语言又不完全适用,那么设计并实现一种供这个工程项目专用的程序设计语言,可能是一个正确的选择。

(4) 程序员的知识。选择一种程序员所熟悉的语言。 (5) 软件可移植性要求。 (6) 软件的应用领域。所谓的通用程序设计语言实际上并不是对所有应用领域都同样适用。因此,选择语言时应该充分考虑目标系统的应用范围。

§7.1.2 编码风格 源代码的逻辑简明清晰、易读易懂是好程序的一个重要标准,为了做到这一点,应该遵循下述规则。 §7.1.2 编码风格 源代码的逻辑简明清晰、易读易懂是好程序的一个重要标准,为了做到这一点,应该遵循下述规则。 程序内部文档——包括恰当的标识符,适当的注解和程序的视觉组织等等。 1.标识符:选取含义鲜明的名字,使它能正确地提示程序对象所代表的实体,缩写和命名规则应一致; 2.注解:是程序员和程序读者通信的重要手段,正确的注解非常有助于对程序的理解; 3.视觉组织:程序清单的布局对于程序的可读性有很大影响,应该利用适当的阶梯形式是程序的层次结构清晰明显。

程序注解示例 // Set toolbar visible status if iw_window.toolbarvisible then cb_visible.text = "&Hide" else cb_visible.text = "&Show" end if // Set toolbar text mode status cbx_showtext.checked = iapp_application.toolbartext // Set toolbar tips mode status cbx_showtips.checked = iapp_application.toolbartips

程序布局示例 锯齿状布局,结构清晰明了 IF This.AcceptText()<0 then return 1 end if if this.getcolumn()=Long(This.Describe("datawindow.column.count")) then if this.getrow()=This.RowCount() then this.insertrow(0) this.scrolltorow(this.getrow()+1) this.setcolumn(1) send(handle(this),256,9,long(0,0)) 锯齿状布局,结构清晰明了

数据说明——对所用到的数据结构中的数据元素进行说明。 语句构造: 1.不要为了节省空间而把多条语句写在同一行; 2.尽量避免复杂的条件测试; 3.尽量减少对“非”条件的测试; 4.避免大量使用循环嵌套和条件嵌套; 5.利用括号使逻辑表达式或算术表达式的运算次序清晰直观; 效率——少用全局变量、多用局部变量或使用传递参数。

合格的程序员 团队精神和协作能力 文档习惯 规范化,标准化的代码编写习惯 需求理解能力 复用性,模块化思维能力 测试习惯 学习和总结的能力

§7.2 软件测试基础 软件产品最大的成本是检测软件错误、修正软件错误的成本。 §7.2 软件测试基础 软件产品最大的成本是检测软件错误、修正软件错误的成本。 在整个软件开发中,测试工作量一般占30%~40%,甚至≥50%。 在测试阶段测试人员设计出的一系列测试方案,是为了“破坏”已经建造好的软件系统——竭力证明程序中有错误。

软件是人编的—所以不完美 例:•Windows95有1000万行代码 Exchange2000和Windows2000开发人员结构 Exchange2000 Windows2000 项目经理 25人 约250人 开发人员 140人 约1700人 测试人员 350人 约3200人

眼见为实 难以说清的软件缺陷 “如果软件中的问题没有人发现,那么它算不算软件缺陷?” 古谚: “一片树叶飘落在森林中没有人听见, 谁能说它发出了声音?” 由于不能报告没有看见的问题,因此,没有看见就不能说存在软件缺陷 眼见为实

§7.2.1 软件测试的目标 (1)预防错误: 几乎不可实现 (2)尽力发现错误 【定义】:为寻找错误而运行程序的过程。 §7.2.1 软件测试的目标 【定义】:为寻找错误而运行程序的过程。 【测试目的】是发现程序中的错误,是为了证明程序有错, 而不是证明程序无错。 【成功的测试标准】:能够发现错误的测试是成功的测试,否则是失败的测试。 【测试的目标】: (1)预防错误: 几乎不可实现 (2)尽力发现错误

§7.2.2 软件测试准则 为了能设计出有效的测试方案,软件工程师必须遵循以下测试准则: (1)所有的测试都应追溯到用户需求 §7.2.2 软件测试准则 为了能设计出有效的测试方案,软件工程师必须遵循以下测试准则: (1)所有的测试都应追溯到用户需求 最严重的错误(从用户角度)是那些导致软件无法满足需求的错误。

(2)概要设计时应完成测试计划,详细的测试用例定义可在设计模型确定后开始,所有测试可在任何代码被产生之前进行计划和设计。 (3)软件测试不等于程序测试 软件测试应贯穿于软件定义与开发的整个期间;据美国一家公司统计,查出的软件错误中,属于需求分析和软件设计的错误约占64%,属于程序编写的错误仅占 36%。程序编写的许多错误是“先天的”。

(4)应由独立的第三方测试机构来构造测试。 (5)测试用例应由输入数据和预期的输出结果两部分组成。 (6)兼顾合理的输入和不合理的输入数据。 (7)程序修改后要回归测试。 (8)应长期保留测试用例,直至系统废弃。

§7.2.3 测试方法 测试任何产品都有两种方法: 【黑盒法】:如果已经知道了产品应该具有的功能,可以通过测试来检验是否每个功能都能正常使用;只关心软件功能是否正确与完善; 【白盒法】:如果知道产品的内部工作过程,可以通过测试来检验产品内部动作是否按照规格说明书的规定正常进行。只关心软件内部逻辑实现是否正确无误。

§7.2.4 测试步骤

§7.2.5 测试阶段的信息流 (1)软件配置,包括需求说明书、设计说明书和源程序清单等; (2)测试配置,包括测试计划和测试方案。 §7.2.5 测试阶段的信息流 (1)软件配置,包括需求说明书、设计说明书和源程序清单等; (2)测试配置,包括测试计划和测试方案。 测试方案不仅仅是测试时使用的输入数据(称为测试用例),还应该包括每组输入数据预定要检验的功能,以及每组输入数据预期应该得到的正确输出。

§7.3 单元测试 【定义】:单元测试集中检测软件设计的最小单元——模块。单元测试和编码属于软件过程的同一个阶段。 §7.3 单元测试 【定义】:单元测试集中检测软件设计的最小单元——模块。单元测试和编码属于软件过程的同一个阶段。 【采用的测试方法】:主要使用白盒测试技术,而且对多个模块的测试可以并行地进行。

§7.3.1 测试重点 着重从下述5个方面对模块进行测试: 1. 模块接口 §7.3.1 测试重点 着重从下述5个方面对模块进行测试: 1. 模块接口 首先应该对通过模块接口的数据流进行测试,如果数据不能正确地进出,所有其他测试都是不切实际的。 测试内容:参数的数目、次序、属性或单位系统与变元是否一致;是否修改了只作输入用的变元;全局变量的定义和用法在各个模块中是否一致。

2. 局部数据结构 对于模块来说,局部数据结构是常见的错误来源。应该仔细设计测试方案,以便发现局部数据说明、初始化、默认值等方面的错误。 3. 重要的执行通路 由于通常不可能进行穷尽测试,因此,在单元测试期间选择最有代表性、最可能发现错误的执行通路进行测试就是十分关键的。

注意:每个执行步骤都要执行到,否则测试不全面。 4. 出错处理通路 好的设计应该能预见出现错误的条件,并且设置适当的处理错误的通路,以便在真的出现错误时执行相应的出错处理通路或干净地结束处理。 注意:每个执行步骤都要执行到,否则测试不全面。

5. 边界条件 边界测试是单元测试中最后的也可能是最重要的任务,软件常常在它的边界上失效,例如,处理n元数组的第n个元素时,或做到i次循环中的第i次重复时,往往会发生错误。使用刚好小于、刚好等于和刚好大于最大值或最小值的数据结构、控制量和数据值的测试方案,非常可能发现软件中的错误。 非常典型的案例为:C语言数组溢出可能会造成计算机死机。

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

§7.3.3 计算机测试 模块并不是一个独立的程序,因此必须为每个单元测试开发驱动软件和(或)存根软件。 §7.3.3 计算机测试 模块并不是一个独立的程序,因此必须为每个单元测试开发驱动软件和(或)存根软件。 通常驱动程序也就是一个“主程序”,它接收测试数据,把这些数据传送给被测试的模块,并且印出有关的结果。 存根程序代替被测试的模块所调用的模块。因此存根程序也可以称为“虚拟子程序”。

图7.2 正文加工系统的层次图

驱动程序和存根程序代表开销,也就是说,为了进行单元测试必须编写测试软件——只是测试用。 模块的内聚程度高可以简化单元测试过程。如果每个模块只完成一种功能,则需要的测试方案数目将明显减少,模块中的错误也更容易预测和发现。

§7.4 集成测试 在单元测试的基础上,需要将所有模块按照设计要求组装成为系统。这时需要考虑的问题是: §7.4 集成测试 【定义】:是测试和组装软件的系统化技术,也称为组装测试或联合测试。 在单元测试的基础上,需要将所有模块按照设计要求组装成为系统。这时需要考虑的问题是: 在把各个模块连接起来的时侯,穿越模块接口的数据是否会丢失; 一个模块的功能是否会对另一个模块的功能产生不利的影响;

各个子功能组合起来,能否达到预期要求的父功能; 全局数据结构是否有问题; 单个模块的误差累积起来,是否会放大,从而达到不能接受的程度。 在单元测试的同时可进行组装测试,发现并排除在模块连接中可能出现的问题,最终构成要求的软件系统。

由模块组装成程序系统的方法: 【非渐增式测试】:先分别测试每个模块,再把所有模块按设计要求放在一起结合成所要的程序。 【渐增式测试】:把下一个要测试的模块同已经测试好的那些模块结合起来进行测试,测试完以后再把下一个应该测试的模块结合进来测试。这种方法实际上同时完成单元测试和集成测试。当使用渐增方式把模块结合到程序中去时,有自顶向下和自底向上两种集成策略。

§7.4.1 自顶向下集成 自顶向下集成方法是一个日益为人们广泛采用的测试和组装软件的途径。从主控制模块开始,沿着程序的控制层次向下移动,逐渐把各个模块结合起来。在把附属于(及最终附属于)主控制模块的那些模块组装到程序结构中去时,或者使用深度优先的策略,或者使用宽度优先的策略。

自顶向下结合 深度优先的结合方法先组装在软件结构的一条主控制通路上的所有模块。选择一条主控制通路取决于应用的特点,并且有很大任意性。 宽度优先的结合方法是沿软件结构水平地移动,把处于同一个控制层次上的所有模块组装起来。 自顶向下结合

§7.4.2 自底向上集成 自底向上测试从“原子”模块(即在软件结构最低层的模块)开始组装和测试。因为是从底部向上结合模块,总能得到所需的下层模块处理功能,所以不需要存根程序。 实现自底向上的结合策略: 第一步,把低层模块组合成实现某个特定的软件子功能的族;

第二步,写一个驱动程序(用于测试的控制程序),协调测试数据的输入和输出; 第三步,对由模块组成的子功能族进行测试; 第四步,去掉驱动程序,沿软件结构自下向上移动,把子功能族组合起来形成更大的子功能族。

§7.4.3 不同集成测试策略的比较 自顶向下测试的方式和自底向上测试的方式各有优缺点。 §7.4.3 不同集成测试策略的比较 自顶向下测试的方式和自底向上测试的方式各有优缺点。 在测试实际的软件系统时,应该根据软件的特点以及工程进度安排,选用适当的测试策略。纯粹自顶向下或纯粹自底向上的策略可能都不实用,在实践中不要生搬硬套,要灵活应用——混合策略:

(1) 改进的自顶向下测试方法。 首先对输入/输出模块和引入新算法模块进行测试; 再自底向上组装成为功能相当完整且相对独立的子系统; 然后由主模块开始自顶向下进行测试。

(2) 混合法——自底向上与自顶向下的方法混合。 对软件结构中较上层使用的自顶向下方法 对软件结构中较下层使用的自底向上方法

§7.4.4 回归测试 为什么要进行回归测试?每当一个新模块加入到系统中时,程序就发生了变化:建立了新的数据流路径,可能出现了新的I/O操作,激活了新的控制逻辑——可能使原来工作正常的系统功能出现问题。 【定义】:是指重新执行已经做过的测试的某个子集,以保证上述这些变化没有带来非预期的副作用。

§7.5 确认测试 什么是软件的有效性?如果软件的功能和性能和用户所要求一致,软件就是有效的。 §7.5 确认测试 确认测试也称为验收测试,它的目标是验证软件的有效性——主要依据软件需求规格说明书。 验证(verification):指的是保证软件正确地实现了某个特定要求的一系列活动。 确认(validation):指的是为了保证软件确实满足了用户需求而进行的一系列活动。 什么是软件的有效性?如果软件的功能和性能和用户所要求一致,软件就是有效的。

测试方法采用的是黑盒法

§7.5.1 确认测试的范围 确认测试必须有用户积极参与,或者以用户为主进行,软件开发人员和QA(质量保证)人员也应参加。 §7.5.1 确认测试的范围 确认测试必须有用户积极参与,或者以用户为主进行,软件开发人员和QA(质量保证)人员也应参加。 由用户参加设计测试用例,使用生产中的实际数据进行测试。 在测试过程中,除了考虑软件的功能和性能外,还应对软件的可移植性、兼容性、可维护性、错误的恢复功能等进行确认。

(1) 功能和性能与用户要求一致,软件是可以接受的; (2) 功能和性能与用户要求有差距。 确认测试有下述两种可能的结果: (1) 功能和性能与用户要求一致,软件是可以接受的; (2) 功能和性能与用户要求有差距。 发现的问题往往和需求分析阶段的差错有关。为了制定解决确认测试过程中发现的软件缺陷或错误的策略,通常需要和用户充分协商。 确认测试应交付的文档有: 确认测试分析报告 最终的用户手册和操作手册 项目开发总结报告。

§7.5.2 软件配置复查 确认测试的一个重要内容是复查软件配置。【复查的目的】:是保证软件配置的所有成分都齐全,质量符合要求,文档与程序完全一致,具有完成软件维护所必须的细节。 【复查的过程】:应当严格遵守用户手册和操作手册中规定的使用步骤,以便检查这些文档资料的完整性和正确性。

§7.5.3 Alpha和Beta测试 在软件交付使用之后,用户将如何实际使用程序,对于开发者来说是无法预测的,原因如下: 如果软件是专为某个客户开发的,可以进行一系列验收测试,以便用户确认所有需求都得到满足了。验收测试是由最终用户而不是系统的开发者进行的。 如果一个软件是为许多客户开发的(例如,向大众公开出售的盒装软件产品),那么,让每个客户都进行正式的验收测试是不现实的。

Alpha测试和Beta测试的引入,可以发现那些看起来只有最终用户才能发现的错误。 【Alpha测试】:由用户在开发者的场所进行,并且在开发者对用户的“指导”下进行测试。开发者负责记录发现的错误和使用中遇到的问题。总之,Alpha测试是在受控的环境中进行的。也可以是公司内部的用户在模拟实际操作环境下进行的测试。

【Beta测试】:由软件的最终用户在用户现场进行,开发者通常不在Beta测试的现场,因此,Beta测试是软件在开发者不能控制的环境中的“真实”应用。

α测试的目的是评价软件产品的FLURPS(即功能、局域化、可使用性、可靠性、性能和支持)。尤其注重产品的界面和特色。

§7.6 白盒测试技术 设计测试方案以及测试用例的准备:所谓测试方案包括具体的测试目的(例如,预定要测试的具体功能),应该输入的测试数据和预期的结果。通常又把测试数据和预期的输出结果称为测试用例。其中最困难的问题是设计测试用的输入数据。 不同的测试数据发现程序错误的能力差别很大,为了提高测试效率降低测试成本,应该选用高效的测试数据。因为不可能进行穷尽的测试,选用少量“最有效的”测试数据,做到尽可能完备的测试就更重要了。

软件人员使用白盒测试方法,主要想对程序模块进行如下的检查: 对程序模块的所有独立的执行路径至少测试一次; 对所有的逻辑判定,取“真”与取“假”的两种情况都至少测试一次; 在循环的边界和运行界限内执行循环体; 测试内部数据结构的有效性,等。

对一个具有多重选择和循环嵌套的程序,不同的路径数目可能是天文数字。 例如:一个执行20次的循环的小程序。包含的不同执行路径数达520条,对每一条路径进行测试需要1毫秒,假定一年工作365 × 24小时,要想把所有路径测试完,需3170年。

§7.6.1 逻辑覆盖 【定义】:逻辑覆盖是以程序内部的逻辑结构为基础的设计测试用例的技术。它属白盒测试。 语句覆盖 判定覆盖 条件覆盖 §7.6.1 逻辑覆盖 【定义】:逻辑覆盖是以程序内部的逻辑结构为基础的设计测试用例的技术。它属白盒测试。 语句覆盖 判定覆盖 条件覆盖 判定-条件覆盖 条件组合覆盖 点覆盖 边覆盖 路径覆盖。

1. 语句覆盖 【定义】:设计若干个测试用例,运行被测程序,使得每一可执行语句至少执行一次。 例如:在图7.5所示的程序流程图为了使每个语句都执行一次,程序的执行路径应该是sacbed,为此只需要输入下面的测试数据(实际上X可以是任意实数):A=2,B=0,X=4

图7.5 被测试模块的流程图

L1 ( a  c  e ) = {(A>1) and (B=0)} and {(A=2) or (X/A>1)} = (A>1) and (B=0) and (A=2) or (A>1) and (B=0) and (X/A>1) = (A=2) and (B=0) or

L2 ( a b  d ) = not{(A>1) and (B=0)} and not{(A=2) or (X>1)} = { not (A>1) or not (B=0) } and { not (A=2) and not (X>1) } = not (A>1) and not (A=2) and not (X>1) or not (B=0) and not (A=2) and not (X>1)

L3 ( a b e) = not {(A>1) and (B=0)} and {(A=2) or (X>1)} = { not (A>1) or not (B=0)} and = not (A>1) and (A=2) or not (A>1) and (X>1) or not (B=0) and (A=2) or not (B=0) and (X>1)

L4 ( a c  d ) = {(A>1) and (B=0)} and not {(A=2) or (X/A>1)} = (A>1) and (B=0) and not (A=2) and not (X/A>1)

(A>1) and (B=0) and (X/A>1) 测试用例的设计格式如下 【输入的(A, B, X),输出的(A, B, X)】 为图例设计满足语句覆盖的测试用例是: 【(2, 0, 4),(2, 0, 3)】  覆盖 ace【L1】 (A=2) and (B=0) or (A>1) and (B=0) and (X/A>1)

语句覆盖的缺点: 语句覆盖对程序的逻辑覆盖很少。此外,语句覆盖只关心判定表达式的值,而没有分别测试判定表达式中每个条件取不同值时的情况。 综上所述,可以看出语句覆盖是很弱的逻辑覆盖标准,为了更充分地测试程序,可以采用下述的逻辑覆盖标准。

2. 判定覆盖 【定义】:又叫分支覆盖。不仅每个语句必须至少执行一次,而且每个判定的每种可能的结果都应该至少执行一次,也就是每个判定的每个分支都至少执行一次。 判定覆盖比语句覆盖强,但是对程序逻辑的覆盖程度仍然不高,例如,上面的测试数据只覆盖了程序全部路径的一半。

条件覆盖通常比判定覆盖强,因为它使判定表达式中每个条件都取到了两个不同的结果,判定覆盖却只关心整个判定表达式的值。 3. 条件覆盖 【定义】:不仅每个语句至少执行一次,而且使判定表达式中的每个条件都取到各种可能的结果。 条件覆盖通常比判定覆盖强,因为它使判定表达式中每个条件都取到了两个不同的结果,判定覆盖却只关心整个判定表达式的值。

既然判定覆盖不一定包含条件覆盖,条件覆盖也不一定包含判定覆盖,自然会提出一种能同时满足这两种覆盖标准的逻辑覆盖,这就是判定/条件覆盖。 4. 判定/条件覆盖 既然判定覆盖不一定包含条件覆盖,条件覆盖也不一定包含判定覆盖,自然会提出一种能同时满足这两种覆盖标准的逻辑覆盖,这就是判定/条件覆盖。 【定义】:选取足够多的测试数据,使得判定表达式中的每个条件都取到各种可能的值,而且每个判定表达式也都取到各种可能的结果。 有时判定/条件覆盖也并不比条件覆盖更强。

5. 条件组合覆盖 条件组合覆盖是更强的逻辑覆盖标准。 【定义】:它要求选取足够多的测试数据,使得每个判定表达式中条件的各种可能组合都至少出现一次。 满足条件组合覆盖标准的测试数据,也一定满足判定覆盖、条件覆盖和判定/条件覆盖标准。因此,条件组合覆盖是前述几种覆盖标准中最强的。注意的是:满足条件组合覆盖标准的测试数据并不一定能使程序中的每条路径都执行到。

6. 点覆盖——等同语句覆盖 满足点覆盖标准要求选取足够多的测试数据,使得程序执行路径至少经过流图的每个结点一次。 7. 边覆盖——等同判定覆盖 为了满足边覆盖的测试标准,要求选取足够多测试数据,使得程序执行路径至少经过流图中每条边一次。

8. 路径覆盖 【定义】:选取足够多测试数据,覆盖程序中所有可能的路径。即使程序的每条可能路径都至少执行一次(如果程序图中有环,则要求每个环至少经过一次)。

§7.6.2 控制结构测试 1. 基本路径测试 也是一种白盒测试技术。使用这种技术设计测试用例时: 计算程序的环形复杂度; §7.6.2 控制结构测试 1. 基本路径测试 也是一种白盒测试技术。使用这种技术设计测试用例时: 计算程序的环形复杂度; 定义执行路径的基本集合; 从该基本集合导出的测试用例可以保证程序中的每条语句至少执行一次,而且每个条件在执行时都将分别取真、假两种值。

要识别判定结点 求平均值过程的流图

使用基本路径测试法设计测试用例时,程序的环形复杂度决定了程序中独立路径的数量,而且这个数是确保程序中所有语句至少被执行一次所需的测试数量的上界。 对于上图所描述的求平均值过程来说,由于环形复杂度为6,因此共有6条独立路径。

2. 条件测试 尽管基本路径测试技术简单而且高效,但是仅有这种技术还不够,还需要使用其他控制结构测试技术,才能进一步提高白盒测试的质量。 用条件测试技术设计出的测试用例,能够检查程序模块中包含的逻辑条件。 条件测试方法着重测试程序中的每个条件。

条件测试的目的不仅是检测程序条件中的错误,而且是检测程序中的其他错误。 当程序中判定多于一个时,形成的分支结构可以分为两类:嵌套型分支结构和连锁型分支结构。 对于嵌套型分支结构,若有n个判定语句,需要n+1个测试用例; 对于连锁型分支结构, 若有n个判定语句,需要有2n个测试用例,覆盖它的2n条路径。

3. 循环测试 循环测试是一种白盒测试技术,它专注于测试循环结构的有效性。在结构化的程序中通常只有3种循环,即简单循环、串接(连锁)循环和嵌套循环,如下图所示。

3种循环

§7.7 黑盒测试技术 黑盒测试着重测试软件功能,也可以叫做数据驱动测试法。黑盒测试并不能取代白盒测试,它是与白盒测试互补的测试方法,它很可能发现白盒测试不易发现的其他类型的错误。 黑盒测试力图发现下述类型的错误: ①功能不正确或遗漏了功能; ②界面错误; ③数据结构错误或外部数据库访问错误; ④性能错误; ⑤初始化和终止错误。

白盒测试在测试过程的早期阶段进行,而黑盒测试主要用于测试过程的后期。设计黑盒测试方案时,应该考虑下述问题: (1) 怎样测试功能的有效性? (2) 哪些类型的输入可构成好测试用例? (3) 系统是否对特定的输入值特别敏感? (4) 怎样划定数据类的边界? (5) 系统能够承受什么样的数据率和数据量? (6) 数据的特定组合将对系统运行产生什么影响?

黑盒法——测试用例设计方法 等价类划分 边界值分析 错误推测法

§7.7.1 等价划分 等价类划分是一种典型的黑盒测试方法,使用这一方法时,完全不考虑程序的内部结构,只依据程序的规格说明来设计测试用例。 §7.7.1 等价划分 等价类划分是一种典型的黑盒测试方法,使用这一方法时,完全不考虑程序的内部结构,只依据程序的规格说明来设计测试用例。 等价类划分方法把所有可能的输入数据,即程序的输入域划分成若干部分,然后从每一部分中选取少数有代表性的数据做为测试用例。 使用这一方法设计测试用例要经历划分等价类(列出等价类表)和选取测试用例两步。

等价类的划分有两种不同的情况: ① 有效等价类:是指对于程序的规格说明来说,是合理的,有意义的输入数据构成的集合。 ② 无效等价类:是指对于程序的规格说明来说,是不合理的,无意义的输入数据构成的集合。 在设计测试用例时,要同时考虑有效等价类和无效等价类的设计。

例如,在程序的规格说明中,对输入条件有一句话: “…… 项数可以从1到999 ……” 则有效等价类是“1≤项数≤999” 两个无效等价类是“项数<1”或“项 数>999”。在数轴上表示成:

§7.7.2 边界值分析 人们从长期的测试工作经验得知,大量的错误是发生在输入或输出范围的边界上,而不是在输入范围的内部,处理边界情况时程序最容易发生错误。 例如:许多程序错误出现在下标、纯量、数据结构和循环等等的边界附近。 因此,设计使程序运行在边界情况附近的测试方案,暴露出程序错误的可能性更大一些。

使用边界值分析方法设计测试用例,首先应确定边界情况。应当选取正好等于,刚刚大于,或刚刚小于边界的值做为测试数据,而不是选取等价类中的典型值或任意值做为测试数据。 通常设计测试方案时总是联合使用等价划分和边界值分析两种技术。

§7.7.3 错误推测 人们也可以靠经验和直觉推测程序中可能存在的各种错误,从而有针对性地编写检查这些错误的例子——错误推测法。 §7.7.3 错误推测 人们也可以靠经验和直觉推测程序中可能存在的各种错误,从而有针对性地编写检查这些错误的例子——错误推测法。 错误推测法的基本想法是:列举出程序中所有可能有的错误和容易发生错误的特殊情况,根据它们选择测试用例。

§7.8 调试 调试是通过现象,找出原因的一个思维分析的过程。 §7.8 调试 调试(也称为纠错)作为成功测试的后果出现,也就是说,调试是在测试发现错误之后排除错误的过程。 调试仍然是一项技巧性工作。 调试是通过现象,找出原因的一个思维分析的过程。

§7.8.1 调试过程 调试 执行案例 结果 测试用例 附加 测试 回归测试 被怀疑 错误现场 改正 已识别 的原因 §7.8.1 调试过程 调试不是测试,但是它总是发生在测试之后。如图7.8所示: 错误现场 结果 执行案例 改正 测试用例 调试 已识别 的原因 被怀疑 回归测试 附加 测试

调试过程总会有以下两种结果之一: ①找到了问题的原因并把问题改正和排除掉了; ②没找出问题的原因。 调试是软件开发过程中最艰巨的脑力劳动。查找软件错误特征的难度在于下述内容: (1) 症状和产生症状的原因可能在程序中相距甚远。紧耦合的程序结构更加剧了这种情况。 (2) 当改正了另一个错误之后,症状可能暂时消失了。 (3) 症状可能实际上并不是由错误引起的(例如,舍入误差)。

(4) 症状可能是由不易跟踪的人为错误引起的。 (5) 症状可能是由定时问题而不是由处理问题引起的。 (6) 可能很难重新产生完全一样的输入条件(例如,输入顺序不确定的实时应用系统)。 (7) 症状可能时有时无,这种情况在硬件和软件紧密地耦合在一起的嵌入式系统中特别常见。 (8) 症状可能是由分布在许多任务中的原因引起的,这些任务运行在不同的处理机上。

§7.8.2 调试途径 通过内存全部打印来调试,在大量的数据中寻找出错的位置。 §7.8.2 调试途径 无论采用什么方法,调试的目标都是寻找软件错误的原因并改正错误。调试的关键在于推断程序内部的错误位置及原因。可以采用以下方法: 1、蛮干法(强行排错) 目前使用较多,效率较低。它不需要过多的思考,比较省脑筋。例如: 通过内存全部打印来调试,在大量的数据中寻找出错的位置。

在程序特定部位设置打印语句,把打印语句插在出错的源程序的各个关键变量改变部位、重要分支部位、子程序调用部位,跟踪程序的执行,监视重要变量的变化。 自动调试工具。利用某些程序语言的调试功能或专门的交互式调试工具,分析程序的动态过程,而不必修改程序。

2. 回溯法 回溯是一种相当常用的调试方法,当调试小程序时这种方法是有效的。 具体做法是,从发现症状的地方开始,人工沿程序的控制流往回追踪分析源程序代码,直到找出错误原因为止。但是,随着程序规模扩大,应该回溯的路径数目也变得越来越大,以至彻底回溯变成完全不可能了。

对分查找法、归纳法和演绎法都属于原因排除法。 3. 原因排除法 对分查找法、归纳法和演绎法都属于原因排除法。 对分查找法:如果已经知道每个变量在程序内若干个关键点的正确值,则可以用赋值语句或输入语句在程序中点附近“注入”这些变量的正确值,然后运行程序并检查所得到的输出。如果输出结果是正确的,则错误原因在程序的前半部分;反之,错误原因在程序的后半部分。

归纳法是从个别现象推断出一般性结论的思维方法。使用这种方法调试程序时,首先把和错误有关的数据组织起来进行分析,以便发现可能的错误原因。然后导出对错误原因的一个或多个假设,并利用已有的数据来证明或排除这些假设。

演绎法从一般原理或前提出发,经过排除和精化的过程推导出结论。 采用这种方法调试程序时,首先设想出所有可能的出错原因,然后试图用测试来排除每一个假设的原因。如果测试表明某个假设的原因可能是真的原因,则对数据进行细化以准确定位错误。

小结 实现包括编码和测试两个阶段。 程序的质量基本上取决于设计的质量。编码使用的语言,程序的布局风格,对程序质量也有相当大的影响。 程序内部的良好文档资料,有规律的数据说明格式,简单清晰的语句构造和输入输出格式等等,可以提高程序的可读性、改进程序的可维护性。

软件测试是保证软件可靠性的主要手段。测试阶段的根本任务是发现并改正软件中的错误。 大型软件的测试应该分阶段地进行,通常至少分为单元测试、集成测试和验收测试3个基本阶段。 程序中潜藏的错误的数目,直接决定了软件的可靠性。通过测试可以估算出程序中剩余的错误数。

测试与调试(排错) 发现错误 找出错误位置,排除 有计划 被动的 以已知条件开始, 使用预先定义的程序, 有预知的结果 测试 (test) 调试 (debug) 发现错误 找出错误位置,排除 有计划 被动的 以已知条件开始, 使用预先定义的程序, 有预知的结果 以不可知内部条件开始,结果一般不可预见 由独立的测试组,在不了解软件设计的条件下完成 由程序作者进行

黑盒测试与白盒测试优缺点比较 黑盒测试 白盒测试 优 点 缺 点 性 质 ①适用于各阶段测试 ②从产品功能角度测试 ③容易入手生成测试数据 黑盒测试 白盒测试 ①适用于各阶段测试 ②从产品功能角度测试 ③容易入手生成测试数据 ①可构成测试数据使特定程 序部分得到测试 ②有一定的充分性度量手段 ③可或较多工具支持 优 点 ①不易生成测试数据(通常) ②无法对未实现规格说明的 部分进行测试 ③工作量大,通常只用于单 元测试,有应用局限 ①某些代码得不到测试 ②如果规格说明有误, 则无法发现 ③不易进行充分性测试 缺 点 性 质 是一种确认技术,回答 “我们在构造一个正确 的系统吗?” 是一种验证技术,回答 “我们在正确地构造一个系 统吗?”

习题 P168 掌握熟练【实例7-2】 P171 一、二、三.(9)