软件工程导论第五版课件第7章.docx
- 文档编号:7371404
- 上传时间:2023-01-23
- 格式:DOCX
- 页数:22
- 大小:91.30KB
软件工程导论第五版课件第7章.docx
《软件工程导论第五版课件第7章.docx》由会员分享,可在线阅读,更多相关《软件工程导论第五版课件第7章.docx(22页珍藏版)》请在冰豆网上搜索。
软件工程导论第五版课件第7章
第7章实现
一、复习要求
1.了解编程风格4个方面的要求。
2.了解软件测试的概念、目的和原则。
3.了解软件测试的方法
4.了解软件测试的过程和策略。
5.了解软件测试用例设计的方法,掌握逻辑覆盖、基本路径测试测试用例设计方法以及等价类测试用例的设计方法。
6.了解程序调试的概念。
二、内容提要
1.编程风格
在软件生存期中,人们经常要阅读程序。
特别是在软件测试阶段和维护阶段,编写程序
的人与参与测试、维护的人都要阅读程序。
因此,阅读程序是软件开发和维护过程中的
一个重要组成部分,而且读程序的时间比写程序的时间还要多。
70年代初,有人提出在
编写程序时,应使程序具有良好的风格。
程序设计风格包括4个方面:
源程序文档化,数据说明,语句结构和输入/输出方法,
力图从编码原则的角度提高程序的可读性,改善程序质量。
(1)源程序文档化
①符号名的命名
②程序的注释
序言性注释:
通常置于每个程序模块的开头部分,它应当给出程序的整体说明,对
于理解程序本身具有引导作用。
有些软件开发部门对序言性注释做了明确而严格的规
定,要求程序编制者逐项列出的有关项目包括:
程序标题、有关本模块功能和目的的说
明、主要算法、接口说明、有关数据描述、模块位置、开发简历等。
功能性注释:
嵌在源程序体中,用以描述其后的语句或程序段是在做什么工作,不
要解释下面怎么做,因为解释怎么做常常是与程序本身重复的,并且对于阅读者理解程
序没有什么帮助。
书写功能性注释,要注意:
·用于描述一段程序,而不是每一个语句;·用缩进和空行,
使程序与注释容易区别;·注释要正确。
③视觉组织
利用空格、空行和移行,提高程序的可视化程度。
恰当地利用空格,可以突出运算的优先性,避免发生运算的错误。
自然的程序段之间可用空行隔开;
对于选择语句和循环语句,把其中的程序段语句向右做阶梯式移行。
这样可使程序的
逻辑结构更加清晰,层次更加分明。
(2)数据说明
在编写程序时,需注意数据说明的风格。
为了使程序中数据说明更易于理解和维护,必
须注意以下几点。
数据说明的次序应当规范化,使数据属性容易查找。
当多个变量名用一个语句说明时,应当对这些变量按字母的顺序排列。
如果设计了一个复杂的数据结构,应当使用注释来说明在程序实现时这个数据结构的
固有特点。
(3)语句结构
在设计阶段确定了软件的逻辑流结构,但构造单个语句则是编码阶段的任务。
语句构造
力求简单,直接,不能为了片面追求效率而使语句复杂化。
此外,对于程序中的变量,标号,注释等,还需要给予一些注意。
(4)输入和输出(I/O)
输入和输出信息是与用户的使用直接相关的。
输入和输出的方式和格式应当尽可能方便
用户的使用。
因此,在软件需求分析阶段和设计阶段,就应基本确定输入和输出的风格。
系统能否被用户接受,有时就取决于输入和输出的风格。
2.测试的概念、目的和原则
(1)什么是软件测试
软件测试是为了发现错误而执行程序的过程。
或者说,软件测试是根据软件开发各阶段
的规格说明和程序的内部结构而精心设计一批测试用例(即输入数据及其预期的输出结
果),并利用这些测试用例去运行程序,以发现程序错误的过程。
软件测试在软件生存期中横跨两个阶段:
通常在编写出每一个模块之后就对它做必要的
测试(称为单元测试)。
模块的编写者与测试者是同一个人。
编码与单元测试属于软件
生存期中的同一个阶段。
在这个阶段结束之后,对软件系统还要进行各种综合测试,这
是软件生存期的另一个独立的阶段,即测试阶段,通常由专门的测试人员承担这项工作。
(2)软件测试的目的和原则
软件测试目的:
测试是程序的执行过程,目的在于发现错误;
一个好的测试用例在于能发现至今未发现的错误;
一个成功的测试是发现了至今未发现的错误的测试。
设计测试的目标是想以最少的时间和人力系统地找出软件中潜在的各种错误和缺陷。
如
果我们成功地实施了测试,就能够发现软件中的错误。
测试的附带收获是,它能够证明
软件的功能和性能与需求说明相符合。
测试不能表明软件中不存在错误,它只能说明软
件中存在错误。
软件测试的原则:
①应当把“尽早地和不断地进行软件测试”作为软件开发者的座右铭。
不应把软件测试仅仅看作是软件开发的一个独立阶段,而应当把它贯穿到软件开发的各
个阶段中。
坚持在软件开发的各个阶段的技术评审,这样才能在开发过程中尽早发现和
预防错误,把出现的错误克服在早期,杜绝某些发生错误的隐患。
②测试用例应由测试输入数据和与之对应的预期输出结果这两部分组成。
测试以前应当根据测试的要求选择测试用例(Testcase),用来检验程序员编制的程序,
因此不但需要测试的输入数据,而且需要针对这些输入数据的预期输出结果。
③程序员应避免检查自己的程序。
程序员应尽可能避免测试自己编写的程序,程序开发小组也应尽可能避免测试本小组开
发的程序。
如果条件允许,最好建立独立的软件测试小组或测试机构。
这点不能与程序
的调试(debuging)相混淆。
调试由程序员自己来做可能更有效。
④在设计测试用例时,应当包括合理的输入条件和不合理的输入条件。
合理的输入条件是指能验证程序正确的输入条件,不合理的输入条件是指异常的,临界
的,可能引起问题异变的输入条件。
软件系统处理非法命令的能力必须在测试时受到检
验。
用不合理的输入条件测试程序时,往往比用合理的输入条件进行测试能发现更多的
错误。
⑤充分注意测试中的群集现象。
在被测程序段中,若发现错误数目多,则残存错误数目也比较多。
这种错误群集性现象,
已为许多程序的测试实践所证实。
根据这个规律,应当对错误群集的程序段进行重点测
试,以提高测试投资的效益。
⑥严格执行测试计划,排除测试的随意性。
测试之前应仔细考虑测试的项目,对每一项测试做出周密的计划,包括被测程序的功能、
输入和输出、测试内容、进度安排、资源要求、测试用例的选择、测试的控制方式和过
程等,还要包括系统的组装方式、跟踪规程、调试规程,回归测试的规定,以及评价标
准等。
对于测试计划,要明确规定,不要随意解释。
⑦应当对每一个测试结果做全面检查。
有些错误的征兆在输出实测结果时已经明显地出现了,但是如果不仔细地全面地检查测
试结果,就会使这些错误被遗漏掉。
所以必须对预期的输出结果明确定义,对实测的结
果仔细分析检查,抓住征侯,暴露错误。
⑧妥善保存测试计划,测试用例,出错统计和最终分析报告,为维护提供方便。
3、测试方法概述
软件测试的种类大致可以分为人工测试和基于计算机的测试。
而基于计算机的测试由可
以分为白盒测试和黑盒测试。
①黑盒测试
根据软件产品的功能设计规格,在计算机上进行测试,以证实每个实现了的功能是否符
合要求。
这种测试方法就是黑盒测试。
黑盒测试意味着测试要在软件的接口处进行。
就
是说,这种方法是把测试对象看做一个黑盒子,测试人员完全不考虑程序内部的逻辑结
构和内部特性,只依据程序的需求分析规格说明,检查程序的功能是否符合它的功能说
明。
用黑盒测试发现程序中的错误,必须在所有可能的输入条件和输出条件中确定测试数
据,来检查程序是否都能产生正确的输出。
②白盒测试
根据软件产品的内部工作过程,在计算机上进行测试,以证实每种内部操作是否符合设
计规格要求,所有内部成分是否已经过检查。
这种测试方法就是白盒测试。
白盒测试把
测试对象看做一个打开的盒子,允许测试人员利用程序内部的逻辑结构及有关信息,设
计或选择测试用例,对程序所有逻辑路径进行测试。
通过在不同点检查程序的状态,确
定实际的状态是否与预期的状态一致。
不论是黑盒测试,还是白盒测试,都不可能把所有可能的输入数据都拿来进行所谓的穷
举测试。
因为可能的测试输入数据数目往往达到天文数字
4.软件测试的过程与策略
(1)测试与软件开发各阶段的关系
软件开发过程是一个自顶向下,逐步细化的过程,而测试过程则是依相反的顺序安排的
自底向上,逐步集成的过程。
低一级测试为上一级测试准备条件。
参看下图,首先对每
一个程序模块进行单元测试,消除程序模块内部在逻辑上和功能上的错误和缺陷。
再对
照软件设计进行集成测试,检测和排除子系统(或系统)结构上的错误。
随后再对照需
求,进行确认测试。
最后从系统全体出发,运行系统,看是否满足要求。
图软件测试与软件开发过程的关系
测试过程见下图:
图软件测试的过程
(2)单元测试
单元测试针对程序模块,进行正确性检验的测试。
其目的在于发现各模块内部可能存在
的各种差错。
单元测试需要从程序的内部结构出发设计测试用例。
多个模块可以平行地
独立进行单元测试。
1单元测试的内容
模块接口测试:
对通过被测模块的数据流进行测试。
为此,对模块接口,包括参数
表、调用子模块的参数、全程数据、文件输入/输出操作都必须检查。
局部数据结构测试:
设计测试用例检查数据类型说明、初始化、缺省值等方面的问
题,还要查清全程数据对模块的影响。
路径测试:
选择适当的测试用例,对模块中重要的执行路径进行测试。
对基本执行
路径和循环进行测试可以发现大量的路径错误。
错误处理测试:
检查模块的错误处理功能是否包含有错误或缺陷。
例如,是否拒绝
不合理的输入;出错的描述是否难以理解、是否对错误定位有误、是否出错原因报告有
误、是否对错误条件的处理不正确;在对错误处理之前错误条件是否已经引起系统的干
预等。
边界测试:
要特别注意数据流、控制流中刚好等于、大于或小于确定的比较值时出
错的可能性。
对这些地方要仔细地选择测试用例,认真加以测试。
②单元测试的步骤
通常单元测试在编码阶段进行。
在源程序代码编制完成,经过评审和验证,确认没有语
法错误之后,就开始进行单元测试的测试用例设计。
利用设计文档,设计可以验证程序
功能、找出程序错误的多个测试用例。
对于每一组输入,应有预期的正确结果。
(2)集成测试
在单元测试的基础上,需要将所有模块按照设计要求组装成为系统。
这时需要考虑:
在把各个模块连接起来的时侯,穿越模块接口的数据是否会丢失;
一个模块的功能是否会对另一个模块的功能产生不利的影响;
各个子功能组合起来,能否达到预期要求的父功能;
全局数据结构是否有问题;
单个模块的误差累积起来,是否会放大,从而达到不能接受的程度。
单个模块的错误是否会导致数据库错误。
选择什么方式把模块组装起来形成一个可运行的系统,直接影响到模块测试用例的形
式、所用测试工具的类型、模块编号的次序和测试的次序、以及生成测试用例的费用和
调试的费用。
通常,把模块组装成为系统的方式有两种方式:
①一次性集成方式
它是一种非渐增式集成方式。
也叫做整体拼装。
使用这种方式,首先对每个模块分别进
行模块测试,然后再把所有模块组装在一起进行测试,最终得到要求的软件系统。
由于程序中不可避免地存在涉及模块间接口、全局数据结构等方面的问题,所以一次试
运行成功的可能性并不很大。
②渐增式集成方式
首先对一个个模块进行模块测试,然后将这些模块逐步组装成较大的系统,在组装的过
程中边连接边测试,以发现连接过程中产生的问题。
最后通过增殖逐步组装成为要求的
软件系统。
自顶向下的集成方式:
将模块按系统程序结构,沿控制层次自顶向下进行集成。
由于
这种集成方式在测试过程中较早地验证了主要的控制和判断点。
在一个功能划分合理的
程序结构中,判断常出现在较高的层次,较早就能遇到。
如果主要控制有问题,尽早发
现它能够减少以后的返工。
自底向上的集成方式:
从程序结构的最底层模块开始组装和测试。
因为模块是自底向
上进行组装,对于一个给定层次的模块,它的子模块(包括子模块的所有下属模块)已
经组装并测试完成,所以不再需要桩模块。
在模块的测试过程中需要从子模块得到的信
息可以直接运行子模块得到。
③混合集成测试:
是把以上两种方式结合起来进行集成测试。
衍变的自顶向下的增殖测试:
它的基本思想是强化对输入/输出模块和引入新算法模块的测试,并自底向上组装成为功能相当完整且相对独立的子系统,然后由主模块开始自顶向下进行增殖测试。
自底向上-自顶向下的增殖测试:
它首先对含读操作的子系统自底向上直至根结点模块进行组装和测试,然后对含写操作的子系统做自顶向下的组装与测试。
自底向上-自顶向下的增殖测试:
它首先对含读操作的子系统自底向上直至根结点模块进行组装和测试,然后对含写操作的子系统做自顶向下的组装与测试。
回归测试:
这种方式采取自顶向下的方式测试被修改的模块及其子模块,然后将这一部分视为子系统,再自底向上测试,以检查该子系统与其上级模块的接口是否适配。
自顶向下集成方式与自底向上集成方式的比较
自顶向下集成的方式和自底向上集成的方式各有优缺点。
自顶向下集成方式的缺点是需
要建立桩模块。
要使桩模块能够模拟实际子模块的功能将是十分困难的。
同时涉及复杂
算法和真正输入/输出的模块一般在底层,它们是最容易出问题的模块,到组装和测试
的后期才遇到这些模块,一旦发现问题,导致过多的回归测试。
而自顶向下集成方式的
优点是能够较早地发现在主要控制方面的问题。
自底向上集成方式的缺点是“程序一直
未能做为一个实体存在,直到最后一个模块加上去后才形成一个实体”。
就是说,在自底
向上组装和测试的过程中,对主要的控制直到最后才接触到。
但这种方式的优点是不需
要桩模块,而建立驱动模块一般比建立桩模块容易,同时由于涉及到复杂算法和真正输
入/输出的模块最先得到组装和测试,可以把最容易出问题的部分在早期解决。
此外自
底向上集成的方式可以实施多个模块的并行测试。
(3)确认测试
确认测试又称有效性测试。
它的任务是验证软件的有效性,即验证软件的功能和性能及
其它特性是否与用户的要求一致。
在软件需求规格说明书描述了全部用户可见的软件属
性,其中有一节叫做有效性准则,它包含的信息就是软件确认测试的基础。
在确认测试阶段需要做的工作如下图所示。
首先要进行有效性测试以及软件配置复审,然后进行验收测试和安装测试,在通过了专家鉴定之后,才能成为可交付的软件。
图确认测试的步骤
5.测试用例设计
(1)逻辑覆盖
逻辑覆盖是以程序内部的逻辑结构为基础的设计测试用例的技术。
属白盒测试。
这一方
法要求测试人员对程序的逻辑结构有清楚的了解,甚至要能掌握源程序的所有细节。
由
于覆盖测试的目标不同,逻辑覆盖又可分为:
语句覆盖、判定覆盖、判定-条件覆盖、
条件组合覆盖及路径覆盖。
①语句覆盖:
语句覆盖就是设计若干个测试用例,运行被测程序,使得每一可执行语
句至少执行一次。
这种覆盖又称为点覆盖,它使得程序中每个可执行语句都得到执行,
但它是最弱的逻辑覆盖准,效果有限,必须与其它方法交互使用。
②判定覆盖:
判定覆盖就是设计若干个测试用例,运行被测程序,使得程序中每个判
断的取真分支和取假分支至少经历一次。
判定覆盖又称为分支覆盖。
判定覆盖只比语句覆盖稍强一些,但实际效果表明,只是判定覆盖,还不能保证一定能
查出在判断的条件中存在的错误。
因此,还需要更强的逻辑覆盖准则去检验判断内部条
件。
③条件覆盖:
条件覆盖就是设计若干个测试用例,运行被测程序,使得程序中每个判
断的每个条件的可能取值至少执行一次。
条件覆盖深入到判定中的每个条件,但可能不能满足判定覆盖的要求。
④判定-条件覆盖:
判定-条件覆盖就是设计足够的测试用例,使得判断中每个条件
的所有可能取值至少执行一次,同时每个判断本身的所有可能判断结果至少执行一次。
换言之,即是要求各个判断的所有可能的条件取值组合至少执行一次。
⑤条件组合覆盖:
多重条件覆盖就是设计足够的测试用例,运行被测程序,使得每个
判断的所有可能的条件取值组合至少执行一次。
这是一种相当强的覆盖准则,可以有效地检查各种可能的条件取值的组合是否正确。
它不但可覆盖所有条件的可能取值的组合,还可覆盖所有判断的可取分支,但可能有的路径会遗漏掉。
测试还不完全。
⑥路径测试:
路径测试就是设计足够的测试用例,覆盖程序中所有可能的路径。
这是
最强的覆盖准则。
但在路径数目很大时,真正做到完全覆盖是很困难的,必须把覆盖路
径数目压缩到一定限度。
(2)基本路径测试:
如果把覆盖的路径数压缩到一定限度内,例如,程序中的循环体只
执行零次和一次,就成为基本路径测试。
它是在程序控制流图的基础上,通过分析控制构造的环路复杂性,导出基本可执行路径集合,从而设计测试用例的方法。
①程序的控制流图
②计算程序环路复杂性
进行程序的基本路径测试时,程序的环路复杂性给出了程序基本路径集合中的独立路径条数,这是确保程序中每个可执行语句至少执行一次所必需的测试用例数目的上界。
所谓独立路径,是指包括一组以前没有处理的语句或条件的一条路径。
如下图所示的控制流图中,一组独立的路径是
path1:
1-11
path2:
1-2-3-4-5-10-1-11
path3:
1-2-3-6-8-9-10-1-11
path4:
1-2-3-6-7-9-10-1-11
基本路径集不是唯一的,对于给定的控制流图,可以得到不同的基本路径集。
(a)程序流程图(b)控制流图
图程序流程图与对应的控制流图
通常环路复杂性可用以下三种方法求得。
将环路复杂性定义为控制流图中的区域数。
设E为控制流图的边数,N为图的结点数,则定义环路复杂性为V(G)=E-N+2。
若设P为控制流图中的判定结点数,则有V(G)=P+1。
因为图5.14(b)所示控制流图有4个区域。
其环路复杂性为4。
它是构成基本路径集的独立路径数的上界。
可以据此得到应该设计的测试用例的数目。
③导出测试用例
利用逻辑覆盖方法生成测试用例,确保基本路径集中每条路径的执行。
(3)等价类划分
等价类划分是一种典型的黑盒测试方法。
使用这一方法时,完全不考虑程序的内部结构,只依据程序的规格说明来设计测试用例。
由于不可能用所有可以输入的数据来测试程序,而只能从全部可供输入的数据中选择一个子集进行测试。
如何选择适当的子集,使其尽可能多地发现错误。
解决的办法之一就是等价类划分。
等价类的划分有两种不同的情况:
有效等价类:
是指对于程序规格说明来说,是合理的,有意义的输入数据构成的集合。
利用它,可以检验程序是否实现了规格说明预先规定的功能和性能。
无效等价类:
是指对于程序规格说明来说,是不合理的,无意义的输入数据构成的集合。
利用它,可以检查程序中功能和性能的实现是否有不符合规格说明要求的地方。
在设计测试用例时,要同时考虑有效等价类和无效等价类的设计。
软件不能都只接收合理的数据,还要经受意外的考验,接受无效的或不合理的数据,这样获得的软件才能具有较高的可靠性。
6.调试(Debug,排错)
它与软件测试不同,软件测试的目的是尽可能多地发现软件中的错误,但进一步诊断和
改正程序中潜在的错误,则是调试的任务。
调试活动由两部分组成:
①确定程序中可疑错误的确切性质和位置。
②对程序(设计,编码)进行修改,排除这个错误。
通常,调试工作是一个具有很强技巧性的工作。
一个软件工程人员在分析测试结果的时
候会发现,软件运行失效或出现问题,往往只是潜在错误的外部表现,而外部表现与内
在原因之间常常没有明显的联系。
如果要找出真正的原因,排除潜在的错误,不是一件
易事。
因此可以说,调试是通过现象,找出原因的一个思维分析的过程。
3、例题分析
选择题
1.软件测试最突出的特点是(C)。
A)软件测试的开销大B)软件测试要依靠工具
C)软件不能进行“穷举”测试D)软件测试要依靠人工
2.集成测试又称为组装测试,其主要内容包括(C、D)。
A)对整体的性能进行测试B)用白盒法设计测试用例进行测
C)确定集成策略和次序D)对集成的模块接口进行测试
3.渐增式是将模块一个一个地连入系统,每连入一个模块(C)。
A)只需要对新连入的模块进行测试
B)都不需要再进行测试
C)要对新子系统进行测试
D)都要进行回归测试
4.静态测试是以人工的、非形式化的方法对程序进行分析和测试。
常用的静态测试方
法有(B)。
A)运行程序并分析运行结果B)桌前检查与代码会审
C)回归测试法D)集成测试法
5.关于白盒法覆盖程度的论述中正确的是(A、B)。
A)语句覆盖:
选择测试用例使程序中每条语句至少被执行一次
B)判定覆盖:
选择测试用例使程序中每个判定至少都获得一次“真”值和一次“假”值
C)条件覆盖:
选择测试用例使路径都满足
D)条件组合覆盖:
将所有的判定条件都组合起来执行
6.软件测试的基本原则是(A、C)。
A)关键是注重选择高效的测试用例
B)选择尽可能多的测试用例
C)尽量不由程序设计者进行测试
D)以白盒测试为主
7.等价分类法的关键是(C)。
A)确定等价类的边界条件
B)按照用例来确定等价类
C)划分等价类
D)确定系统中相同和不同的部分
8.软件维护的类型有(A、B、C、D)。
A)完善性维护B)纠错性维护C)适应性维护D)预防性维护
9.各种软件维护的类型中最重要的是(A)。
A)完善性维护B)纠错性维护C)适应性维护D)预防性维护
10.以下属于完善性维护的有(B)。
A)解决开发是未能测试各种可能条件带来的问题
B)增加联机求助命令
C)考虑未来移植的问题
D)改正发现的错误
二、判断题
1.单元测试通常应该先进行“人工走查”,再以白盒法为主,辅以黑盒法进行动态测试。
(√)
2.功能测试是系统测试的主要内容,检查系统的功能、性能是否与需求规格说明相同。
(√)
3.白盒法是一种静态测试方法,主要用于模块测试。
(×)
4.在等价分类法中,为了提高测试效率,一个测试用例可以覆盖多个无效等价类。
(×)
5.发现错误多的模块,残留在模块中的错误也多。
(√)
6.系统测试的主要方法是白盒法,主要进行功能测试、性能测试、安全性测试及可靠
性等测试。
(×)
7.在发现错误后,则应按照一定的技术去纠正它,纠错的关键是“错误定位”。
(√)
8.软件维护只需要纠正性维护、适应性维护和完善性维护。
(×)
9.改进程序的执行效率不会引入错误。
(×)
10.强调简明性的程序出错率低。
(√)
11.用面向对象方法开发的软件系统,可维护性好。
(√)
3、简答题
1.渐增式与非渐增式各有何优、缺点?
为什么通常采用渐增式?
答:
非渐增式是将所有的模块一次连接起来,简单、易行,节省机时,但测试过程中难
于查错,发现错误也很难定位,测试效率低。
渐增式是将模块一个一个地连入系统,每连入一个模块,都要对新系统进行测试。
这种组装测试方案比较非渐增式,容易查出错误及进行
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 软件工程 导论 第五 课件