③ 确定模块之间的调用关系。 ④ 确定模块之间的接口,即模块之间传递的信息。 ⑤ 评价模块结构的质量。 (2) 数据结构及数据库设计
数据设计是实现需求定义和规格说明过程中提出的数据对象的逻辑表示。数据设计的具体任务是:确定输入、输出文件的详细数据结构;结合算法设计,确定算法所必需的逻辑数据结构及其操作;确定对逻辑数据结构所必须的那些操作的程序模块,限制和确定各个数据设计决策的影响范围;需要与操作系统或调试程序接口所必需的控制表进行数据交换时,确定其详细的数据结构和使用规则;数据的保护性设计:防卫性、一致性、冗余性设计。 数据设计中应注意掌握以下设计原则: ① 用于功能和行为的系统分析原则也应用于数据。 ② 应该标识所有的数据结构以及其上的操作。 ③ 应当建立数据字典,并用于数据设计和程序设计。 ④ 低层的设计决策应该推迟到设计过程的后期。 ⑤ 只有那些需要直接使用数据结构、内部数据的模块才能看该数据的表示。 ⑥ 应该开发一个由有用的数据结构和应用于其上的操作组成的库。 ⑦ 软件设计和程序设计语言应该支持抽象数据类型的规格说明和实现。
(3) 编定概要设计文档。在概要设计阶段,需要编写的文档有,概要设计说明书、数据库设计说明书、集成测试计划等。
(4) 概要设计文档评审。在概要设计中,对设计部分是否完整地实现了需求中规定的功能、性能等要求,设计方案的可行性,关键的处理及内外部接口定义正确性、有效性、各部分之间的一致性等都要进行评审,以免在以后的设计中出现大的问题而返工。
常用的软件结构设计工具是结构图(SC——Structure Chart),也称程序结构图。使用结构图描述软件系统的层次和分块结构关系,它反映了整个系统的功能实现以及模块与模块之间的联系与通讯,是未来程序中的控制层次体系。 结构图是描述软件结构的图形工具。如图3。8所示。
模块用一个矩形表示,矩形内注明模块的功能和名字;箭头表示模块间的调用关系。在结构图中还可以用带注释的箭头表示模块调用过程中来回传递的信息。如果希望进一步标明传递的信息是数据还是控制信息则可用带实心圆的箭头表示传递的是控制信息,用带空心圆的箭头表示传递的是数据。 根据结构化设计思想,结构图构成的基本形式如图
基本形式 顺序形式 重复形式 选择形式
程序结构图的有关术语 深度:表示控制的层数
上级模块、从属模块:上、下两层模块A和B,且有A调用B,则A是上级模块,B是从属模块。 宽度:整体控跨度(最大模块数的层)的表示。 扇入:调用一个给定模块的模块个数。 扇出:一个模块直接调用的其他模块数。 原子模块:树中位于叶子结点的模块。
传入模块:从下属模块取得数据,经处理再将其传送给上级模块。 传出模块:从上级模块取得数据,经处理再将其传送给下必模块。
变换模块:从上级模块取得数据,进行特定的处理,转换成其他形式,再传送给上级模块。 协调模块:对所有下属模块进行协调和管理的模块 2.面向数据流的设计方法
在需求分析阶段,主要是分析信息在系统中加工和流动的情况。面向数据流的设计方法定义了一些不同的映射方法,利用这些映射方法可以把数据流图变换成结构图表示的软件结构。首先需要了解数据流图表示的数据处理的类型,然后针对不同类型分别进行分析处理。 (1)数据流类型
典型的数据流类型有两种:变换型和事务型。
A、变换型。变换型是指信息尚输入通路进入系统,同时由外部形式变换成内部形式,进入系统的信息通过变换中心,经加工处理以后再沿输出通路变换成外部形式离开软件系统。变换型数据处理问题的工作过程大致分为三步,即取得数据、变换数据和输出数据。相应于取得数据、变换数据、输出数据的过程,变换型系统结构图由输入、中心变换和输出等三部分组成。 B、事务型。在很多软件应用中,存在某种作业数据流,它可以引发一个或多个处理,这些处理能够完成该作业要求的功能,这种数据流就叫做事务。事务型数据流的特点是接受一项事务,根据事务处理的特点和性质,选择分派一个适当的处理单元(事务处理中心),然后给出结果。这类数据流归为特殊的一类,称为事务型数据流。在一个事务型数据流中,事务中心接收数据,分析每个事务以确定它的类型,根据事务类型选取一条活动通路。
在事务 型数据流系统结构图中,事务中心模块按所接受的事务类型,选择某一事务处理模块执行,各事务处理模块并列。每个事务处理模块可能要调用若干个操作模块,而操作模块又可能调用若干个细节模块。 (2)面向数据流设计方法的实施要点与设计过程 面向数据流的结构设计过程和步骤是:
第1步:分析、确认数据流图的类型,区分是事务型还是变换型。 第2步:说明数据流的边界。
第3步:把数据流图映射为程序结构。对于事务流区分事务中心和数据接收通咱,将它映射成事务结构。对于变换流区分输出和输入分支,并将其映射成变换结构。
第4步:根据设计准则对产生的结构进行细化和求精。
下面分别讲座变换型和事务型数据流图转换成程序结构图的实施步骤。 变换型
将变换型映射成结构图,又称为变换分析。其步聚如下:
第1步:确定数据流图是否具有变换特性。一般地说,一个系统中所有的信息流都可以认为是变换流,但是,当遇有明显的事务特性的信息流时,建议采采事务分析方法进行设计。
第2步:确定输入流和输出流的边界,划分出输入、变换的输出,独立出变换中心。
第3步:进行第一级分解,将变换型映射成软件结构,其中输入数据处理控制模块协调输出信息的产生过程。 第4步:按上述步骤如出现事务流也可按事务流的映射方式对各个子流进行逐级分解,直至分解到基本功能。
第5步:对每个模块写一个简要说明,内容包括该模块的接口描述、模块内部的信息、过程陈述、包括的主要判定点及任务等。
第6步:利用软件结构的设计原则对软件结构进一步转化。 事务型
将事务型映射成结构图,又称为事务分析。基步骤如下:
事务分析 设计步骤与变换分析设计步骤大致类似,主要差别仅在于由数据流图到软件结构的映射方法不同。它是将事务中心映射成为软件结构中发送分支的调度模块,将接收通路映射成软件结构的接收分支。 3.设计的准则
大量软件设计的实践证明,以下的设计准则是可以借鉴为设计的指导和对软件结构图进行优化。这些准则是: ① 提高模块独立性。对软件结构应首眼于改善模块的独立性,依据降低耦合提高内聚的原则,通过把一些模块取消或合并来修改程序结构。 ② 模块规模适中。 ③ 浓度宽度、扇出和扇入适当。经验表明,好的软件设计结构通常顶层高扇出,中间扇出较少,底层高扇入。 ④ 使模块的作用域在该模块的控制域内。 ⑤ 应减少模块的接口和界面的复杂性。 ⑥ 设计成单入口、单出口的模块。 ⑦ 设计功能可预测的模块。 三、详细设计
详细设计的任务,是为软件结构图中的每一个模块确定实现算法和局部数据结构,用某种选定的表达工具表示算法和数据结构的细节。
常见的过程设计工具有:
图形工具:程序流程图,N-S,PAD,HIPO。 表格工具:判定表。 语言工具:PDL(伪码) 1、程序流程图
2、N-S流程图 为了避免流程图在描述程序逻辑时的随意性与灵活性 特征:
1)每个构件具有明确的功能域;
2)控制转移必须遵守结构化设计要求;
3)易于确定局部数据和(或)全局数据的作用域; 4)易于表达嵌套关系和模块的层次结构。 3、PAD图
是问题分析图的英文缩写。 特征:
1)结构清晰,结构化程度高; 2)易于阅读
3)最左端的纵线是程序主干线,对应程序的第一层结构;每增一层PAD图向左扩展一条纵线,帮程序的纵线数等于程序层次数。
4)程序执行:从PAD图最左主干线上端结点开始,自上而下、自左向右依次执行,程序终止于最左主干线。 4、PDL
过程设计语言也称为结构化的英语的伪码,它是一种混合语言,采用英语的词汇和结构化程序设计语言的语法,类似编程语言。 特征:
1)有为结构化构成元素、数据说明和模块化特征提供的关键词语法; 2)处理部分的描述采用自然语言语法; 3)可以说明简单和复杂的数据结构;
4)支持各种接口描述的子程序定义和调用技术。 3.4软件测试
软件测试是保证软件质量的重要手段,其主要过程涵盖了整个软件生命期的过程,包括需求定义阶段的需求测试、编码阶段的单元测试、集成测试以及后期的确认测试、系统测试,验证软件是否合格、能否交付用户使用等。 一、软件测试的目的
1983年IEEE将软件测试定义为:使用人工或自动手段来运行或测试某个系统的过程,其目的在于检验它是否满足规定的需求或是弄清预期结果与实际结果之间的差别。
关于软件测试的目的, Grenford J.Myers 在《The Art of Software Testing》一书中给出了更深刻的阐述:软件测试是为了发现错误而执行程序的过程;一个好的测试用例子指很可能找到迄今为止尚未发现的错误的用例;一个成功的测试是发现了至今尚未发现的错误的测试。
Myers的观点告诉人们测试要以查找错误为中心,而不是为了演示软件的正确功能。 二、软件测试的准则
1、所有测试都应追溯到需求
软件测试的目的是发现错误,而最严惩的错误不外乎是导致程序无法满足用户需求的错误。 2、严格执行测试计划,排除测试的随意性。
软件测试应当制定明确的测试计划并按照计划执行。测试计划应包括:所测软件的功能、输入和输出、测试内容、各项测试的目的和进度安排、测试资料、测试工具测试用例的选择、资源要求、测试的控制方式和过程等。 3、充分注意测试中的群集现象
经验表明,程序中存在错误的概率与该程序中已发现的错误数成正比。这一现象说明,为了提高测试效率,测试人员应该集中对付那些错误群集的程序。 4、程序员应避免检查自己的程序
为了达到好的测试效果,应该由独立的第三方来构造测试。因为从心理学角度讲,程序人员或设计方在测试自己的程序,要采取客砚的态度是程序不同地存在障碍的。 5、穷举测试不可能
所谓穷举测试是指把程序所有可能的执行路径都进行检查的测试。但是,即使规模较小的程序,其路径排列数也是相当大的,在实际测试过程中不可能穷尽每一种组合。这说明,测试只能证明程序中有错误,不能证明程序中没有错误。 6、妥善保存测试计划、测试用例、出错统计和最终分析报告,为维护提供方便。 三、软件测试技术与方法综述 不同角度分类:
若从是否需要执行被测软件的角度,可以分为静态测试和动态测试方法。若按照功能划分可以分为白盒测试和黑盒测试方法 1、静态测试与动态测试 (1)静态测试
静态测试包括代码检查、表态结构分析、代码质量度量等。静态测试可以由人工进行,充分发挥人的逻辑思维优势,也可以借助软件工具自动进行。经验表明,使用人工测试能够有效地发现30%到70%的逻辑设计和编码错误。
代码检查主要检查代码和设计的一致性,包括代码的逻辑表达的正确性,代码结构的合理性等方面。这项工作可以发现违背程序编写标准的部下,程序中不安全、不明确和模糊的部分,找出程序中不可移植部分、违背程序编程风格的问题,包括变量检查、命名和类型审查、程序逻辑审查、程序语法检查和程序结构检查等内容。代码检查包括代码审查、代码走查、桌面检查、静态分析等具体方式。
代码审查:小组集体阅读、讲座检查代码。
代码走查:小组成员通过用“脑”研究、执行程序来检查代码。
桌面检查:由程序自己编写的程序。程序在程序通过编译之后,进行单元测试之前,对源代码进行分析、检验,并补充相关文档,目的是发现程序的错误。
静态分析:对代码的机械性、程式化的特性分析方法,包括控制流分析、数据流分析、接口分析、表达式分析。 (2)动态测试
静态测试不实际运行软件,主要通过人工进行。动态测试是基于计算机的测试,是为了发现错误而执行程序的过程。或者说,是根据软件开发各阶段的规格说明和程序的内部结构而精心设计一批测试用例(即输入数据及其预期的输出结果),并利用这些测试用例去运行程序,以发现程序错误的过程。
设计高效、合理的测试用例是动态测试的关键。测试用例是为测试设计的数据。测试用例由测试输入数据和与之对应的预期输出结果两部分组成。测试用例的格式为:[(输入值集),(输出值集)] 2、白盒测试方法与测试用例设计
白盒测试方法也称结构测试或逻辑驱动测试。它是根据软件产品的内部工作过程,检查内部万分,以确认每种内部操作符合设计规格要求。白盒测试把测试对象看作一个打开的盒子,允许测试人员利用程序内部的逻辑结构及有送信息来设计或选择测试用例,对程序所有的逻辑路径进行测试。通过在不同点检查程序的状态来了解实际的运行状态是否与预期的一致。所以,白盒测试是在程序内部进行,主要用于完成软件内部操作的验证。
白盒测试的基本原则是:保证所测模块中每一独立路径至少执行一次;保证所测模块所有判断的每一分支至少执行一次;保证所测模块每一循环都在边界条件和一般条件下至少各执行一次;验证所有内部数据结构的有效性。
按照白盒测试的基本原则,“白盒”法是穷举路径测试。在使用这一方案时,测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据。贯穿程序的独立路径数是天文数字,但即使每条路径都测试了仍然可能有错误。第一,穷举路径测试决不能查出程序是否违反了设计规范,即程序本身是个错误的程序;第二,穷举路径测试不可能查出程序中因遗漏路径而出错;第三,穷举路径测试可能发现不了一些与数据相关的错误。 白盒测试的主要方法有逻辑覆盖、基本路径测试等。 (1)逻辑覆盖测试
逻辑覆盖是泛指一系列以程序内部的逻辑结构为基础的测试用例设计技术。通常所指的程序中的逻辑表示有判断、分支、条件等几种表示方式。
○1语句覆盖。选择足够的测试用例,使得程序中每个语句至少都能被执行一次。 例3.1设有程序流程图表示的程序如图3.24 测试用例1 : 输入
(i , j) 输出 (i , j , x)
(10,10) (10,10,10) 测试用例2: 输入
(i , j) 输出 (i , j , x)
(10,15) (10,15,15)
语句覆盖是逻辑覆盖中基本的覆盖,尤其对单元测试来说。但是语句覆盖往往没有关注判断中的条件有可能隐含的错误。 ○2路径覆盖。执行足够的测试用例,使程序中所有可能的路径都至少经历一次。 例3.2设有程序流程图表示的程序如图3.25
对图3.25的程序设计如表3.2列出的一组测试用例, 就可以覆盖该程序的全部4条路径:ace,abd,abe,acd。
测试用例 通过路径 测试用例 通过路径
[(A=2,B=0,X=3),输出略] (ace) [(A=2,B=1,X=1),输出略] (abe) [(A=1,B=0,X=1),输出略] (abd) [(A=3,B=0,X=1),输出略] (acd) ○3判定覆盖。使设计的测试用例保证程序中每个判断的每个取值分支(T或F)至少经历一次。
根据判定覆盖的要求,对如图3.26所示的程序,如果其中包含条件 i≥j的判断为真值(即为“T”)和为假值(即为“F”)的程序执行路径至少经历一次,仍然可以使用例3.1的测试用例1和测试用例2。 程序每个判断中若存在多个联立条件,仅保证判断的真假值往往会导致某些单个条件的错误不能被发现。例如,某判断是“X<1或Y>5”,其中只要一个条件联欢会为真,无论另一个条件是否错误,判断的结果都为真,这说明,仅有判断覆盖还无法保证能查出在判断的条件中的错误,需要更强的逻辑覆盖。
4条件覆盖。设计的测试用例保证程序中每个判断的生个条件的可能取值至少执行一次。 例3.3设有程序流程图表示的程序如图3.26
按照条件覆盖的测试要求,对图3.26的程序判断框中的条件i≥j和条件j<5设计如下测试用例1和测试用例题,就能保证该条件取真值和取假值的情况至少执行一次。 测试用例1 输入
(i , j) 输出 (i , j , x)
(3,2) (3,2,3)
测试用例2 输入
(i , j) 输出 (i , j , x)
(5,10) (5,10,10)
条件覆盖深入到判断中的每个条件,但是可能会忽略全面的判断覆盖的要求。有必要考虑判断-条件覆盖。
○5判断-条件覆盖。设计足够的测试用例,使判断中每个条件的所有可能取值至少执行一次,同时每个判断的所有可能取值至少执行一次。
例3.4设有程序流程图表示的程序如图3.27
按照判断-条件覆盖的测试要求,对图3。27程序的两个判断框的每个取值分支至少经历一次,同时两个判断框中的三个条件的所有可能取值至少执行一次,设计如下测试用例1、测试用例2和测试用例3,就能保证满足判断-条件覆盖。 输入
(i , j,x) 输出 (i , j , x)
(3,2,0) (3,2,0) 测试用例1
测试用例2 输入
(i , j) 输出