https://www.kekaoxing.com/d/uploads/book/软件可靠性.rar
第1章
软件可靠性工程概论
在学习本章之前一定要先阅读本书的前言,了解本书的所有章节是如何组织的。
软件开发具有一种或多种风险:
1. 发布产品的不可靠性。
2. 开发进度落后。
3. 开发费用超出预算。
这些情况可能造成市场份额减小或收益减少,因此软件开发人员和测试人员所承受的压力
经常是非常巨大的。
为了解决这个问题,人们将注意力主要放在开发和测试的技术工作方面,并构建了很多支
持过程的工具。研究人员也重点研究软件开发和测试理论,以及它所涉及的许多难题。然而,
在如何对基于软件的产品可靠性的工程方面,所投入的注意力太少了。工程软件可靠性是指以
这样一种方法来开发一种产品,使得这种产品能够在合适的时间,以可以接受的成本和令人满
意的可靠性投放“市场”。请注意,“市场”两个字是加了引号的,这是为了表示一种比商业产
品市场更为广泛的概念。即使是为军事目的或为政府开发的产品也有市场问题,如果产品推出
时间太迟、价格太高或者很不可靠,那么用户完全可以选择其他的产品来替代。
开发和测试的传统观点,没有提供足够的能力达到这个工程目标。软件可靠性工程要求一
个更为广泛、更具活力的观点。例如,软件可靠性工程已经表明,最有效率的测试包括所有那
些出现在整个产品生存周期和与系统工程和系统设计任务交互的工作。因此,在面对用户的需
要时,软件可靠性工程使测试人员能够处于领导地位。这包括系统工程师、系统构架师、潜在
用户、经理们( M u s a,1 9 9 6 c)以及作为合作者的开发人员( M u s a,1 9 9 6 a,1 9 9 6 b,1 9 9 7 c,
1 9 9 7 d,1 9 9 7 g;Musa and Widmaier 1996)。
软件可靠性的标准定义( M u s a,Iannino and Okumoto,1 9 8 7),是在一段特定的自然单
元或时间间隔内,无失效运行的概率。尽管失效的机制可能是不同的,不过这个定义与硬件
可靠性的定义是相容的。这种相容性,使这种可靠性定义能够用于既包括软件又包括硬件的
系统。
前面提到的产品特性,即可靠性、开发时间和开发费用,它们都是一个更为一般的特性的
属性,即产品质量。产品质量是这些特性的一个合适的平衡点。得到一个好的平衡点,意味着
必须为这三个特性找到定量的目标,并且在开发过程中进行度量。
当然,各个项目组已经能够为产品的交付时间和开发费用给出定量目标并对其进行度量。
但是直到现在,仍然没有为基于软件的系统可靠性做同样的工作。从1 9世纪4 0年代开始,对硬
件系统的可靠性可以给出定量目标并度量。但是,这样的纯硬件系统几乎已经消失殆尽,因此
需要发展软件可靠性工程。
1.1 什么是软件可靠性工程,它是如何帮助开发和测试的
软件可靠性工程是惟一一种标准化的,被证明是最好的一种实践方法,使得测试者和开发
者可以同时实现:
1. 确保产品的可靠性达到用户要求。
2. 加快产品上市的速度。
3. 降低产品的成本。
4. 提高用户满意度,降低用户不满意的风险。
5. 提高生产率。
软件可靠性工程可以应用于任何基于软件的产品的任一版本,可以开始于任一版本周期的
开始。因此,老产品也可以很容易地处理。使用基于软件这样的描述是为了强调纯软件系统是
不存在的,因此在分析中必须说明硬件部分的问题。在对任何产品的测试应用软件可靠性工程
之前,必须首先对单元和模块进行测试(或用其他方法验证),然后把它们集成为可以执行的完
整功能。
软件可靠性工程之所以有效,在于它运用了两个基本的思想:第一,通过定量描述产品的
使用方式,可以更有效地开发产品的功能并且使用这些信息,以便:
1. 将资源精确地集中到最常用和最关键的功能上。
2. 使测试工作真实地反映实际条件。
关键是指它的成功执行会具有很大的附加价值,而失败会产生很大的负面影响。这种价值
和影响可能关系到人的生命、财产或系统的工作能力。
第二,软件可靠性工程平衡用户对可靠性、开发时间和开发费用的需求,从而更加有效。
为此,软件可靠性工程要像对开发时间和开发费用设置定量目标那样,对可靠性也设置定量目
标,要制定策略来达到这些目标。最后,软件可靠性工程在测试过程中跟踪产品的可靠性,并
用来作为产品是否可以发布的标准。通过软件可靠性工程,你可以交付“正好合适”的可靠性
的产品,并且既避免了不必要的资金和时间成本,又避免了发生由不够可靠的产品导致的用户
不满和问题。
软件可靠性工程建立在牢固的理论基础之上( M u s a,Iannino and Okumoto,1 9 8 7),这些理
论包括操作剖面、随机过程软件可靠性模型、统计估计和顺序采样理论。从1 9 7 3年起,软件小
组就一直在实践着软件可靠性工程( Musa and Iannino,1 9 9 1 b)。在AT & T公司,从1 9 9 1年5月以
来,软件可靠性工程就一直是一项最佳当前实践( B C P)(D o n n e l l y,E v e r e t t,Musa and Wi l s o n,
1 9 9 6)。被选为AT & T的最佳当前实践是相当重要的,这是因为它使用了非常严格的标准。首先,
必须在几个(通常是至少8到1 0个)项目中使用所建议的实践方法,得到以财务术语表示的效益
与费用的比率。然后详细描述对这种实践方法以及在项目中如何使用,同时给出采用这种实践
的商业案例。由有经验的第三或第四级的经理组成的委员会,将对此描述及案例进行长时间的
仔细审查。审查一般要持续几个月,这期间由第一级的软件经理和高级软件开发人员进行详细
的评审。对软件可靠性工程的最佳当前实践建议的审查,要由7 0个以上这样的人员参加,在最
终审查之前的意见收集阶段,参与人员会超过1 0 0人。即使到那时,这个软件可靠性的最佳当前
空2 第1 章空
实践还只是1 9 9 1年3 0个建议中获得通过的仅有的5个中的1个。
此外,美国航天航空协会1 9 9 3年通过将软件可靠性工程作为一项标准。这对航空业产生了 #p#分页标题#e#
重大影响( A I A A,1 9 9 2)。1 9 9 6年,《软件可靠性工程手册》出版,进一步证实了这个领域的重
要性(Ly u,1 9 9 6)。I E E E在开发软件可靠性工程的标准方面也一直非常活跃。
曾经使用过软件可靠性工程的机构,包括阿尔卡特、AT & T、B e l l c o r e、C N E S(法国)、
E N E A(意大利)、爱立信、法国电信、惠普、日立、I B M、N A S A的发动机推进实验室、N A S A
的航天飞机计划、洛克希德·马丁、朗讯、微软、M i t r e、摩托罗拉、北电、北卡罗来州立大学、
R a y t h e o n、绅宝军用飞机(瑞典)、Tandem 计算机、美国空军、美国海军陆战队等。本书附录H
中给出了一些由软件可靠性工程的使用者撰写的描述其使用经验的论文。
Ti e r n e y(1 9 9 7)于1 9 9 7年下半年发表了一份调查报告,报告表明微软公司在其5 0 %的软件
开发小组中使用软件可靠性工程,其中包括像Windows NT和Wo r d这样的项目。得到的益处包括
测试覆盖率的提高、所需测试量的压缩、有助于建立定版评判准则的有用指标和规格说明评审
的改进。
很多年来,AT & T公司网络和计算服务部的运行技术中心一直将软件可靠性工程作为标准软
件开发过程的一部分。这个过程现在正在进行I S O认证。运行技术中心是AT & T公司业务单元的
一个主要软件开发组织,它在1 9 9 4年获得了Malcolm Baldrige国家质量奖。当时,它是AT & T中
使用软件可靠性工程比例最高的单位。另一个有趣的现象是,前5个获得AT & T贝尔实验室主席
质量奖的单位中,有4个使用了软件可靠性工程。
International Definity项目是对软件可靠性工程的一次应用。在这个项目中,软件可靠性工
程和其他相关软件技术一起使用。与前一个没有使用这些技术的版本相比,由用户发现的错误
减少了9 0 %,这使得客户的满意度大幅度上升。结果,销售量也上升了1 0倍,系统测试时间和
费用减少了一半,整个项目的开发时间减少了3 0 %,程序维护费用降低了9 0 %(A b r a m s o n等,
1 9 9 2)。
软件可靠性工程领域的快速发展体现了它的价值。I E E E计算机协会软件可靠性工程委员会
从1 9 9 0年创建时的大约4 0人,到1 9 9 6年中期超过了1 0 0 0人,每年增长速度超过7 0 %。由向一年
一度的国际软件可靠性研讨会( I S S R E)投稿的数量判断,软件可靠性工程研究的同期年增长率
为3 5%。
应用软件可靠性工程的经验表明,对大多数项目来说,应用软件可靠性工程将占用全部开
发费用的0 . 1 %到0 . 2 %。对大型项目,这个比例会减少;对小型项目,这个比例会增加。对小型
项目来说,全部工作量将小于1个人月,包括培训、开发操作剖面、收集数据和处理的成本。
1.2 软件可靠性工程过程
应用软件可靠性工程的过程,首先要求确定哪些系统与要测试的产品相关联。在这项工作
中,必须了解软件可靠性工程测试的类型。因此,首先来看一下后面这个问题,然后再讨论如
何确定要测试哪些关联系统。
软件可靠性工程的过程包括5个步骤,即定义“必要”的可靠性、开发操作剖面、准备测试、
空软件可靠性工程概论3空
执行测试和应用失效数据得到结论。图1 – 1对此进行了说明,图的底部还标出了典型的项目阶段。
请注意,“执行测试”和“应用失效数据得到结论”这两个步骤是同时进行的,并且联系的很紧
密,随着可用的失效数据的增加,重点相对向应用数据倾斜。这5个步骤的每一步都分别在本书
的一章中详细讨论(第2章到第6章)。
图1-1 软件可靠性工程过程框图
为了简洁起见,这个过程框图只给出了以箭头表示的软件可靠性工程的主要工作流。实际
上,任务经常会有循环和反馈,这与软件开发过程的螺旋模型(与瀑布模型相反)类似。就像
在软件开发过程中,一些需求和体系结构在测试之后可能会发生变化一样,在软件可靠性工程
的过程中,对“必要”的可靠性定义在“执行测试”和“应用失效数据得到结论”两个步骤之
后,也可能会发生变化。
软件生命周期中,测试之后的发行与维护阶段并没有在图1 – 1中表示出来。在这个阶段中,
可以确定事实上得到的可靠性以及实际的操作剖面。这些信息会对下一个版本“必要”可靠性
的定义和操作剖面的开发产生影响。它可能会产生产品和开发过程的再工程。
测试人员与软件工程师一起合作完成前两个活动,即“定义必要的可靠性”和“开发操作
剖面”。我们原来曾经认为这两个活动应该完全交给系统工程师和系统构架师来完成,但是,在
实践中效果并不好。测试人员需要依靠这两项工作,因而比系统工程师和构架师更有动力去成
功完成。让测试人员参加系统工程和系统构架小组就可以解决这个问题。
这个解决方法还会带来意料之外的益处。测试人员与产品用户有了更多的接触,这是非常
有益的,这有助于了解什么样的系统行为是不可接受的,它们在多大程度上是不可接受的,以
及用户将会怎样使用这个产品。系统工程师和构架师对于测试,以及在什么地方需求和设计应
该更清楚、更精确有了充分的了解,这使得测试计划、测试案例和测试过程的设计能够顺利进
行。系统测试人员对系统结构的审查做出重要贡献,经常会指出一些被遗忘的重要功能。
系统体系结构阶段包括软件可靠性工程中的对失效预防、失效清除和容错的策略混合的选
择活动。因此会影响产品和过程的设计。测试人员可以不做这项工作,但是必须了解它,因为
它会影响他们。
空4 第1 章空
定义“必要的”可靠性
开发操作剖面
准备测试
应用失效数据
得到结论
执行测试
需求与体系结构设计与实现测试
1.3 Fone Follower
考虑一个贯穿全书的例子,以便使应用软件可靠性工程的过程说明得更加具体。这个例子
取材于一个实际的项目,为了简洁和对专有信息的保护,其中的细节做了修改。选择这个例子
是因为它是关于电话服务的,对大多数人来说很容易理解。同时,它还很小(全部人员少于1 0 #p#分页标题#e#
人,软件可靠性工程要求的额外工作量大概为1人月)。这绝不是说软件可靠性工程只能应用于
通信系统或小的项目。实际上,软件可靠性工程已经被应用于源代码量从5 000行到10 000 000
行的各类系统。除了通信系统之外还(至少)应用于医用成像系统、资产管理和财会系统、编
译器、终端固件、仪器固件、军事系统和空间系统。
Fone Follower系统可以处理从世界各地打入的电话呼叫(传真或语音),包括蜂窝电话和其
他移动电话。作为Fone Follower的用户,可以拨打Fone Follower,并输入想要拨打的电话号码。
从电话网来的对某一号码的呼叫都被传送到Fone Follower,它根据输入程序对传真和语音
呼叫进行处理。如果某一号码对语音呼叫没有应答,并且此号码有寻呼服务,则对其进行寻呼。
如果仍然没有应答或此号码没有寻呼服务,那么语音呼叫将被传送到语音信箱。
Fone Follower使用的操作系统是由销售商提供的,它的可靠性目前是未知的。在使用者看
来,服务包括标准的电话服务和Fone Follower提供的呼叫传送服务。
1.4 测试的类型
软件可靠性工程测试包括两种类型:可靠性增长测试和确认测试。这两种类型与不同测试
阶段无关,例如单元测试、子系统测试、系统测试或b 测试,而是与测试的目标相关。可靠性
增长测试的目标是找到并清除错误。在可靠性增长测试过程中,使用软件可靠性工程来估计并
跟踪可靠性。测试人员和开发经理应用可靠性信息来指导开发和发布。可靠性增长测试一般在
自己机构内开发软件的系统测试阶段。如果一边测试一边解决失效问题(清除导致它们的错误),
那么可靠性增长测试也可以应用于b 测试阶段。为了得到一个“好的”(有一定的不确定性)对
失效强度的估计,在失效数据样本中对失效数据的数量有一个最低要求,通常是1 0到2 0。
可靠性增长测试包括特性测试、负载测试和回归测试。在特性测试中,操作都是独立运行
的,运行场地环境的影响和交互作用被减小到最低程度。有时通过在操作之间重新初始化系统
来减小交互作用。负载测试是指同时运行很多操作,并且是以相同的频率,在其他现场将会出
现的相同环境条件下。这样就可以产生与在现场中可能出现的情况相同的交互作用和环境条件
的影响。验收测试和性能测试都属于负载测试。回归测试是在系统发生重要改变之后进行的,
包括一些(通常是随机选取的)或全部特性测试。在回归测试中应该包括所有关键操作。
负载测试通常包括对系统资源的竞争,这可能会产生排序或计时问题,同时还经常出现数
据随时间的退化问题。前述的因素可能会揭示出一些潜在的特性测试和回归测试中没有被激活
的由交互作用导致的失效。尽管交互作用对于多用户系统更为重要,它对于像在个人电脑上运
行的软件这样的单用户系统也是重要的,因为可能会有由于操作之间的顺序而产生的不同的交
互作用。
空软件可靠性工程概论5空
确认测试不包括调试过程,不会试图通过引起定位错误后再清除错误来解决所发现的失效。
被测系统必须是稳定的,不能出现任何改变,不管是由于增加了新特性还是由于错误的清除。
通过确认测试,得到一个二选一的结论:或者接受这个软件,或者拒绝它并把它退回给提供商。
在确认测试中,所需要的失效数据样本的数量要少得多。事实上,如果无失效运行的时间足够
长,那么可以在出现任何失效之前就做出结论。通常只在负载测试(不是特性或回归测试)中
使用确认测试。
1.5 待测系统
为了学习或分析的方便,可以用各种方法对“系统”进行定义。它可以包含硬件、软件和
人员要素的各种组合。一般地,可以将“系统”定义为要单独测试的每一个实体。
当然,一般情况下希望将正在开发的真实产品作为一个系统。只要是正在开发,即使是产
品的一部分,我们也将使用可靠性增长测试。接下来可能是确认测试,如果用户将要进行验收
测试,那么这就是一次彩排。如果只是将各个组件集成起来形成产品,那么就只对集成后的产
品做确认测试。对产品的主要变体也要识别为待测系统。产品的一个不同的硬件配置(完成同
样的功能)是一个不同的系统。因为必须要能够在不同的平台或不同的操作系统上运行,所以
会有多个有很大差别的版本。国际性的产品在不同的国家还需要有不同的接口。
如果有超系统或者说是此产品在其中作为一个组件运行的系统,那么应该将它们看作潜在
的要单独测试的系统。如果用户通过超系统的可靠性来判断一个产品,或者是产品和组成超系
统的其他系统之间的交互非常复杂,以至于难以定义的话,那么很可能要对超系统进行单独测
试。这是由于使用接口驱动来独立测试产品是有风险的,因为对接口的刻画可能是不正确的。
在封闭式软件包的情况下,经常对超系统进行测试。其他的例子包括打印机和个人电脑。如果
对一个或多个包含此产品的超系统进行测试,那么对此产品的变体所对应的超系统可能也需要
测试。
有些超系统进行系统测试是不实际的,或不经济的,但是可以进行b 测试,因此要为此阶
段做必要的进度安排。当然, b 测试涉及现场环境中的直接执行,标识失效,并应用失效数据。
b 测试不要求开发操作剖面,准备测试用例和过程,也不需要通过测试过程调用测试案例。
可能还要将采办的软件(不是由自己机构开发的软件)组件作为自己的系统测试,如果它
们的可靠性是未知的,或是有疑问的,并且尽早发现不可靠性可以避免进度拖延或费用超支的
话。通常,这种测试仅对于产品的第一版是必要的,尽管对于后续包含新的或较大变化的采办
组件的版本可能也是需要的。采办软件包括下架软件,或包装的软件包,或由其他产品或组件
或对象库重用得到的软件或子结构软件。如果根据以前经验得知一个组件对于此产品来说具有
足够的可靠性,那么就没有必要单独对它进行测试。如果并不能肯定组件,但是与其供货商有
着良好的关系,可以由他们在监督下进行可靠性增长测试,跳过验收测试并节约时间和金钱。
请注意,在确定是否测试组件时,尺寸是一个重要考虑因素。如果组件是一个主要部分,则对 #p#分页标题#e#
它进行单独测试是经济的。如果都是些小的采办软件组件(包括对象),那么只有当很多系统都
空6
用这些组件时,对其进行单独测试才是经济的。
将软件可靠性工程应用于对象库的测试上似乎很有潜力,因为这些对象库是面向对象开发
中需要的,而在很多系统中都希望使用这些对象。事实上,面向对象开发的进一步发展和使用
可能要依赖于这种技术融合:面向对象的概念使更好的模块化成为可能,但是通常并没有了解
重用的前提和益处,因为开发者(很可能是正确的)拒绝使用那些可靠性不明确的对象。
当然,要选择多少个系统进行单独测试是有限制的。每一个单独测试都包含额外开销。尽
管可以并行执行多个测试,但在某些时候,有限的人力和计算资源还是会造成进度拖延。费用
包括开发一个或多个附加的操作剖面、开发测试案例和测试过程,以及执行测试。只有当从单
独测试得到的益处大于其所要求的额外时间和费用时,才会对额外系统进行单独测试。益处包
括客户不满意程度的降低或日程拖延(两者都将影响市场份额)的减少和额外开发费用的节省。
对一个额外系统进行单独测试的费用可以降低,如果这个系统拥有操作体系结构(它的组
件对应于操作或操作组)。这是因为对它的组件开发操作剖面相对简单,使得对组件进行单独测
试相对容易。
尽管对多于几个的系统进行单独测试可能是不值得的,但是确定对在一起测试的大量独立
组件的失效强度并不那么昂贵,因此也很现实。这是因为,只需要将组件的失效进行分类并度
量组件所做的处理(通过自然单元或者时间单元计算)。然而,由于从小的失效样本来估计失效
强度时会引起误差,因此估计多个失效强度是不实际的。
在Fone Follower中,要对操作系统获得的组件、Fone Follower本身以及包含电话网和F o n e
F o l l o w e r的超系统进行测试。可以对产品使用确认测试,但是由于这会延长交付时间,所以没有
这么做。
1.6 常见问题
在本节中,首先研究的问题为是否需要应用软件可靠性工程及其带来的益处。接下来的问
题集中于澄清软件可靠性工程的概念,它与其他实践方法的联系,以及何时、何处应用软件可
靠性工程。
1.6.1 有效性和益处
1. 为什么软件可靠性在软件质量领域如此重要?
答:在软件质量这个较大并且可能有些模糊的概念中,软件可靠性是一个很专门的可度量
的属性。它可能是最具包含性的最重要的属性,因为它处理运行中与用户描述的行为的偏离自
由度。换句话说,软件以用户所希望的方式执行。严格说来,软件质量中的没有包含在软件可
靠性中的其他方面(例如可维护性),在程序没有让人满意地运行的时候都是第二位的。
2. 软件可靠性与其他量化质量的方法相比,在有效性上有什么差别吗?
答:对用户来说,软件可靠性是质量最重要的方面,因为它定量地指出一个软件产品对于
用户的需求的工作好坏程度。质量的其他度量可能与软件可靠性有些关系,但是相比起来它们
空软件可靠性工程概论7空
都很不直接。例如,剩余错误数量与软件可靠性有关系,但它是面向开发者的,并且它没有指
出对操作的影响。不仅如此,剩余错误不能度量而只能是推测,这意味着精确性很低。已发现
的错误数量与可靠性没有关系。如果只发现了几个错误,这或者可以表明软件是可靠的,或者
表明是很差的测试和不可靠的软件。在设计或代码检查中没有发现的问题数量作为一种质量度
量来说,与已发现的错误有相同的属性。其他度量,例如程序复杂性,离用户的质量概念就更
远了。
3. 从硬件可靠性照搬的软件可靠性是否会导致一种不合适的技术?
答:软件可靠性不是从硬件可靠性照搬过来的。在开发软件可靠性的过程中,充分意识到
了两者的区别。然而,我们故意使其定义在数学上与硬件可靠性相容,这样就可以计算那些同
时包含硬件和软件的系统的可靠性。我们研究了诸如错误计数之类的其他方法,但是由于不相
容等原因又否决了它们。一个不相容的定义是没有实际意义的,因为真实系统都是既包含硬件
又包含软件的。
4. 软件可靠性工程对于获得B a l d r i g e奖而知名的全面质量管理有帮助吗?
答:软件可靠性工程与全面质量管理紧密联系,并且实际上是它的主旨。它提供了一个与
用户满意度紧密相连的面向用户的指标。说它是主旨是因为,没有一个面向用户的系统可靠性
指标,就无法管理质量,并且没有软件可靠性度量,就无法确定基于软件的系统可靠性。
软件可靠性工程几乎与B a l d r i g e奖打分系统中所有主要指标有关联。
5. 有人说软件可靠性工程是不充分的,因为它没有充分强调防止灾难性失效。这种看法
对吗?
答:不对。这种看法没有正确理解软件可靠性工程。灾难性失效是所有失效中的一部分。
跟踪和减少所有失效,也会按比例减少灾难性失效。
6. 在测试中,遇到失效我们就解决它,为什么还需要估计软件可靠性呢?
答:因为如果不这样的话,就不会知道还要执行多少测试。
7. 软件可靠性概念是否有益于根原因分析(找到造成错误的最终原因,目的是提高软件工
程过程的质量)?
答:是的。操作剖面(在第3章中定义)加强了这些经常执行的功能。与这些功能有关或与
会产生严重影响的失效有关的失效报告,在根原因分析的研究中应该得到优先考虑。在根原因
分析基础上进行的提高质量的活动,应该首先强调那些将使客户对质量的感觉产生最大影响的
因素。
8. 如何使用软件可靠性工程来改善设计和测试过程呢?
答:使用软件可靠性工程可以在以下几个方面改善设计和测试过程:
a. 使用操作剖面(在第3章中定义)的知识,将设计工作重点放在最常用的功能上。
b. 应用操作剖面来驱动测试,将首先激活最常用的功能,有助于首先找出并清除这些功能
的错误,从而快速降低失效强度。
c. 开发机构和客户一起建立的失效强度目标,决定了在设计和测试中需要多大的工作量,
以及要使用的技术。
d. 失效强度目标给出了一个发布标准,即在何时可以停止测试。 #p#分页标题#e#
空8 第1 章空
e. 由于不同软件工程技术而产生的对可靠性的不同度量,加上与之相关的费用和持续时间,
将提供一个在未来的项目上选择这些技术的基础。
9. 应用软件可靠性工程对那种在很短的时间内使用商品化货架组件快速创建的“高速”程
序有益处吗?例如用户在因特网上编制的系统、代理或小应用程序。
答:是的,尽管这显然与在商品化软件实施软件可靠性工程不同,但仍然希望有实质性的
用处。有用的分析要确定所建造的组件的可靠性水平,以使系统的可靠性是可被接受的。
10. 为什么要度量软件可靠性?建立最好的软件开发过程并且努力地使用不是更有效吗?
答:关键的问题是,“最好”是什么意思?最好的意义必须由人来定义,最合适的人选应该
是基于软件产品的最终用户。一个没有度量的定义是很不精确的。我们需要知道用户需要的可
靠性水平。请注意,最高水平可能是不合适的,因为这将使所需开发时间和费用变得不可接受。
最后,除非我们可以度量某种方法在提高必要产品特性(如可靠性、开发时间和开发费用方面)
的有效性,否则将没有一个满意的方法来决定在开发过程应该增加什么活动。
11. 由软件工程研究所提出的能力成熟度模型( C M M)要求对基于软件的系统可靠性进行
度量吗?
答:是的,对第4级和第5级机构有明确要求,对第3级机构有间接要求。
12. 在什么地方软件可靠性工程对改善软件开发过程能做出最大贡献?
答:当需要加速产品功能的开发(同时减少费用),并且保持必要的可靠性的时候。
13. 我的公司正从软件开发商发展为软件集成商,这会对软件可靠性工程的应用产生什么影
响呢?
答:你将继续对软件可靠性工程有强烈的需求,因为你必须保证最终产品的可靠性,并且
在可靠性、开发时间和费用之间求得最佳平衡。总之,你可能比原来更加需要软件可靠性工程,
因为需要对交给你的组件进行确认测试。但是,对可靠性增长测试的需求可能会减少。
14. 可以将软件可靠性工程应用于超可靠系统吗?
答:是的。一些统计学家说不能这样做,因为测试时间可能会长得不切实际。这个观点是
基于硬件角度的,所以对软件来说并不适用。通常在软件操作中,只有一小部分必须是超可靠
的,并且并不经常被调用。通过使用适当的软件体系结构,例如防火墙,这些操作可以被隔离。
因为它们并不是经常被调用,可以通过实际可以达到的测试量来保证它们的高可靠性水平。最
后,因为处理器很便宜,并且会越来越便宜,因此可以使用并发的多个处理器来进行测试。
15. 让用户在什么时间介入软件可靠性工程?
答:在建立产品和超系统的失效强度目标,以及开发操作剖面(包括决定操作模式)时,
要让用户加入。如果用户要求进行验收测试,他们会加入到其中。
16. 可以将软件可靠性工程应用于经费很少的系统吗?
答:是的。仅有的区别是开发预算可能会较少,因此测试可以使用的资源会减少。结果,
必须努力将测试系统的数量、操作模式的数量、操作的数量、测试案例的数量以及测试时间保
持在一个较低的水平。
17. 有时我会听到一些在本书中没有的新的软件可靠性工程思想,这是为什么?
答:我们有意将本书的内容限制在那些已经被实践验证了的思想。在你所听到的思想中,
空软件可靠性工程概论9空
有一些可能确实很有前途,并且有些在未来几年就可能被实践所证明。本书介绍的是1 9 9 8年初
的实践情况。
1.6.2 概念
1. 软件可靠性这个词让人感到不安。软件不会像硬件那样受到磨损,怎么能使用一个硬件
的概念呢?
答:首先,软件可靠性这个词使用的是它的一般含义,无论喜欢或不喜欢。然而,我们故
意决定提升这个词的使用,以强调软件可靠性与硬件可靠性的相容性,以及在计算系统可靠性
中的结合。软件磨损方式与硬件的确不同,尽管随着软件功能的发展和对软件的维护,软件也
随时间而退化。软件可靠性实际上是对设计自信度的一种度量。也可以估计硬件系统的设计自
信度。但通常不这么做,因为对多数硬件系统来说,磨损现象会掩盖设计缺陷。
2. 当我们说软件失效是随机的时候,难道没有曲解这个问题吗?硬件失效确实像是随机的,
但是软件失效是由一个可以控制的智能过程产生的。
答:硬件失效的随机性并不比软件的随机性更“确实”。随机性的概念是用来对那种影响因
素过多以至于无法用确定性模型描述的行为进行建模的。我们可能认为自己可以控制智能过程
及它们的产品,但这是一种错觉。许多缺陷(比如内存方面的小错)都可能在智能过程中发生。
这些缺陷是由很多因素引起的,因此最好使用随机过程来对整体进行建模。
3. 怎么能讨论软件可靠性问题呢?这与硬件不同。如果让我选择软件测试并且确定它们的
顺序,我就可以给出想要的任何可靠性估计。比如,如果进行了一次运行,并且执行过程没有
失效,接着不停地重复它,那么就可以得到一个接近于1的可靠性。
答:操纵可靠性估计是可能的。至少要知道一个失败的运行和一个成功的运行。然后就可
以用希望的比例选择它们。但事实上,我们对程序相应人工选择测试集的行为并不感兴趣。我
们感兴趣的是将会经常遇到的典型运行(通常随机排序)环境。对硬件的测试进行人为控制也
是可能的,并且同软件一样是不合理的。例如,让汽车轮胎不停地在尖东西上转就会得到一个
非常低的可靠性。
4. 怎么能把系统使用看成是随机的呢?如果知道了系统的弱点就可以避免它们。
答:假设人们知道系统的弱点,并且避免使用有错误的操作,而不是要求软件设计者去改
正,这等价于对系统需求的重新定义。有时,没有任何理由不把对剩余操作的使用看作是一个
随机过程。
5. 软件的可靠性怎么会由于不会磨损而随时间变化呢?
答:请注意,软件的可靠性是随执行时间变化的。随着失效的出现以及导致失效的错误的
发现和改正,可靠性会增长。出现软件可靠性随时间而变化的现象,仅仅是因为时间与执行时
间有某些关系。 #p#分页标题#e#
6. 管理层告诉我,我们的目标是使那些对总任务的成功非常关键的一些功能达到完美(所
有这些功能的成功对于任务的成功都是必需的,任何一个都不能失败)。我们要怎样应用软件可
靠性度量呢?
答:期望完美是不实际的,尽管从公共关系的立场来看,承认自己的目标达不到完美可能
空10 第1 章空
是难堪的。真正要做的是确定所需要的“接近完美”的程度。
你应该是在一个不错的公司工作,因为性命攸关的软件,例如医疗系统、飞机和空中交通
控制以及核电站中的软件的开发者需要处理这些问题。
对关键功能设置一个合适的目标,通常取决于失效造成的影响,这些影响通常用金钱和生
命来表示。尽管设置精确的目标可能是困难的,但是通常使用边界和近似目标是可能的。一种
有用的方法是利用过去的经验和相同的情况来估计什么是可以接受的。例如,在美国,人们显
然可以接受汽车的风险等级是大约每1 06小时的运行出现一个致命意外,因为这种风险并不会使
人们放弃开车。
如果每年的失效损失水平占了公司年收入相当大的部分,那么就是不可接受的。对于你正
在考虑的系统来说,如果失效的风险水平足以使人们停止使用它,那么就是不可接受的。
7. 在测试的不同阶段(例如单元测试、子系统测试、系统测试)度量失效的重要性一
样吗?
答:在测试中迟一些进行的度量,通常可以对将来的运行有较好的指示作用。这是因为有
更多的数据可用,并且可用的数据通常更基于所提交的系统,基于更接近于真实的操作剖面的
测试操作剖面。
然而,这并不是说在开发的早些时候得到的数据对于将来的运行无法给出有用的估计。必
须对早期数据进行调整,以使它们能够解释所提交系统的一部分,以及与真实操作剖面有一定
距离的测试操作剖面。
8. 软件可靠性工程是基于需求的吗?
答:是的。但这并不意味着我们忽视有关设计和项目历史的有用信息。
9. 关于软件可靠性工程的常见错误概念是什么?
答:最普遍的错误概念是:
a. 软件可靠性工程主要是关于软件可靠性模型和预测的。
b. 软件可靠性工程错误地照搬了硬件可靠性理论。
c. 软件可靠性工程解决错误和调试问题。
d. 软件可靠性工程本身与典型测试无关。
e. 测试超可靠软件是设有希望的。
10. 可靠性增长与对现有可靠性的估计是矛盾的目标吗?
答:很可能不是,如果是,矛盾程度也很有限。当测试时,估计现有可靠性要求你准确地
表现现场条件(也就是根据在第3章中定义的操作剖面来选择测试)。取得最优的可靠性增长,
意味着你选择测试以使每个单元测试时间内的可靠性增长都尽可能的快。在某种程度上,根据
操作剖面来选择测试可能得到最快的可靠性增长,因为会更早地测试那些经常执行的代码,并
发现和清除代码中的错误。然而,在一些较少执行的代码被第一次测试之前,可能会对那些经
常执行的代码重复测试了几次了。重复执行可能使其代码中的错误几乎都被清除了,所以这段
代码的继续执行不会使可靠性有太大的增长。于是在一定的条件下,由操作剖面驱动的选择之
外的其他方法可能会提高测试效率。但是现在还不知道这些条件是什么。
11. 为什么软件可靠性与硬件可靠性是如此不同呢?我知道软件与硬件非常不同,但是为什
空软件可靠性工程概论1 1空
么不能像处理硬件失效数据那样处理软件失效数据?
答:软件和硬件可靠性确实有相同的定义:在确定时间内无失效操作的概率。最主要的区
别是软件可靠性比硬件可靠性更可能随时间发生变化,或者由于在可靠性增长测试中清除错误,
或者由于加入了新的代码(新代码中可能包含错误)。所以需要模型来刻画这种改变。如果软件
是稳定的(不会发展且不会被调试),那么对软件失效数据可以像对硬件失效数据那样进行处
理。
12. 不难注意到,质量属性重要性的顺序一般是可靠性、进度、费用。有没有其他有重要差
别的顺序?
答:有。政府和军事应用通常把费用排在进度之前。
13. 面向运行视图的软件可靠性与面向时间视图的软件可靠性,哪一种更合适?
答:因为所有的运行都有一个发生的频率和一段执行的时间,所以两种视图是等价的。
14. 影响硬件可靠性的环境因素会影响软件可靠性吗?
答:一般不会。硬件可靠性通常受一些物理因素的影响,比如温度和机械压力。软件可靠
性通常受使用方式的影响。
15. 向网络计算(例如小应用程序、J a v a、客户机-服务器网络等)的转移会对软件可靠性工
程产生怎样的影响?
答:这不会影响基本理论,也很可能不会影响实践中使用的基本方法。但是,在一定领域
中,我们会发现更强调在多种多样的应用系统中所使用的小软件组件。于是,软件可靠性工程
将经常应用于领域中,并且在领域中的验证测试的重要性将会增加。这些组件可能会组合到更
多的系统中去,并且会有更多的操作模式(在第3章中定义)。
16. 为什么必须建立一个可靠性目标呢?难道不应该力求零缺陷(错误)吗?
答:设置零缺陷(错误)目标实际是不考虑产品的交付日期和产品费用。你需要在可靠性、
交付日期和费用之间找到一个满足用户需求的平衡点。
1.6.3 与其他实践的联系
1. 下列质量属性中的哪些可以结合到软件可靠性中并且由软件可靠性度量?
a. 功能(特性的体现)。
b. 失效消息的质量。
c. 易于学习。
d. 用户操作的友好性。
e. 可维护性。
f. 硬件容错与可恢复性。
g. 性能。
h. 可扩展性。
i. 支持水平(对支持要求的反应速度)。
j. 软件容错与可恢复性。
k. 易于将用户的问题与系统能力联系起来。
空12 第1 章空
l. 用户错误的容错。
答:属性a、b、d、f、g、j 和l。我们可以把这些质量属性与执行中用户可能感到不满意的
程序行为联系起来。
2. 怎样使用软件可靠性来刻画功能?
答:确定你的客户想要的功能以及会以什么样的频率使用它们。将一个没有出现的功能认
为是一个失效。例如,假设客户需要一个状态显示功能,此功能可在航空定座系统中显示每架 #p#分页标题#e#
飞机上没有售出的座位,以此作为每天定价的基础。于是可以认为此项功能的不存在就是一个
失效。于是在可能存在其他失效的情况下,每1 0 0 0个小时还有4 1 . 7个失效。尽管存在这种将功能
结合进软件可靠性的可能性,但通常不这么做。一般情况下,要为一个产品版本确定一个固定
的功能集,然后根据这个功能集来度量软件可靠性。
3. 软件安全性与软件可靠性有什么联系?
答:软件安全性是软件可靠性的一个方面。可靠性暗含了合适的软件功能,安全是软件必
须满足的一种合适功能。可以将失效分类为安全攸关的和非安全攸关的。例如,一个系统可能
每1 0 0 0小时出现2个安全失效。请注意,一个不安全的系统也是不可靠的。
4. 什么是系统的可存活性?
答:可存活性通常是指当一个系统随时间而退化时,对于一个具体关键功能集的可靠性。
例如,可以将太空飞船的可存活性表示为当它遭受辐射时,飞行导航功能的可靠性。
5. 没有失效可能性的软件可以是不安全的吗?
答:不是,如果将“失效”广义地解释为“客户会不满意的行为”。当然,发生的不安全事
件可以被解释为不满意。于是,不安全事件可以组成失效的一个子集。
6. 风险评估与软件可靠性有什么联系?
答:风险评估研究的是不希望发生的事件的发生概率。这些事件包括软件失效,也可以包
括其他事件,例如费用超支。于是风险评估可以比软件可靠性更一般。
7. 失效模式和影响分析( F M E A)与软件可靠性工程有什么联系?
答:软件可靠性工程是一种宏观的方法,它对于软件产品采用一种全局性的“大图景”式
的观点。F M E A是一种关于特定失效、失效如何发生、如何预防失效的宏观方法。由于详细分析
需要大量工作,因此F M E A比软件可靠性工程要昂贵。所以在实践中要更加预防关键失效。可以
按下述方法将这两种实践结合起来:应用软件可靠性工程以降低总失效强度;对潜在的严重等
级为1的失效使用F M E A,可以确定和实现合适的失效预防或容错特点。
8. 软件可靠性工程与净室开发如何联系?
答:软件可靠性工程与净室开发有很多相似之处,但软件可靠性工程是一种更一般的实践。
净室开发包括层次的规格说明和设计,以及进行形式化正确性验证的小组评审。可以在净室开
发中使用软件可靠性工程,也可以在其他开发方法学中使用软件可靠性工程。
9. 我们与自己的软件供应商有非常紧密的联系。当测试他们的软件时,我们向他们递交错
误报告。它们改正后交回,我们集成之后继续测试。我们做的是哪种类型的测试?
答:可靠性增长测试。
10. 功能点分析在软件可靠性工程中用得上吗?
空软件可靠性工程概论1 3空
答:根本用不上。功能点分析最初是为了支持成本估计和生产率度量而开发的。完成同样
功能的代码行数可能有很大差别,这取决于编程人员对于所解决问题的认识和自己的风格。因
此,代码行数在估计成本和度量生产率时不是一个好的度量。然而,产生错误的数量(以及失
效强度)与代码行数是高度相关的,因为每行代码的人员错误率似乎是固定的。所以功能点分
析在预测失效强度方面并不是必需的。
1.6.4 应用
1. 可靠性对于系统的用户会产生特别的心理影响吗?
答:当用户首次开始使用一个新系统时,有一点是很重要的,就是那些经常使用的功能要
有较高的可靠性。如果不是这样的话,这个系统将很快得到一个坏名声,而且以后也很难得到
改变的。用户可能会避免使用部分或整个系统,或者会绕过它进行工作。这种情况正是决定系
统期望使用方式观点的又一个有力论据,这个观点就是:使用它来指导测试,并且先测试那些
最常用的功能。
2. 可以将软件可靠性工程应用于那些“自顶向下”设计和测试的系统吗?
答:是的。当在系统测试阶段应用软件可靠性工程时,测试时间很可能会减少,因为要清
除的错误已经减少了。然而,任何软件产品发布之前似乎都必须有一个实质性的系统测试阶段。
通过大量的功能测试来运行代码是必需的。
3. 空间任务中使用的飞行软件通常是“一种中的一个”。这会给软件可靠性工程的应用带来
问题吗?因为上一次的经验可能无法应用到下一次任务中。
答:不会。在测试中对失效强度的估计是基于失效数据的,这依赖于本次任务而不是以前
的任务。
4. 软件重用从可靠性和费用的观点来看都是有益的吗?
答:是的。被重用的软件组件一般具有更高的可靠性,从而使系统有更高的可靠性。但是
必须在使用重用组件的系统中以及该系统的使用环境中,对重用组件的可靠性进行验证。
5. 在应用软件可靠性工程中,人们常犯的错误是什么?
答:最常见的两种错误是:
a. 在创建操作剖面(在第3章中定义)时,由于忽视特殊或短暂的环境(例如:一个正处于
插入数据过程中的数据库)而丢失了一些有很高出现概率的操作。
b. 不依据操作剖面进行测试,于是估计的可靠性不能反映真实的情况。
6. 软件可靠性工程可以应用于面向对象开发吗?
答:是的。
7. 在面向对象程序中应用软件可靠性工程,需要做特别的改动吗?
答:不需要。
8. 要实现软件可靠性工程,“传统”软件开发过程需要做哪些变动呢?
答:这些变动并不是实质性的,并且除了软件可靠性工程外,它们还带有很多其他益处:
a. 需要为产品确定一个或多个操作剖面(在第3章中定义)。
b. 系统测试必须与操作剖面一致。
空14 第1 章空
只有第一个改变会涉及到一些实质的工作。建立一个操作剖面将使开发过程集中于那些最
常见的功能上,在生产率上得到很大的改进。系统测试的变动更多地反映在测试的顺序上而不
是工作量上。软件可靠性工程要求记录测试输出,并且在失效时进行检查,但这对于好的传统
系统测试实践来说,并不是一个新的要求。
顺便说一句,软件可靠性工程不会对系统构架师和开发人员的工作影响太大,除非要求在
交付的产品中包括失效记录和报告的特点。
9. 在我们的项目中,有些人对于建议由客户设定失效强度目标感到不快。你是如何处理的? #p#分页标题#e#
答:应指出,从长期利益讲,以具体定量语言理解客户需求,对于他们及其客户都是有益
的。当然,前提是双方都了解在可靠性、新特性的交付时间和费用三种要素之间折衷考虑。更
好的了解,意味着客户将更有可能感到满意,开发组织相对于自己的竞争者将更有可能占据先
机。尽管刚开始时对于由客户设定失效强度目标可能会有阻力,但是这些阻力将随着深入的理
解而消失。
10. 将软件可靠性工程应用于封装式软件包(例如,销售给大量客户的软件)时,必须考虑
哪些不同呢?
答:封装式软件包的最初销售,更多地取决于在竞争对手之前上市大量有用的功能。因此,
对于一些最常使用的特性进行快速测试,以使其达到最低的可靠性标准是很重要的。达到一定
的最低标准是最基本的,因为如果产品经常失效,它将会得到一个无法挽回的坏名声,但是除
了必要的弥补之外,不应做更多的测试,否则竞争对手可能会在你之前发布一个提供最常用功
能的产品。使较少使用的特性达到好的可靠性,可以在以后的版本实现。因此操作剖面的开发
(在第3章中讨论)是一个非常优秀的方法。
在设定要达到的最终失效强度目标时,同时综合考虑成本将是特别重要的,因为价格上的
竞争是很激烈的。
由于包装式软件包通常有大量的用户,因此需要通过抽样来得到操作剖面(在第3章中定义)
数据和可靠性需要的数据。可能必须引导用户提供这些数据。一些软件供应商已经在对早期用
户免费提供的通常由因特网分发的b 测试版本中包含了使用记录。请注意,在对从一组具体用
户得来的数据进行解释时必须要小心,他们对整个最终用户群可能不具有代表性。
11. 我们的产品必须与多种多样的接口硬件与软件一起工作。在这种情况下,我们应该如何
组织测试呢?
答:你的产品匹配的每一个硬件与软件配置,在与你的产品结合之后,都构成一个超系统。
需要对每一个超系统进行测试。
可以看到,超系统的数量很容易超出控制。可能希望开发一个配置剖面( J u h l i n,1 9 9 2),
即一个包含配置以及它们出现概率的列表。这些概率通常是由与特别配置相关联的用户数量来
决定的。这些数据通常是对一小部分使用情况的合理近似,并且易于收集。可以使用配置剖面
来分配测试的工作量。对于很少出现的配置,甚至可以不去测试。
另一个策略是定义一个基准配置,外加一个增量配置集。每个增量配置都表示从基准配置
到一个专门配置所需做的变动。许多增量配置只会影响有限的操作,通过对所有操作测试基准
配置,并只对有关的操作进行增量配置测试,可以节约大量测试时间。
空软件可靠性工程概论1 5空
12. 为什么要设置可靠性目标?为什么我们不能只开发一个操作剖面(在第3章中定义),并
用分配开发资源以使测试更为现实?
答:操作剖面在分配开发资源和进行现实的测试方面有很大帮助,但是它不能说明需要进
行多长时间的测试,或者在可靠性改进策略方面要投入多少工作量。这些都需要一个绝对的度
量方法,就像失效强度目标一样。
13. 对于合作开发的软件,是看作开发的还是采办的软件呢?
答:如果你的机构是合作者之一,则应该将它看作是开发的软件,并且只进行可靠性增长
测试。如果不是,就将它看作采办的软件,并且只做确认测试。
14. 我们制造了一种笔记本电脑,编写了一些基本的固件和软件,以使标准商业操作系统可
以在上面运行。这个产品必须与不同的打印机一起工作。我们怎样与计算机一起进行打印机测
试呢?
答:计划一组超系统测试,每个测试都包含计算机和其中一个打印机。
15. 系统的一个组件不再被支持了。应该对它进行确认测试吗?
答:是的。你需要知道组件的可靠性,以及组件将如何影响该系统的可靠性。如果其影响
是不可接受的,就必须找到一个替代组件或者某种方法,以提高其可靠性。
16. 我们可以对老系统实施软件可靠性工程吗?什么时候实施?
答:可以,在每一个发布周期的开始。
17. 对产品的单元测试可以应用软件可靠性工程吗?
答:在理论上可以。但由于为单元开发操作剖面的工作量和成本太大,通常这样做并不实
际,除非这个单元将会在多个产品中使用。但是使用软件可靠性工程来对将在多个产品中使用
的组件进行验证是很需要的。
18. 什么类型的系统由于在系统测试中无法经济地进行,而通常推迟为b 测试?
答:超系统,因为重新制造或者模拟那些与你的产品交互的系统通常是非常昂贵的。对于
分布在广泛地理区域的系统网络,更是如此。
19. 当测试接口时,我们应当使用确认测试还是可靠性增长测试?
答:当测试接口时,通常使用两种方法:在每一个它所包含的接口系统中,检查所传递的
变量,对于包含接口系统的系统,观察整体行为。测试的类型与当前系统所使用的测试相同。
20. 有的机构在其所有产品中都使用层次式结构:用户界面、应用系统和数据库。这样的机
构如何应用软件可靠性工程?
答:所包含的工作实质上是相同的。一些层次,例如数据库和用户界面,很可能是他们自
己的产品,这些产品作为组件与应用相结合,成为交给“最终”用户的“最终”产品。请注意,
像数据库和用户界面这样的产品会和许多其他系统一起工作。因此在开发操作剖面时,必须把
一些外部系统看作是操作的发起者,可能还需要测试一些超系统。
1.7 背景
本节为软件可靠性工程的实践提供更加广泛的背景知识。首先深入研究一些与软件可靠性
空16 第1 章空
有关的概念,然后将软件可靠性与硬件可靠性进行比较,最后讨论软件可靠性模型。需要更多
的背景,请参考M u s a,1 9 8 8,1 9 8 9 b,1 9 9 1 c,1 9 9 5 b;Musa and Ackerman,1 9 8 9,1 9 9 1,M u s a、
Ackerman and Everett,1 9 9 4;M u s a,B u c k l e y,K e l l e r,Lyu and Ta u s w o r t h e,1 9 9 5;Musa and
E h r l i c h,1 9 9 6;Musa and Everett,1 9 9 1,1 9 9 3 a,1 9 9 3 b;Musa and Iannino,1 9 9 0; Musa and #p#分页标题#e#
O k u m o t o,1 9 8 6。
1.7.1 软件可靠性概念
对于软件经理和软件工程师来说,理解软件可靠性工程已经成为一项关键的技能。这项知
识对于包括软件在内的产品的经理和工程师,以及这些产品的用户也同样重要。幸运的是,在
过去的2 5年里,大家已经积累了一整套知识来帮助达到这个目标,并且从实际项目中已经得到
了很多实践经验。一些问题仍然存在,但是解决这些问题取决于在实际项目中出现这些问题,
并收集有关数据。这些度量足够准确和有用,所获得的收益超过了它们的费用。
软件可靠性工程的一个主要目标,是帮助软件工程师、软件经理和软件用户学会做精确的
决定。第二位的目标,是通过将注意力集中于软件可靠性而使得每个人都更好地了解软件可靠
性的重要性。好的决定能够在很多方面为一个项目或一个软件部分的生命周期节约费用。通常
可以期望得到的节约超过了应用这些思想的1 0倍。为了更好地理解,请考虑下面这个简单的例
子:有一个为期2年的软件项目,系统测试时间大约是6个月。测试量通常与所要求的可靠性有
很强的联系,尽管它并不是惟一的因素。假设对于一个专门的应用,只需要5个月的测试就可以
达到所要求的可靠性,这样可以节约这个项目开发费用的4 %。将它与应用软件可靠性工程的花
费相比,通常只是项目开发费用的0 . 1 % ~ 0 . 2 %,因此采用这种方法是很划算的。
软件可靠性工程是“工程”,这可以从下面意义上来理解,即产品的设计和构建要达到产品
所需要的可靠性水平,综合考虑测试与其他提高可靠性的方法,以及根据操作的使用情况和关
键程度来分配测试资源。
应用软件可靠性工程的主要费用用在开发所需要的操作剖面(在第3章中定义)。开发操作
剖面的费用随它的规模和所要求的准确度而不同,但是对于从几百到几千条源指令的系统,平
均工作量是1 ~ 2人月。这样,后续版本升级操作剖面任务就轻松很多。在当前的情况下,在单元
测试中使用软件可靠性工程是昂贵的,除非这些单元在多个系统中使用。
许多类型的测试都被单独命名,可以将软件可靠性工程应用于所有类型的测试,根据操作
剖面,及时(比如一天)地集中测试。因此,软件可靠性工程可以包括特性、回归、配置、负
载、稳定性、开关式操作场景、性能和安全测试。通常不包括安装测试。
基于软件的产品三个最重要的质量特性,是可靠性、进度和费用。请注意,这些特性更多
的是面向用户,而不是面向开发者的属性。人们很早就开始定量度量后两种特性了,但是定量
度量可靠性则是最近的事。这非常重要,因为对于软件,如果没有可靠性的具体度量,那么在
进度和成本上的竞争就会处于劣势。事实上,这种具体度量问题,可能就是许多软件产品存在
着众所周知的可靠性问题的主要原因。
可靠性可能是“软件质量”这个概念中一个最重要的固有特性。可靠性与缺陷联系密切,
就像J o n e s ( 1 9 8 6 )所指出的那样,缺陷是程序设计中花费最大的元素。软件可靠性描述了软件功
空软件可靠性工程概论1 7空
能满足用户需求的程度。“客户”与“用户”的区别在于,客户是决定是否购买此软件的人,而
用户则是操作软件的人。通常(但并不总是)用户和客户的交流是良好的,所以用户的需求包
含在客户的需求之中。
可靠性是在一段时间内,软件无失效运行的概率。“失效”是指程序的功能在某方面没有达
到用户的需求。“没有像用户需求的那样工作”是一个很广的定义。因此,可靠性结合了与程序
执行相关联的所有属性。例如,它包括正确性、安全性和可使用性的操作方面,以及对用户的
友好性。请注意,安全性实际上是软件可靠性的一个特殊子类。可靠性不包括可移植性、可修
改性或文档的可理解性。
最初(和许多现在)的软件可靠性度量方法都试图对在程序中找到的错误或缺陷进行计数。
这类方法是面向开发人员的。而且,在实践中被计数的或者是失效(出现故障)或者是修改
(例如,维护或修改报告),它们都不等价于错误。即使正确地统计了所找到的错误,也没有多
少提示作用(数量很大是好还是不好?)。软件中仍然存在的错误有更好的提示作用,但是可靠
性的内涵更加丰富。
可靠性是面向用户的而不是面向开发人员的。可靠性与操作有关,而不是与程序的设计有
关,因此可靠性是动态的,而不是静态的( S a u n i e r,1 9 9 3)。可靠性考虑问题出现的频率,直接
与操作经验和在经验中错误的影响相关。因此,可以很容易地将可靠性与成本联系起来。可靠
性很适合检查发展趋势的重要性、设定目标和预测什么时候可以达到目标。可靠性使人们可以
使用同样的术语对硬件和软件的系统可靠性进行分析,而在真实系统中硬件和软件都同时存在。
所以,可靠性度量比错误度量要有用得多。
这并不意味关注错误是没有价值的。但是应该将注意力集中于把错误看作是可靠性的指示,
集中到错误的自然属性。更好地理解错误和人们犯错的过程,会导致制定避免、检测、清除或
者补偿错误的策略。
通常将软件可用性定义为一段执行时间,在这段时间中一个软件组件或系统以可以接受的
方式运行。假设这个程序已经运行,并且没有由于要加入新的功能而进行修改,因此具有固定
的失效强度。可以像对硬件那样计算软件的可用性。失效强度是所度量的时间段接近无穷时,
可用时间与可用时间和停机时间之和的比。一段给定时间段内的停机时间,是这个时间段的持
续长度、失效强度和平均修复时间( M T T R)的积。这里使用的失效强度通常是对严重失效的统
计,而不是那些仅仅包含系统的一些微小退化问题。一般说来,在运行现场确定错误并改正它
的时候将系统停止下来是不实际的。所以,一般将M T T R定为恢复数据、重新载入程序和重新执
行所需的时间。如果希望确定包含硬件和软件组件的系统的可用性,可将M T T R定为修复硬件和
恢复软件的平均时间。
请注意,可维护性这个词对于硬件和软件有相同的定义,即解决一次失效所需要的平均人 #p#分页标题#e#
力时间,但是意义有所不同。解决硬件问题是在线的,它对停机时间会发生影响。解决软件问
题是离线的,不影响停机时间。
还有其他几个与可靠性有关的术语。完整性是在给定威胁剖面和威胁出现率的情况下,系
统在一段特定时间内没有发生安全性被破坏的运行概率。可恢复性是指从失效状态恢复所需的
平均时间,包括数据清理或重新初始化,类似于硬件M T T R。
空18 第1 章空
1.7.2 可靠性
对可靠性定量的定义可以通过自然单元(在第2章中讨论)或时间单元。我们当前考虑两种
时间。程序的执行时间是处理器真正用来执行该程序指令的时间。第二种时间就是我们日常所
熟悉的通常时间。执行时间是重要的,因为现在人们普遍接受的一种观点是基于执行时间的模
型更高级。然而,具体的定量值必须最终与普通时间相关联对许多工程师和经理来说才能是有
意义的。如果只占用程序执行时间一小部分的计算机利用时间是固定的,那么普通时间就与执
行时间成比例。作为这两种时间类型的一个例子,考虑一个秘书使用的字处理系统。在一星期
内,系统运行的时间可能是4 0小时,字处理程序本身执行的时间可能是2小时。
每周的计算机平均利用率,在系统测试期间有增长的趋势,尽管在现场它经常是相对固定
的。可以使用日历时间模型( M u s a、Iannino and Okumoto,1 9 8 7)来描述系统测试期间的普通
时间与执行时间之间的关系。
有4种方法通常被用来描述失效发生的时间:
1. 失效时间。
2. 失效间隔时间。
3. 直到指定时刻为止所累积的失效数。
4. 一段时间内发生的失效数。
表1 – 1和表1 – 2中对这些方法进行了说明。
表1-1 基于时间的失效规格说明
失效数失效时间(秒) 失效间隔(秒)
1 1 0 1 0
2 1 9 9
3 3 2 1 3
4 4 3 11
5 5 8 1 5
6 7 0 1 2
7 8 8 1 8
8 1 0 3 1 5
9 1 2 5 2 2
1 0 1 5 0 2 5
11 1 6 9 1 9
1 2 1 9 9 3 0
1 3 2 3 1 3 2
1 4 2 5 6 2 5
1 5 2 9 6 4 0
表1-2 基于失效的失效规格说明
时间(秒) 累积失效数时间段内的失效数
3 0 2 2
6 0 5 3
空软件可靠性工程概论1 9空
(续)
时间(秒) 累积失效数时间段内的失效数
9 0 7 2
1 2 0 8 1
1 5 0 1 0 2
1 8 0 11 1
2 1 0 1 2 1
2 4 0 1 3 1
2 7 0 1 4 1
请注意,前面给出的4种量都是随机变量。所谓随机,是指不能确定地知道变量的值。这种
情况通常发生于当影响值的因素(许多是不知道的)过多,以至于预测是不实际的。存在许多
可能的值,每一个值都有其出现概率。例如,无法真正知道下一个失效在何时发生。如果可以
知道,就能够试图阻止它,或者避免它,所知道的只是一组失效可能发生的时间,以及每个失
效出现的概率。每次失效出现的概率只占该失效出现情况的很少一部分。
请注意,随机两个字并不包含任何非理性或不可预测性的含义,不像有些人所错误认为的
那样。随机表示的不可预测只是说不知道确切值。然而,平均值或某种意义上的偏差是知道的。
随机并不意味着不受其他变量的影响。尽管失效的发生是随机的,但它绝对是受一些因素的影
响,比如测试策略和所使用的程序。随机也不意味着有任何特别的概率分布,有些人错误地认
为是均匀分布。
有这种随机性至少有两个主要原因。第一,程序员出现错误,从而导致程序错误,这是一
个很复杂、不可预测的过程。因此程序中错误的位置是未知的。第二,程序执行的环境条件一
般是不可预测的。例如,对于电话交换系统,怎样才能知道下一个呼叫是何种类型的呢?还有,
所要求的程序功能和所执行的代码路径之间的关系,尽管理论上是可以确定的,但实际上可能
因为太复杂而无法确定。由于失效依赖于代码中存在的错误,以及在一定的机器状态情况下执
行错误代码,因此引入第三个因素,即失效过程的随机性。
表1 – 3说明了在一段执行时间中出现失效的一个典型的概率分布。每个失效的随机变量值都
与它的概率一起给出。当然,概率加起来为1。请注意,随机变量在这里是离散的,因为失效数
必然是一个整数。同样也可以有连续的随机变量,比如时间就可以是任何值,请注意,最有可
能的失效数是2(概率是0 . 2 2)。失效数的平均值是可以计算的。将每个可能的值乘以它所出现的
概率,然后将所有这些乘积加起来,如表1 – 3所示,平均有3 . 0 4个失效。
表1-3 典型失效概率分布
随机变量值(一段时间内的失效数) 概率失效数与概率的乘积
0 0 . 1 0 0
1 0 . 1 8 0 . 1 8
2 0 . 2 2 0 . 4 4
3 0 . 1 6 0 . 4 8
4 0 . 11 0 . 4 4
5 0 . 0 8 0 . 4 0
空20 第1 章空
(续)
随机变量值(一段时间内的失效数) 概率失效数与概率的乘积
6 0 . 0 5 0 . 3 0
7 0 . 0 4 0 . 2 8
8 0 . 0 3 0 . 2 4
9 0 . 0 2 0 . 1 8
1 0 0 . 0 1 0 . 1
平均失效数3 . 0 4
可以将随机过程看作是一个随机变量的集合,每一个随机变量都与一个时间点相对应。可
以有离散的或连续的时间随机过程。随机过程的一个特征是随机变量的概率分布形式。例如,
一种普通的分布形式是泊松分布。另一个主要特征形式是过程随时间的变化。
可以从两个视点来看时间变化,即平均值函数和失效强度函数。平均值函数表示了与每个
时间点相关的平均累积失效数。失效强度函数是平均值函数的变化率或每个单位时间内的失效
数。例如,可以说每小时0 . 0 1个失效或1 0 0小时1个失效。严格地说,失效强度是平均值函数的关
于时间的派生,并且它是一个瞬时值。
其他每个表达可靠性的方法,比如失效强度或真实可靠性都有其优点。失效强度表达更为
经济,因为只需要给出一个数字。然而,可靠性表达有时更适合于将组件的可靠性组合起来,
以得到系统的可靠性。如果每个时间点的失效率是要优先考虑的,那么失效强度可能是更为合
适的度量。当要求系统在一段时间内正常工作以完成一些功能时,可靠性通常是最好的度量。 #p#分页标题#e#
例如登月飞船。图1 – 2表明了随着错误的清除,失效强度和可靠性一般是怎样变化的。测试阶段
的时间将典型地表示数百或数千个运行。请注意,对失效强度的定义,与对可靠性的定义一样,
都是关于特定环境的。
图1-2 可靠性与失效强度
空软件可靠性工程概论2 1空
可靠性
时间(执行小时)
失效强度
随着错误的清除(例如,在可靠性增长测试阶段),失效强度逐渐下降,可靠性逐渐提高。
当引入新的功能或做设计变动的时候,经常会引入新的错误,结果是失效强度的一个跳跃式的
增长,以及可靠性的一个跳跃式的降低。如果引入新功能的同时还修改了原有的错误,失效强
度可能会跳跃式的增长,也可能跳跃式的降低,取决于是新功能引入的错误占主要地位,还是
所清除的错误占主要地位。可靠性也会有相应的减少或增加。如果系统是稳定的(也就是说代
码不变),失效强度和可靠性就趋向为固定的。这相当于程序已经发布到现场,代码不做任何修
改并且也不做任何错误修复工作。
平均失效时间(M T T F)是硬件可靠性中使用的术语,在软件可靠性中,平均失效时间的
范围会缩小。它是下一次失效间隔的平均值。使用M T T F是很有吸引力的,因为值越大意味着
越好。然而,在很多情况下,软件可靠性的M T T F是没有定义的。因此,更倾向于使用失效强
度,因为失效强度总是存在。同时,失效强度使用起来也更为简单,因为失效强度可以通过相
加合并起来。以近似的、不严格的语言说,平均失效时间与失效强度成反比。在硬件可靠性中,
当发生修复或替换时,要使用平均失效时间间隔(M T B F)。M T B F是M T T F和M T T R的和。
表1 – 4以简单的方式说明了一个失效随机过程的例子,显示了在两个不同的时间点所经历的
累积失效数的平均值函数。时间点是tA=1小时和tB=5小时,概率分布随时间变化的随机过程称
为非均匀的。可靠性增长测试中的大部分失效过程都符合这种情况。图1 – 3也显示了在时间点tA
和tB 上的相关失效强度函数。请注意,在这两点上,平均失效数从3 . 0 4增长到7 . 7 7,同时失效强
度是降低的。
表1-4 时间点tA 和tB 上的概率分布
概率
随机变量值(一段时间内的失效数) 经过时间tA=1小时经过时间tB=5小时
平均失效数3 . 0 4 7 . 7 7
空22 第1 章空
图1-3 平均值与失效强度函数
影响失效行为的两个最重要的因素是:
1. 所执行的软件中的错误数。
2. 操作剖面。
软件中的错误数是在其生命期内引入的错误数与被清除的错误数之差。
程序员在开发代码时会引入错误。在初始设计阶段,或增加新功能、改变设计,或修复已
发现的错误时,都可能会引入错误。我们有意使用被定义为程序员创建或修改的指令的开发代
码。在一般情况下,只有新的或修改了的代码会引入错误。重用在另一个应用中完成的相同功
能的代码通常不会引入多少错误,除非是在接口部分。因为在以前的应用中,这些代码通常是
经过全面调试的。请注意,清除错误的过程通常会引入一些新的错误,因为这种过程要修改或
者写新的代码。大家都希望(如果编程队伍具有足够的能力)引入的错误少于所清除的错误。
除非能够以某种方法首先发现错误,否则清除错误显然是无法进行的。因此清除通过执行
发现的错误,取决于相关失效的出现,这种出现又取决于软件执行时间的长短和操作剖面。当
执行不同的操作时,会碰到不同的错误,而且所显示出的失效也很可能不同,这是操作剖面的
影响。例如,不难想像,电子电话交换系统在商业区运行的可靠性与在生活区运行的可靠性是
不同的。
常常不用执行程序也可以发现错误,可以通过审查、编译器诊断、设计或代码评审或阅读
代码来发现错误。
错误的清除还取决于错误发现和清除的效率。例如,一个失效处理小组可以解决所报告的
每1 0 0个失效中的9 5个错误。其效率依赖于诸如失效周围的环境是否有充分的文档,以及程序的
结构和清晰程度等因素。
大家已经看到,失效过程依赖于被构建的系统、具体项目的开发过程属性以及该系统的使
空软件可靠性工程概论2 3空
平均值函数
时间(小时)
失效强度
时间tA
时间tB
用。由于系统和项目组联系得非常紧密,因此在提到具体的失效过程时,我们常常互换使用这
两个词。
下面的关系适用于可靠性(硬件或软件)。可靠性由R(t) 表示,以下的公式与失效概率F(t)
相联系:
R(t)=1-F(t) (1 . 1)
失效概率是失效时间少于或等于t 的概率。如果F(t) 是可微分的,失效强度f(t) 就是F(t) 关于
时间的一阶导数。如果已知在从0到t 的时间间隔中没有失效发生,则危险率z(t) 是条件失效强
度,由下面公式给出:
(1 . 2)
并且与可靠性还有以下关系:
(1 . 3)
在软件可靠性工程中,现场的危险率是分段不变的,只有在发布新版本时才会出现发生不连续
现象。危险率等于失效强度l。因此由公式1 . 3可以导出在附录D中给出的可靠性与失效强度之间
的关系。
平均失效时间MTTF q 由下面的公式与可靠性联系起来:
(1 . 4)
其中,积分在系统的操作时间上进行。
1.7.3 软件可靠性与硬件可靠性
硬件可靠性领域的建立已经有一段时间了。因此,读者可能会问软件可靠性与硬件可靠性
有怎样的联系。事实上,硬件与软件可靠性的区分颇有人为的因素。两者都可以用同样的方式
定义,因此可以将硬件与软件组件的可靠性组合起来得到系统的可靠性。
硬件和软件可靠性都依赖于环境。软件失效的根源在于设计错误,而硬件失效的主要根源
通常在于物理变质。然而,为软件可靠性开发的概念和理论确实可以应用于任何设计活动,包
括硬件设计。一旦软件(设计)缺陷被适当地修复,通常就被永久性修复了。失效通常只发生
在当程序(设计)运行在并非它所开发和测试时面向的环境中的情况。尽管制造过程也可能影
响物理组件的质量,但是软件(设计)的复制过程很简单,并且其质量水平很高。 #p#分页标题#e#
工程师们并没有在任何程度上将“设计可靠性”的概念应用于硬件。由于损耗和其他物理
原因造成失效的概率,通常远远大于由于未发现的设计问题所造成的失效。将硬件的设计失效
保持在一个低水平上是可能的。因为硬件在逻辑上通常比软件简单。硬件的设计失效也必须控
制在一个低的水平上,因为在该领域中更新所制造的元件是非常昂贵的。然而,关于硬件可靠
性的考虑重点可能已在开始改变。对软件可靠性工作的了解,加上对设计错误重要性了解的不
断增进,可能会产生一定的影响力。人们正在开始的对软件工程与芯片设计的比较,更加强了
R(t)
空24 第1 章空
这种不断增进的了解。
由于设计错误的引入和清除发生在软件开发和测试阶段,因此可以预期在这些阶段中出现
软件可靠性改变。硬件可靠性在一些阶段中也可能改变,例如刚开始老化或有用生命的末尾。
然而,硬件可靠性相比于软件更趋向于一个固定值。
尽管存在上述的不同,我们提出软件可靠性理论所采用的方法与硬件可靠性理论仍然是相
容的。因此可以使用标准硬件组合技术( Lloyd and Lipow,1 9 7 7;S h o o m a n,1 9 8 6)来计算系
统可靠性。总之,硬件与软件可靠性有许多相似之处,也有一些不同。不能错误地假定软件所
表现出的问题总是特有的,同时又必须小心不要将此类推广得太远。
1.7.4 软件可靠性建模
对软件可靠性建模,首先必须考虑影响它的主要因素:错误的引入、错误的清除以及环境。
错误的引入主要取决于产品特性和开发过程。最重要的产品特性就是程序的大小。开发过程特
性包括所使用的软件工程技术和所使用的工具、人员的经验水平、需求的易变性以及其他因素。
请注意,你可能会开发代码以增加功能或清除错误。错误的清除依赖于失效的发现和修复活动
的质量,而失效的发现又依赖于软件被执行的程度以及操作剖面。由于上述因素中的一些本质
上是概率性的,而且操作是在一段时间内进行,因此软件可靠性模型通常刻画为执行时间上的
随机过程。模型之间的不同,一般是失效时间或失效数的概率分布,以及执行时间内随机过程
的变化性质。请注意,可以根据应用系统的具体情况,将执行时间转换为自然单元或时间单元,
以便更容易地进行测量。
软件可靠性模型要描述失效过程对上述因素的一般依赖形式。使用不同的数学形式描述失
效过程的可能几乎是无限的。这里只考虑那些很成熟的、已经很好地应用于真实数据并且得到
合理结果的模型。第8章还将全面讨论模型。通过确定模型的参数值,可以从模型的一般形式得
到特殊形式,这可以通过以下两种方式进行:
1. 估计—将统计推论过程应用于程序的失效数据。
2. 预测—根据软件产品的性质和开发过程确定(这可以在推行任何活动之前完成)。
在对确定具体形式时总会有一些不确定性。这通常称为参数的置信区间。置信区间表示参
数以一定的置信度取值的一个范围。例如,在无限时间内,置信度为0 . 7 5将会经历的失效数为从
1 5 0到1 7 5个失效。
一旦确定具体形式之后,就可确定失效过程的许多不同特性。许多模型有下列要素的解析
描述:
1. 任何时间点所经历的平均失效数。
2. 一段时间间隔内的平均失效数。
3. 任何时间点的失效强度。
4. 失效间隔的概率分布。
好的软件可靠性模型应该具有一些重要特性:
1. 给出未来失效行为的好的映射。
2. 计算一些有用的量。
空软件可靠性工程概论2 5空
3. 简单。
4. 可广泛应用。
5. 基于可靠的假设。
未来失效行为的映射在映射期间内,模型参数值不会改变。如果错误引入和错误修复的对
立影响的净作用发生明显变化,那么或者针对变化做相应的补偿,或者等到出现足够多的新失
效之后,再对模型参数进行估计。由于非常复杂,因此将这些变化结合到模型本身中去是不实
际的。不管是哪种情况,由于参数的精度一般是未知的,因此陷入这种复杂问题是不值得的。
软件可靠性工程一般都是以在一种固定环境中执行的稳定程序为基础(尽管常常并不明确
说明这一点)。这意味着代码和操作剖面都不会改变。如果程序和环境确实发生变化,而且实际
情况也往往如此,则通常以分段形式进行处理。因此,模型主要关注的是错误的清除。然而,
大多数模型都可以处理缓慢错误引入的影响,其中一些模型假定平均长期净影响是失效强度的
降低。如果错误引入、错误清除和操作剖面都不发生变化,那么失效强度将会是固定的,因此
应该简化模型以适应这种情况。假设程序的行为与需求会有全面的可对比性,因此所有失效都
可以被检测到。这可以对变化的程序或环境进行补偿(请参阅第6 . 3 . 1节和第6 . 3 . 4节)。
对于已经发布并投入运行的程序,通常会在下一个版本中延迟提供新功能和修复。假设操
作剖面是固定的,程序会表现出一个固定的失效强度。
一般说来,好的模型会强化项目组内的沟通,并且提供理解软件开发过程的一般框架。模
型还要实现管理层和其他有关各方的可视性。这些优点很有价值,可使通过模型所做的映射在
具体情况下得到的精度比所期望的要低。
开发一个实用的软件可靠性模型需要大量的理论工作、工具构建以及从实践得来的大量资
料的积累。这项工作通常需要几人年的工作量。相反,应用通过实践建立起来的良好模型只需
要很少的项目组资源。因此我们强烈推荐使用成熟的模型。
有时有人建议对每一个项目应用一系列模型,选择其中表现最好的(或它们的一些加权组
合)。这种方法对于研究调查来说可能是合适的,但是对于实际项目来说,使用多于一个或两个
模型在概念上和经济上都是不实际的。
1.8 问题
1. 我们有一个文本处理软件产品,完全是自己开发的。它必须运行于操作系统1和2上,并
使用打印系统(硬件和软件) A、B、C和D。我们应该测试哪些系统呢?
2. 我们有一个包含5个对象的对象库,它们分别在2 0、1 2、4、2和1个系统中使用。应该选
择哪些对象进行单独测试呢? #p#分页标题#e#
3. 我们的产品使用一个数据库,这个数据库将在系统测试开始前2个星期提交。我们是否应
该对其进行确认测试?
空26 第1 章空
第3章
开发操作剖面
开发操作剖面提供有关用户将怎样部署所建的产品的信息,从而使测试人员可以关注开发
和测试资源。通过这类信息,可以大大提高开发和测试的效率,并且还可以使测试更加实际可
行。本章首先讨论与操作剖面相关的概念,然后分步讨论开发操作剖面的过程( M u s a,1 9 9 2,
1 9 9 3,1 9 9 5 a)。
3.1 概念
需要理解的三个主要术语是操作、操作剖面和操作模式。
操作是一个主要的系统逻辑任务,持续时间短,结束时将控制权还给系统,并且它的处理
与其他操作有显著的不同。这里的主要是指操作应该与功能需求或产品特征(经常是列举出来
的)相关,而不是设计中的子任务。操作是一种逻辑概念,可以跨越一组软件、硬件和人件。
操作可以以一系列片段的形式存在,服务器将每一个片段作为一个进程执行,服务器可以在相
同的或不同的机器上实现。操作可以在非连续的时间段里执行。这里的持续时间较短是指在通
常的负载条件下每小时至少有数百个操作,通常有数千个操作在执行。例如,不能将一架飞机
的飞行轨道定义为一个单独的操作。当一个操作将控制权还给系统后,它释放相关的资源以便
开始一个新操作。
处理上显著的不同是指操作作为一个实体,包含一个在其他操作中不会发现的错误的概率
是很高的。作为一个较粗的指导原则,如果一个操作的处理与其他操作至少有1 0 0行可交付的可
执行的源代码是不同的,那么就认为这个操作在处理上与其他操作有显著不同。这个指导原则
是这样导出的。M u s a、Iannino and Okumoto(1 9 8 7)广泛收集的大量项目中的数据说明,在系
统测试的开始阶段仍然存在的错误平均密度为每1 0 0 0行源代码6个错误。因此平均起来, 1 0 0行
不同的源代码包含0 . 6个错误,也就是说不会在其他地方找到的错误的概率是很高的。因此,对
每个操作至少需要测试一次。在第4 . 2 . 1 . 3节将看到,应该通过对每个操作分配至少一个测试案例
来实现这一点。这可能会使有些很少发生的非关键操作被略过,只要它们的失效不会使得每个
运行的可靠性低于其目标。
只要有可能,对操作的定义就应该使其所包含的处理与一个自然单元所需要的处理近似相
等。操作的发起者可以是用户、另一个系统或者是系统自身的控制器。对于面向对象系统,操
作通常对应于一个用例,尽管有时用例是在更低的层次指定的,比如运行或运行的集合。
一些操作的例子是:
1. 用户执行的命令(例如,在Fone Follower中,输入电话号码),有时由一个用户来指定该
命令的参数的输入屏幕来刻画。
2. 对外部系统输入的反应,例如:
a. 事务处理(例如,采购、销售、送货服务或预定)。
b. 事件处理(例如,报警、机械移动或状态改变;在Fone Follower中,处理一个传真呼
叫)。
3. 由系统自身激活的例行内务管理(例如,安全审计,文件备份,数据库审计或数据库清
理);例如在Fone Follower中,对一段电话号码数据库的一次审计。
操作剖面就是操作的集合及其出现的概率。例如,表3 – 1给出了Fone Follower的系统操作剖
面(由于篇幅限制,只给出一部分)。术语有寻呼和无寻呼表明正在处理的操作依据用户是否拥
有寻呼服务,而成为显著不同的操作。同样,术语有应答和无应答是指被转发方(传送呼叫的
目的地)是否应答;在这两种情况下处理有显著不同。
表3-1 Fone Follower的系统操作剖面
存在每小时操作数概率
处理话音呼叫,无寻呼,有应答18 000 0 . 1 8
处理话音呼叫,无寻呼,无应答17 000 0 . 1 7
处理话音呼叫,有寻呼,有应答17 000 0 . 1 7
处理传真呼叫15 000 0 . 1 5
??
??
??
合计100 000 1
操作剖面的表格表示法对每一个操作都起一个名字,并且每个名字有一个相关的概率。表
格表示法名称的由来在于操作及其相关概率形成一种表格。
图形表示法将每一个操作表示为通过图的一条路径,从而得名为图形表示法。这种图包含
一个节点集,表示操作的属性,还包含分支,表示属性的不同值。每个属性值都有一个相关联
的出现概率。这些出现概率可以是该路径上全面分支的条件概率。请注意,每一个有效属性对
于其属性值都有一个子剖面。因此从一个节点引来的分支的概率和一定是1。要找到某个操作的
出现概率,可通过表示该操作的路径上的所有分支相关联的概率相乘得到。
图3 – 1给出了一个小型分支交换机( P B X)图形表示法的一部分。这是一个电信交换系统,
通常是公司或研究所专用的。在P B X领域,操作的图形表示被称为呼叫树。
属性“拨号类型”刻画了使用中的标准拨号和缩位拨号。缩位拨号使用2位数字码代替通常
号码,对应关系要存放在与电话机相关联的一个文件中。请注意,在这个例子中, 2 0 %的呼叫使
用缩位拨号。“呼叫目的地”属性指出呼叫目的地是在公司或研究所的内部还是外部。请注意,
这里的出现概率是有条件的,它基于拨号类型属性的值,缩位拨号大部分用于内部呼叫; 9 0 %的
缩位拨号是内部的, 1 0 %是外部的。另一方面,对于标准拨号, 3 0 %是内部的, 7 0 %是外部的。
这个P B X中的一个操作使用粗线标出。
请注意:可以从操作剖面的图形表示法生成其表格表示,方法是检查所有可能的路径并将
概率相乘。事实上,这项工作是生成测试案例的步骤之一。
空64 第3 章空
图3-1 PBX的操作剖面(图形表示)
通常以时钟小时来度量操作的出现率。请注意,带有出现率的操作的集合本身并不是操作
剖面。然而将全部出现率除出现率就可以将其很容易地转化为一个操作剖面。出现率形式对于
在测试中重建通信量水平是很方便的。
操作模式是系统使用的独特模式,并且/或者是需要单独测试的环境条件的集合,因为这些
环境条件可能会引起不同的失效。负载测试将被分为操作模式。对于每一个操作模式都需要一 #p#分页标题#e#
个操作剖面。同一个操作可以在不同的操作模式中出现,但其出现概率是不同的。
我们还需要一个系统操作剖面,它包含该系统带有基于所有操作模式的出现概率的完整操
作集合。
所有测试人员都需要知道如何开发操作剖面,因为他们可能会碰到有些没有做过,而又必
须自己做的情况。在许多情况下,系统工程师(可能还有市场和产品管理人员)将要对同预期
用户合作开发操作剖面的工作负责。然而,系统测试人员经常参与甚至领导这项工作;这是有
益处的,因为他们可以确保操作剖面的开发方法能够满足测试的需要。有时,系统工程师开发
操作剖面的第一稿,然后由系统构架师和开发人员对其进行精化。
尽管随着时间推移,可以对操作模式操作剖面进行精化,但如果需要使用操作剖面进行性
能分析的话,在需求阶段将需要初始的版本。同时,需要尽早得到系统操作剖面,以分配资源
和优先级,并支持系统工程师准备操作开发和精简操作软件( R O S)的计划。操作开发是一种
开发方法,即对操作进行排序,在第一个发布版本中实现那些最常用和最关键的操作,而将那
些较少用到和较不关键的操作推迟,其结果就是可以用最快的时间将最重要的能力在市场上推
出。R O S是对硬件精简指令集计算( R I S C)的软件模拟。通过仅实现常用的或关键的操作,并
且使用这些操作来实现较少使用的或较不关键的操作(或者根本不实现这样的操作),可以节约
大量的开发时间和费用。为了分配测试工作量,选择测试并且确定测试进行的顺序,在开始测
试计划时,必须有接近最终版本的操作剖面版本。
空开发操作剖面6 5空
“拨号类型”属性“呼叫目的地”属性
外部=0 . 7
标准=0 . 8
缩位=0 . 2
内部=0 . 3
外部=0 . 1
内部=0 . 9
3.2 过程
对每一个要测试的系统,都必须首先确定其操作模式,这对于产品及其变体,有时还包括
超系统都是相同的。然后确定系统的操作剖面(对所有的操作模式)和每个操作模式的操作剖
面。在测试活动的准备阶段,需要使用系统操作剖面来选择将被创建的测试案例。在执行测试
活动(例如,功能测试和回归测试)时,使用系统操作剖面选择在除了负载测试外的所有其他
测试中要使用的测试案例。要使用每个操作模式操作剖面调用测试案例,以在该操作模式下的
负载测试中执行。
为了开发操作剖面,需要:
1. 确定操作的发起者。
2. 选择表格表示法或图形表示法。
3. 对每一个(操作)发起者建立一张操作“表”并且将结果合并。
4. 确定单个操作或属性值的出现率(每小时)。
5. 总出现率除单个的出现率,得到操作或属性值的出现概率。
所有这5步都在需求阶段开始,在体系结构、设计和实现阶段对其进行反复精化。前面3
步对于不同的操作模式经常产生同样的结果,对于系统本身以及产品之间、产品变体之间、
有时还在超系统之间产生相同的结果。对于这5步来说,新版本经常只需要在前面版本上做少
量修改。
如果对系统的使用有丰富的经验,那么可能没有必要确定操作的发起者。可以直接列举操
作。但是,首先确定操作的发起者通常是一个好的点子,因为考虑操作的发起者会在列举操作
时想到去请教专家,这样就不容易遗漏不考虑操作发起者时就很可能遗忘的操作。
3.2.1 确定操作模式
要根据所使用的操作模式数量,以及将系统操作划分为这些操作模式的确切方式进行工程
判断:更多的操作模式可以增加测试的真实性,但同时也增加了准备和进行系统测试的工作量
和费用。最好的方法,是首先考虑本来可确定单个操作模式因素的所有可能的组合,然后将得
到的结果限制在最常出现的和最关键的操作模式上,这样就可以将开发操作剖面准备测试和执
行测试所需的时间和费用控制在合理的范围内。
可能会产生不同操作模式的一些因素是:
1. 一周的某天或一天的某段时间(主要时间与次要时间)。
2. 一年的某段时间(金融系统的年末财务结算)。
3. 业务量水平。
4. 不同用户类型(可能会以相同的方式使用系统的用户集合)。
5. 用户的经验(专家和新手对系统的使用是不同的);新手倾向于使用更小、更简单的命
令集,而专家可能会更多地使用复杂功能。
6. 系统的成熟度(数据库总数据量)。
空66 第3 章空
7. 精简的系统能力(对所有操作,或只对特定操作)。
对Fone Follower选择三个操作模式:
1. 高峰时段—很大的呼叫和拨号通信量,不执行管理或审计操作。
2. 主要时段—平均的呼叫和拨号通信量,执行管理操作,但不执行审计操作。
3. 低谷时段—较低的呼叫和拨号通信量,较少的管理操作,大量执行审计操作。
管理是指由电话公司的员工执行的功能,例如增加或移除客户。审计是指对数据库中退化
数据的例行、定期检查。使用的方式随时间而改变,这是因为系统对任务的启动是根据呼叫、
拨号、管理和审计的优先级顺序进行的。
在负载测试中,对系统的每种操作模式都要进行测试。按操作模式将负载测试分开,可保
证同时测试那些在不同的使用模式下可能会发生的不同交互的操作,这些不同的交互有可能造
成不同的失效。
3.2.2 确定操作的发起者
操作的发起者包括系统的用户、外部系统和系统自身的控制器。要确定用户,通常首先要
根据像相关系统的系统业务案例和市场数据这样的信息,确定系统的期望客户类型。客户类型
是一组具有相似的业务,因此具有相同用户类型的客户(购买但不一定直接使用该产品的机构
或个人)。客户类型并不一定对应于以销售目的而定义的市场分段,客户也不一定是付款的用户,
可能是机构内部的人。
用户类型是用户(直接使用产品的人)的集合,同一集合中的用户倾向于相同的方式使用
产品。对客户类型进行分析以确定所期望的用户类型,用户类型经常与工作角色高度相关。术
语期望,顾名思义思义,它包含了当前的用户中可能会使用新系统的用户,而排除了当前用户 #p#分页标题#e#
中不会使用新系统的用户,因为他们提供的信息更多地反映了当前的工作过程而不是将来的工
作过程,从而可能是无关的和误导的。最后,因为不同的客户类型可以有相同的用户类型,所
以需要在客户类型之间将用户类型表进行合并。
用户概念,是指可能启动系统操作的任何人,不仅包括系统预期用户,也包括维护和管理
系统的人。但是,阅读报告的管理者是由系统产生的,而不是用户,而在线获得同样数据的管
理者是用户。
下一步,确定当前系统的所有外部并且有可能会在当前系统中启动操作的系统。事件驱动
系统通常有许多可以在其中启动操作的外部系统。最后,检查当前系统自己可能启动的操作。
这些操作通常是典型的管理和维护功能,例如审计和备份。
回到Fone Follower例子上。这个系统的客户类型包括医院和销售机构,医院的用户类型中
包括医生,销售机构的用户类型包括销售人员。这两种用户类型很可能以相同的方式使用系统。
于是,对他们统称为“定户”。运行Fone Follower的电话公司,要把“系统管理员”作为一种用
户类型。
Fone Follower进行接口的主要系统是电话网。可以认为Fone Follower自身也可以启动操作。
这样,我们得到表3 – 2中列出的操作发起者。
空开发操作剖面6 7空
客户类型和用户类型表足以用来确定操作的启
动者。这不需要它们的剖面,因为要直接估计操作
的出现概率。然而,如果是在特定用户的语景下估
计操作的出现概率,那么在组合出现概率时,需要
用户类型剖面。
3.2.3 选择表格还是图形表示法
在这两种表示法之间进行选择并不是那么清晰的。如果大部分操作可以用很少的(通常是1
个或2个)属性来表示,就倾向于使用表格表示法。在表格表示法中通常以其功能来命名操作,
例如Fone Follower中的“连接呼叫”。另一方面,如果大部分操作由许多属性来描述,逐一地考
虑会比较容易,因此应该选择图形表示。
那些可以用相对独立的处理决定的序列来刻画的功能或操作特别适合于图形表示法。请注
意,表格表示法在描述通信交换的某个操作时会很笨拙:即针对缩位拨号呼叫的呼叫处理,拨
打外部网络、应答、候机、最后是摘机通话。
可以有些操作适合表格方式表示,另一些操作适合图形方式表示。例如,尽管之前对F o n e
F o l l o w e r的操作主要用表格表示法,但是其中的一些操作也可以分解为图形。可以在处理语音呼
叫处放置节点,根据是否有寻呼服务而分开。同样,在图形表示法中,可以用表格方式表示一
条有几个节点的路径。
在当前的实际实践中,大部分应用都采用表格表示法。
3.2.4 创建操作表
当创建操作表的时候,以操作的启动者来划分这项任务通常是很方便的,因为某一特定的
操作发起者所需的专门知识通常属于某一特定的人。于是,先对每个启动者建立一张表,然后
再将这些表合并。
为了创建操作表,需要为每个显著不同的处理过程分配一个不同的操作或属性值,除非发
生的概率非常低,并且所完成的是非关键功能。显著不同的处理,是指可能会有不同的失效行
为。与第4 . 2 . 1 . 3节所论述的一样,对每个操作至少要分配一个测试案例,在测试中每个操作至少
要有一个运行,除非其出现概率非常低。于是,对每个具有显著不同的处理过程的情况都要进
行测试,除非它既不关键又不经常发生。在后一种情况下,可能会漏掉某个失效,并因此没有
清除导致失效的错误。然而,系统中遗留一个会导致不经常发生的非关键的失效是可以接受的。
为了列出操作,主要应该参考系统需求。然而,其他资料来源也很重要,因为系统需求通
常都是不完整的。其他有用的信息源还包括不同工作角色的工作过程流程图、用户手册草稿、
原型以及系统的前几个版本。与系统工程师进行讨论可以找出他们在系统要求中遗漏的或者过
时的一些操作。与“典型”预期用户的直接讨论通常很有启迪意义,经常会找出一些被系统工
程师所遗漏的操作。如果选择的是表格表示法,则可以直接列出操作;如果选择的是图形表示
法,则可以通过标出属性和属性值而间接地列出操作。
空68 第3 章空
表3-2 Fone Follower操作发起者
订户
系统管理员
电话网
系统控制器
如果正在开发的软件系统所表示的是某种全部或部分自动化的工作过程,那么以工作流为
基础,包括硬件、软件和人的因素在内,画出图表是很有益的。这种工作过程可表现软件运行
的背景,并且可以提示一些操作。请注意,该过程所要求的不同任务及其出现概率,通常可以
将这些任务与操作联系起来。一种可以帮助定义这个工作过程的有用方法是问这样一个问题:
如何才能对一个新雇员解释清楚什么是必须要做的呢?用户输入对于建立工作过程图表至关重
要。只有那些对当前工作过程具有实践经验的人才能够在所提议的工作过程中发现问题。
原型可以用来作为系统需求的第二验证源,但是必须小心地使用,因为原型通常只实现了
一部分操作。产品的最近版本也可以作为有价值的校验,当然它缺少对下一个版本所计划实现
的新操作。有时可能有用来加强与用户联系的用户手册草稿可以作校验,但是这种用户手册很
可能只是强调了由命令来激活的操作,而不包括由事件或数据激活的操作。
为菜单驱动程序生成操作表的一个很好的方法,是在前一个版本中“遍历菜单树”。然而,
这样可能会产生太多的操作,所以一定要注意将其中一些操作组合起来的可能性。
有一点非常重要,就是要保持操作剖面和需求之间的可追踪性,以便校验,这可保证有一
个完整的需求集,并且所有这些需求在操作剖面中都可得到反映。当需求改变时,当对操作进
行组合或划分时,以及当开发产品的新版本时,可追踪性将会变得特别重要。
如果在确定操作时有困难,通常是因为需求不完整或模糊,需要澄清。
现在从表3 – 2中的操作启动者开始,为Fone Follower建立操作表。操作表列在表3 – 3中。用户
的主要动作是在不同的时间输入其所要的电话号码。系统管理员可以进行大量的操作,不过增 #p#分页标题#e#
加和删除用户当然是主要的操作,外部系统、电话网有可能是操作的主要启动者,因为每个呼
叫都是从电话网传输过来的。有1个操作是处理传真呼叫的。处理语音呼叫的操作有5个,其中3
个处理带有呼服务的用户,另外2个处理无寻呼服务的用户。处理过程会有所不同,这取决于用
户对传递过来的呼叫是否应答,或是当把呼叫传递给寻呼服务后应答。系统控制器定期在通信
流量低的时候对电话号码数据库进行审计。最后,当系统控制器检测到一个硬件失效时,要调
用一个恢复操作。
表3-3 Fone Follower的操作表
操作发起者操作
订户电话号码输入
系统管理员增加订户
删除订户
电话网处理话音呼叫,无寻呼,有应答
处理话音呼叫,无寻呼,无应答
处理话音呼叫,有寻呼,有应答
处理话音呼叫,有寻呼,有对寻呼的应答
处理话音呼叫,有寻呼,无对寻呼的应答
处理传真呼叫
系统控制器审计电话号码数据库
恢复硬件失效
输入一个电话号码和增加或删除一个用户所需的处理量,大体上与处理一个呼叫所需的处
空开发操作剖面6 9空
理量相同。电话号码数据库的审计是分节进行的,所选择的每节大小,可以使其所需的处理量
大约与处理一个呼叫所需的处理量相同。恢复硬件失效可以预期其处理量与处理一次呼叫相同,
因为其处理过程只是确定失效发生的位置,然后将这之前的检查点重新装载。重新装载要花费
一些时间但并不包括处理。于是,所有操作在大小上都是足够近似的,因此任何给定的运行都
表示一个自然单元。
对于图形表示法,仍然从每个启动者开始,但是所建立的是一张图的一部分,而不是一张
表的一部分。考虑一个P B X,呼叫者可作为一个启动者(另一个可能是系统管理员)。确定与呼
叫启动者有关的属性序列,以及每个属性可能的取值,如图3 – 2所示。
图3-2 PBX图形表示的部分“操作表”
因为开发操作剖面是软件可靠性工程的主要开销,而这个开销受该产品或领域(组件或对
象)操作的总数量影响非常大,所以对这个数量进行控制是很重要的。这个数量应该与产品或
领域的预算相关联。产品或领域的每个操作剖面所包含的操作数量,应该与其所包含的系统和
操作模式的相对使用量和关键程度相关联。一个操作剖面所包含的操作数量并不是固定的,但
通常是5 0到几百个。越大的产品可以有越长的表,经常可以扩展到几百个,但极少能够上千。
由于开发预算通常与该产品的预期销售量相关联,从而对于大批量生产的产品来说,较长的操
作表是可行的。换句话说,单独测试产品的更多变体,或定义更多操作模式将是更为可行的。
如果组件被众多产品共享(例如对象),则这些组件可以将自己作为系统进行测试。许多因素会
影响开发操作剖面的费用,不过有一个非常粗略的估计是每个操作大约半个人时。
读者可能会发现,要覆盖所有显著不同的处理过程所需的操作数量,要多于由于考虑到开
销的因素而愿意为其收集有用数据的操作数量。这个问题可以通过为所有显著不同的处理过程
定义足够的操作来解决,这保证了对每种情况都至少有一个测试案例可用。但是,只对高使用
率的操作确定出现概率,从而将开发操作剖面的工作量和费用控制在可以接受的范围内。
随着系统的开发,对系统所定义的操作集可能会变化。这种变化的结果是需要调整操作剖
空70 第3 章空
“拨号类型”属性“呼叫目的地”属性
外部
标准
缩位
内部
外部
内部
面。通常这种情况发生的原因在于对需求的细化,或体系结构的开发所带来的新信息。最一般
的直接原因在于操作体系结构(在现场环境中为了完成工作而调用的操作结构及其之间的关系)
的变化,对资源分配或测试真实性进行控制所需的粒度,或处理差异方面的知识。
如果决定把一个操作分成两个单独启动的操作,以通过推迟其中一些可以推迟的任务而减
少某一特定操作的响应时间,那么操作体系结构就可能发生变化。请注意,简单地在时间上分
成两个任务并不是将操作分为两个操作。在操作体系结构和确定模块和子系统是如何组合进系
统的系统体系结构之间有一定的相关性,但极少是完全相关的。
决定是否要对表进行修改的评判准则,是改变操作的粒度所得到的好处是否明显大于其费用
(以工程观点判断)。粒度上的每一个改变都需要一些(通常很少)费用和发布日期的推迟,因为
当操作表改变时,必须重新计算与之相关联的操作剖面。第3 . 3 . 1节将解释如何更新出现概率。
如果操作太多,可能会想要把其中一些操作分组。分在同组的操作应该具有相同的输入变
量,从而可以为这个领域建立通用的有效测试方法。但是不必把所有具有相同输入变量的操作
都放在一组。如果一个或多个输入变量的值或值域可以很容易地确定,并且出现概率有很大不
同,那么可以相应地定义多个操作以区分应用的测试的量。
选择区分操作的程度是在分配资源和优先级之间灵活性的一种平衡,越详细的剖面可以使
分配资源和设置优先级具有更强的灵活性,但同时收集和分析更详细的数据以及管理需要更多
的费用。在实践中,因为在较早的设计阶段就完成了操作剖面,可用的信息限制了当时操作表
可以达到的精细程度。
考虑一些别的方法来定义以A 和B 为参数的命令X,参数A 的值可以是A1 或A2,参数B
的值可以是B1、B2 或B3。假设设置参数A 对所执行代码的影响比参数B 要大得多,那么有两
种可能:
1. 一个操作X,包含了参数值的所有集合。
2. 两个操作,即X A1 B 和X A2 B;这种情况在分开操作的时候只考虑A 的不同参数值。
最好不要定义六个操作, X A1 B1、X A1 B2、X A1 B3、X A2 B1、X A2 B2 和X A2 B3,每
组参数值是一个单独操作,因为参数B 的取值对所执行代码的影响并不大。在所有三种情况下,
都有六种方式执行X,惟一的差别是如何组织这些方式。
我们前面曾经做了一个保守的假设,即所有启动者和所启动的全部操作都可能在操作表中 #p#分页标题#e#
出现。但是,我们最终会发现,在高峰时段的操作模式中,一些管理操作的出现概率为0,这是
由于给予客户操作的优先级高于管理操作的优先级。
对操作的区分不依赖于确保操作表合理的完整性的任务。检查操作表是否完整的一种好方
法,是检查输入空间以确保它被很好地覆盖。一个程序的输入空间是指在其运行中可以发生的
输入状态的集合,或输入变量值的集合。这个集合不是无限的,但是对任何有实际意义的程序
来说,输入空间的尺寸都是天文数字。许多程序可以对错误的输入作出一些推理反应,这就扩
展了在一个程序必须作出反应并必须被测试的所要求的输入空间,而原来的设计输入空间是在
程序功能构建时确定的。没有落在设计输入空间的所要求输入空间部分,包含具有很容易造成
失效的输入状态,除非程序中做合适的处理。尽管在定义操作表时可以考虑环境变量,但通常
是以长时间的测试来处理。这种经过简化的方法似乎很起作用,这可能是因为环境变量要随时
空开发操作剖面7 1空
间变化的。
在定义输入空间时,最重要的是开发出一张在实践意义上完整的输入变量的列表。这样的
列表要给出所有输入变量,那些以非常高的概率取某个值的变量除外。在这种情况下,可忽略
并且不测试该变量的其他取值,除非其他取值中的一个或一些与其他变量的某些取值一起定义
了一个关键运行。忽略其他取值是可以接受的,因为它们出现的概率极小,即使出现失效对可
靠性也几乎没有影响。这要求系统具有高可靠性。
如果遗漏了会显著影响程序操作的输入变量,就不能清楚地标识运行,因此也不能标识错
误的输入状态。这使得无歧义地重现失效或成功的行为变成不可能。例如,有些变量对某个运
行的影响并不明显,除非它与其他运行发生交互作用,这时就可能将这些输入变量漏掉。与其
等待这样的交互作用,不如有意识地标识“间接”输入变量。第4章将讨论这样的变量。
描绘所要求的输入空间可能是件困难并且耗时的工作,特别是当输入状态对输入变量的特
定值的出现概率非零的时候。反之,可以通过只列出所需的输入变量来定义一个专门的输入空
间。假设每个输入变量都可以取任何可能的值(有限数量,以机器表示的范围和粒度为基础),
并且忽略所浪费的测试资源,因为一些输入状态的出现概率为零。这个专门的输入空间将比所
需的输入空间覆盖的范围更大,并且更容易定义和为之选择测试。
通过定义操作覆盖输入空间时,可以不需覆盖的输入空间的量依赖于系统可靠性目标。如
果一个运行的可靠性目标是RF,则覆盖率(已经定义的操作出现概率的和)必须至少是RF。例
如,如果对每次运行要求的可靠性目标为0 . 9 9,那么覆盖率必须至少是0 . 9 9。请注意,这提供了
一个通过清除那些极少发生的操作来减少操作总量的机会。不过,这样做只能是在已经投入工
作量以得到出现概率之后,除非事先已经知道某些操作会极少发生。然而,事后减少操作的数
量仍然是有价值的,因为可以避免向它们分配测试案例,从而可以节约测试案例资源投入其他
方面。理论上可以除去那些出现概率小于1减去每个运行的可靠性目标的非关键操作。然而,为
了留出一定的错误余量,可以限制到那个值的(例如)一半。于是,如果每个运行的可靠性目
标为0 . 9 9,则允许除去那些出现概率小于0 . 0 0 5的非关键操作。
所定义的操作集合应该包含所有关键操作,即使它们的使用率很低。为了增加将所有关键
操作包含进来的可能性,应该关注那些如果没有成功完成就会产生严重后果的操作,并特别注
意它们执行时的所有环境条件。检查以前的或相关系统的严重失效,常常有助于确定这种环境
条件。第4 . 2 . 1 . 3节将会介绍,对每个关键操作都要至少分配一个测试案例,以确保能够被测试。
从而关键性的失效不大可能(尽管没有什么可以肯定发生)被漏过。
如果使用表格表示法并且有多个操作模式时,一张电子表对于组织操作表和发生频率以及
后来的概率时是很有用的。
有一点非常重要,就是要在操作表中包含一些重新初始化或者清理数据库(随着要执行越
来越多的面向用户的功能,数据库可能会逐渐退化)的内务操作,否则这些功能执行时的数据
环境将不能反映真实情况。
3.2.5 确定出现率
许多初次实施软件可靠性工程的人都认为确定操作的出现率是非常困难的;但是经验表明,
空72 第3 章空
难度要比大家想像的小得多( M u s a,1 9 9 7 a,1 9 9 7 b,1 9 9 7 e;M u s a、F i o c o、I r v i n g、Kropfl and
J u h l i n,1 9 9 6)。使用真实的现场数据是最好的,通过通常是机器可读的系统日志也可以进行度
量。很多时候,这样的数据对于相同或相似的系统已经存在了,可能是以前的版本,也可能是
正在进行自动化的人工系统。如果都没有,也可以自己收集,尽管这应该是第二选择,因为这
当然需要费用。如果操作是事件驱动的,则可以模拟确定了事件频率的环境。最后,即使没有
直接的数据,通常还是会有一些相关信息可以用来做合理的估计。如果绝对没有任何信息用以
估计操作的相对的出现率,那么就让这些出现率都相等。
如果所选择的是表格表示法,就需要确定操作的出现率。如果所选择的是图形表示法,就
需要确定属性值的出现率。操作或操作的属性值的出现率通常相对于时间来度量。
为了说明操作的出现率数据,在表3 – 4中给出了Fone Follower的系统(所有操作模式的平均)
出现率。在图3 – 3中给出了P B X的图形表示法中的属性值出现率。
表3-4 Fone Follower表格表示法的系统出现率
操作出现率(每小时操作个数)
电话号码输入10 000
增加订户5 0
删除订户5 0
处理话音呼叫,无寻呼,有应答18 000
处理话音呼叫,无寻呼,无应答17 000
处理话音呼叫,有寻呼,有应答17 000
处理话音呼叫,有寻呼,有对寻呼的应答12 000
处理话音呼叫,有寻呼,无对寻呼的应答10 000
处理传真呼叫15 000
电话号码数据库审计9 0 0
硬件失效恢复0 . 1 #p#分页标题#e#
合计100 000
图3-3 PBX图形表示法中的属性出现率
空开发操作剖面7 3空
“拨号类型”属性“呼叫目的地”属性
外部=5 6 0
标准=8 0 0
缩位= 2 0 0
合计=1 0 0 0
内部=2 4 0
合计=8 0 0
外部=2 0
内部=1 8 0
合计=2 0 0
在计算出现率时,不要把填空发生计算在内。填空发生是高于正常系统操作所要求的最小
值的操作的一个执行实例。许多系统被设计为当没有其他事做时,执行一些例如维护功能(称
为填空操作)的操作。这是有意义的,因为这样就利用了一些原本会被浪费的资源,而使得系
统操作有一些小的改进。然而计算这些填空发生可能会使操作剖面失真,从而使测试失真。
例如,对于Fone Follower,允许数据库审计操作使用系统的任何空闲时间。由于在晚上和
周未会有大量空闲时间,审计操作的出现率很自然地达到0 . 9 5。然而,它需要的出现率仅为
0 . 0 0 9,如果在确定系统操作剖面时使用前一个出现概率,那么就需要将9 5 %的测试时间给它。
这当然是完全不合适的。
如果正在度量的是现场数据,需要额外小心,以保证度量活动确实划算,并且没有忽略其
他更简单的方法,特别是当所面对的是构建专门的记录和度量工具的时候。例如,针对某个软
件产品的第一版,使用元素和准确性都适中的简单操作剖面。对于以后版本,只有当在现场发
现通过测试得来的可靠性投影是错误的时候,才需要对操作剖面进行精化。
为操作开发可以记录的软件可能要费些工夫,但是可以开发一个一般的记录例程,每个应
用只需要一个接口。系统的记录软件必须可以抽取有关输入变量的足够数据,用来识别正在执
行的操作。那么,对每个操作就只是一个统计其执行次数的问题了。可以用表格或图形表示法
记录操作剖面,只记录操作的使用要比记录完整的输入状态容易得多,因为所包含的数据要少
得多。
记录的过程通常不会给应用增加太多的负担。因为现场数据对于开发操作剖面非常重要,
记录现场数据的负担也相对很低,因此在所开发的基于软件系统中加入记录操作的功能会是一
个好主意。在很多情况下,从整个用户群收集数据是可能的,在对用户采样过程中,在选举和
市场调查中使用的指标和统计理论同样可以应用;一个包含3 0个或更少用户的抽样可能就足够
产生一个具有可接受精度的操作剖面。
对于在已经存在的系统中加入的新系统或新操作,由已确定的出现率可以得出操作剖面,
已经记录下来的关于操作的使用数据也可以起帮助作用。通常最好是由一个经验丰富的系统工
程师来估计出现率,这位工程师要对该领域、用户需求和用户将如何利用新的操作,有全面的
理解。让有经验的用户来检查这些估计也是很重要的。通常,新的操作实现了以前由人工或其
他系统所完成的过程,所以,可能会有一些可用的数据来提高估计的精确性。让用户直接参与
估计出现率的过程通常是有用的。这可以通过调查问卷进行,不过应用D e l p h i技术(专家先提出
个人估计,然后由专家组进行修改)在专家组环境下通常是水准较高的。当必须估计使用情况
时,建立并评审当前系统所支持的整体工作进程图通常是会有帮助的。
当一个系统的操作剖面依赖于在另一个相关系统中所发生事件的频率时,模拟第二个系统,
对估计事件频率可能是有帮助的。例如,如果一个监视系统的操作剖面依赖于被监视系统中发
生的特定情况的频率,就可以模拟这些被监视系统的操作。
由以前的数据计算得来的出现率必须进行调整,以便说明新操作、新环境和由于其他因素
引起的变化。大多数系统都是由以前的版本加上新操作混合而成的,需要对这些系统估计其使
用情况。尽管估计不如度量精确,但由于新操作的比例通常很小,可能是5 % ~ 2 0 %,所以整体操
作剖面的精度还应该是比较好的。
空74 第3 章空
一般来说,对单个操作,应该确定在当前软件版本生命中的平均出现率。如果想要考虑操
作剖面随时间的变化情况,通常最好是根据需要定义额外操作模式,并且为每个操作模式确定
出现率。
不同操作模式中的出现率通常是不同的,特别是当负载/能力比不同并且操作被赋予选择优
先级的时候。例如,如果操作正在等待处理器的执行队列中,并且队列顺序依赖于操作的类型
(维护操作的优先级可能低于警报操作),那么负载总量将会影响操作中的相对混合量,较重的
负载会使维护操作的发生比例较小。
在确定操作剖面时,不需要特别精确,于是经常可以节省收集数据所需的工作。在出现率
中给定的差错比例,在分配资源时会造成同样的差错比例。对失效强度的度量相对于出现率的
差错和变体一般是非常健壮的。在大多数情况下,出现率的给定差错在失效强度中造成较低的
差错比例。失效强度的差错对于出现率最大的操作、大的正相关的错误以及那些趋向于不一致
的操作剖面来说是最大的。M u s a(1 9 9 4 a)指出,平均来讲,失效强度的差错比大约是出现概率
差错的2 0 %。C r e s p o,Matrella and Pasquini(1 9 9 6)所做的一项研究也说明,操作剖面中的差
错不会对可靠性估计产生很大的影响。
在极少情况下,系统是全新的并且所有操作从来都没有执行过,甚至连一个相似的系统或
手工系统都没有,它的操作剖面会是很不精确的。然而,操作剖面仍然是所拥有的关于客户的
最好的说明,因此也是有价值的。
单独预测使用情况的过程,很可能是市场研究的一部分,是极为重要的,因为它所要求的
与客户的交互突出了操作的相对价值。它很可能会导致放弃某些操作而加强其他操作,结果会
产生一个更有竞争力的产品。减少那些极少使用的操作方法,精简操作软件( R O S),可以增加
可靠性,加快交付时间,并且减低费用( M u s a,1 9 9 1 b)。
3.2.6 确定出现概率
在表格表示法中,为了确定操作的出现概率,需要将每个操作的出现率除以总出现率。在
图形表示法中,为了确定属性值出现率,需要将每个属性值的出现率除以该属性的总出现率。 #p#分页标题#e#
操作或属性值的出现概率通常都会随操作模式变化,尽管属性或属性值本身不会变化。我
们把图形表示法中的概率,表示为条件概率,而不是结合起来的概率,这是因为当工程师必须
估计概率时,条件概率更容易与工程师们的判断相联系。
表3 – 5给出了Fone Follower的操作的系统出现概率的表格表示法。表中的操作按概率降序排
列。这是习惯上采用的顺序,这种形式的操作剖面特别适合工程师和管理者使用。
表3-5 Fone Follower系统出现概率
操作出现概率
处理话音呼叫,无寻呼,有应答0 . 1 8
处理话音呼叫,无寻呼,无应答0 . 1 7
处理话音呼叫,有寻呼,有应答0 . 1 7
处理传真呼叫0 . 1 5
处理话音呼叫,有寻呼,有对寻呼的应答0 . 1 2
空开发操作剖面7 5空
(续)
操作出现概率
处理话音呼叫,有寻呼,无对寻呼的应答0 . 1 0
电话号码输入0 . 1 0
电话号码数据库审计0 . 0 0 9
增加订户0 . 0 0 0 5
删除订户0 . 0 0 0 5
硬件失效恢复0 . 0 0 0 0 0 1
合计1 . 0
回忆2 . 2 . 4节,Fone Follower的失效强度目标是每1百万次呼叫发生9 5个失效。于是,这个软
件每次呼叫的可靠性目标是0 . 9 9 9 9 0 5。因此可以安全地除去那些出现概率总计为0 . 0 0 0 0 5的非关
键操作。没有一个非关键操作的集合满足这个标准。
图3 – 4中给出了P B X图形表示法的属性值出现概率。
图3-4 PBX图形表示法的属性值出现概率
3.3 特殊情况
有些时候,随着系统的开发,对操作的定义可以发生变化。下面讨论了作为其结果,操作
剖面必须要做怎样的调整。本节还将讨论模块使用表,当需要在模块间分配设计、编码、代码
审查、单元测试以及其他资源的时候,模块使用表将是有用的。
3.3.1 系统开发期间操作定义进化的处理
3 . 2 . 4节曾经指出,偶而需要将为某个操作集合或属性值网络开发的操作剖面转换为一个由
空76 第3 章空
“拨号类型”属性“呼叫目的地”属性
外部=0 . 7
标准=0 . 8
缩位=0 . 2
合计=1 . 0
内部=0 . 3
合计=1 . 0
外部=0 . 1
内部=0 . 9
合计=1 . 0
前面的操作集合或网络发展而来的第二个操作集合和网络的操作剖面。为了简单起见,对于正
在发展成为别的操作或属性值的某个操作或属性值,我们使用操作这个术语来统一表示。
考虑下面一个例子,具有操作A、B和C的系统,进化成为具有操作W、X、Y和Z的系统,
初始操作剖面列在表3 – 6中。
表3-6 初始操作剖面
操作出现概率
A 0 . 5 4
B 0 . 3 6
C 0 . 1
假定在进化后的系统中,原来的操作A始终由操作W代替, 2 0 %的时间由操作Y代替。类似
地,操作B始终由W代替,2 0 %由X代替,1 0 %由Y代替。操作C始终由Z代替。表3 – 7说明了这种
映射。这个格式正巧也可以用来处理这种类型的其他问题。
表3-7 操作列表的映射
以前的操作
A B C
出现概率0 . 5 4 0 . 3 6 0 . 1
后操作
W 1 1
X 0 . 2
Y 0 . 2 0 . 1
Z 1
为了对新的操作剖面确定出现概率,首先要根据每个旧操作映射到新操作上的比例来计算
旧操作的权重,然后如表3 – 8所示把它们加起来。这样就得到了新操作的初始出现“概率”。然
而,总的初始出现概率大于1,所以必须把每个初始出现概率除以总的初始出现概率。
表3-8 新的操作剖面
以前的操作
A B C
出现概率0 . 5 4 0 . 3 6 0 . 1
后操作初始出现概率最终出现概率
W 0 . 5 4 0 . 3 6 0 . 9 0 . 7 4 0
X 0 . 0 7 2 0 . 0 7 2 0 . 0 5 9
Y 0 . 1 0 8 0 . 0 3 6 0 . 1 4 4 0 . 11 9
Z 0 . 1 0 . 1 0 . 0 8 2
合计1 . 2 1 6 1
空开发操作剖面7 7空
3.3.2 应用模块使用表
模块使用表可以用来表示程序模块的相对使用情况。模块使用表是包含所有程序模块的列
表,标出每个模块在任一给定操作中的使用概率。在与模块相关的工作中分配资源和赋予优先
级时,可以模块使用表为基础。模块使用表不是剖面,因为模块的使用并不是不相交的;出现
率相加起来也不需要等于1。
可以通过操作剖面和操作使用矩阵来建立模块使用表。操作-模块矩阵指出了哪些操作使
用了哪些模块。表3 – 9是一个操作-模块矩阵的例子,它所基于的系统操作剖面在表3 – 8中给出。
请注意,操作W使用模块1和3;X使用2,3和4;等等。
表3-9 样本操作-模块矩阵
模块
操作1 2 3 4
W 1 0 1 0
X 0 1 1 1
Y 1 1 0 0
Z 0 0 1 1
以qj 表示模块出现概率, pi 表示操作出现概率。则有:
(3 . 1)
其中,如果模块j 被操作i 使用,那么ai j 为1。对应于由表3 – 8和表3 – 9定义的系统的模块使
用表列在表3 – 1 0中。
表3-10 模块使用表
模块出现概率
1 0 . 8 5 9
2 0 . 1 7 8
3 0 . 8 8 1
4 0 . 1 4 1
3.4 常见问题
现在讨论一些经常被问到的问题。这些问题关于操作剖面的使用、与之相关的概念以及开
发和应用操作剖面的活动。
3.4.1 使用
1. 操作剖面在软件可靠性工程之外还有其他的应用吗?
qj = aij pi
i ?
空78 第3 章空
答:是的,只要需要对一个系统是怎样的以及它会怎样被使用做出定量的描述,就可以应
用操作剖面。例如,可以在性能评价中使用。操作剖面对于在何处需要集中开发资源具有指导
作用。与精简指令集计算( R I S C)的软件类似,操作剖面可以作为降低软件费用并加快交付日
期的基础。这种软件类似称为精简操作软件( R O S),可以作为人机界面设计的指导原则:应该
把最常使用的操作设计为学起来最容易、使用起来最简单的操作。操作剖面还可以指导用户手
册的组织,应该把最常使用的操作放在前面。因为操作剖面重点突出了系统的操作,使得功能
扩张清淅可见,从而可以尽量避免出现这种情况。功能扩张是一种不断加入新操作(其中许多 #p#分页标题#e#
操作很少会用到)的不希望出现的趋势。
2. 可以将操作剖面的概念用于硬件吗?
答:是的。事实上,对于某些类型的硬件失效,操作剖面有可能表现为一种非常有用的方
法。硬件包含许多只在特定使用情况(操作或运行)下才会造成失效的缺陷(错误)。操作剖面
和软件可靠性理论有助于深入了解这类失效。
3. 操作剖面概念对于回归测试有用吗?
答:绝对有用。在维持高水平的可靠性时,如果所包含的都是最经常使用的操作,那么回
归测试将会是最划算的。
4. 如果将精简操作软件( R O S)的概念应用于工程中的一个产品,可以节约软件开发的费
用吗?
答:是的,因为所需要的开发和系统测试的工作量是与所实现的功能数量相关的。
5. 操作剖面的形式与使用它来提高生产率的能力有关系吗?
答:有,高度不均匀的形式能提供更多机会以将开发资源集中于最常用的功能。
6. 确定操作剖面过程中的错误对于可靠性度量会产生什么样的影响?
答:失效强度(可靠性)通常很健壮,受确定操作剖面过程中的错误的影响不会很大。
7. 为什么说开发操作剖面的费用是软件可靠性工程中的主要花费?为什么不是准备测试案
例的费用?
答:无论做的是什么样的测试,都必须准备测试案例。在这里,只考虑软件可靠性工程与
其他测试方法不同的活动的成本是合理的。
8. 应用软件可靠性工程怎样才能发现被遗漏的需求?我没有发现它们之间有联系。
答:这与软件开发文化更有关系,而不是逻辑的关系。一些软件系统工程师、构架师和设
计人员开始开发工作时,心里想的都是怎样应用新技术,而不是用户需要做什么。软件可靠性
工程将操作剖面的开发作为其完整过程的一部分。为了合适地开发操作剖面,必须以训练有素
的方法与用户进行交流,这样就更可能找到用户所需的所有操作以及操作的出现概率。因此,
就更可能发现在其他情况下可能会漏掉的所需操作。
9. 开发操作剖面可以改善产品定义吗?怎样改善?
答:是的。开发操作剖面将注意力集中于用户将会怎样使用产品,以及不同用户的相对重要
性。这可以指导合理地分配开发资源,可以有助于更好地以用户期望的价格来定义和设计产品。
10. 对于新版本,需要开发操作剖面和测试案例来测试它,为什么不能记录以前的现场运行
的输入状态,然后再重放一遍?
空开发操作剖面7 9空
答:这通常不是实用方法。新版本总是会有新功能(除了极少情况的“仅是清除错误”的
发布版本),从而有新的操作,所以必须为它们建立测试案例。不仅如此,记录那些极少发生的
关键运行的机会是很少的,所以也必须为它们建立测试案例。新版本的操作剖面将是不同的,
因此必须开发。
最后,记录现场运行的时候,要想避免偏差是相当困难的。例如,如果在某个具体时间、
具体地点进行记录工作,那么一些特别环境条件,例如长时间的运行,就会使测试案例的记录
发生偏差。避免这种偏差的惟一方法是随机地对大量地点、大段时间的运行记录进行选择。这
样做的成本可能大大超过了从头开发测试案例的成本。
11. 怎样将操作剖面应用于领域工程?
答:通常是在开发那些将会在很多不同的系统中使用的组件时使用领域工程。对于这样的
组件,开发操作剖面的过程与其他系统是相同的,惟一的区别在于,对于这样的组件要进行宽
范围的分析,以了解它们将以怎样不同的方式被使用。
3.4.2 概念
1. 获得不同任务的可靠性与操作剖面有什么联系?
答:可以将任务看作组成操作剖面中操作的一个子集。度量根据该操作子集按照相对出现
概率的测试,可以得到每个任务的可靠性。如果任务的操作集合之间有重叠,对于属于两个或
多个任务的操作,就需要在多个任务之间分配其出现概率。可以通过带权重的平均任务可靠性,
确定所有任务的总可靠性,其中的权重为任务的出现概率。请记住,这样度量得到的可靠性精
度会有所降低,因为每个任务对应的失效样本数要小于整个系统的失效样本数。因此,我们不
推荐使用这种方法。
2. 客户开始使用新功能的方式会怎样影响操作剖面呢?
答:在操作剖面稳定之前,可能会有一个过渡。对于由命令驱动的系统,也就是那些对功
能的选择主要依赖于用户输入的系统,最好首先使用最基本、最易学的功能,然后逐步使用更
复杂的功能。同样,用户更可能较晚地使用那些新加入到系统中的功能。这种过渡在操作的早
期可能会造成可靠性度量的不精确,特别是由命令驱动的系统。因此,对于这类系统,应该注
意在稳定阶段度量,或者对过渡阶段进行补偿。
3. 功能与输入空间有什么联系吗?
答:有。功能与输入空间的大小有联系。软件的功能越强,其输入空间就越大。
4. 输入空间的概念是否真的刻画了某个程序在其中运行的所有不同环境?
答:是的,但是输入变量可以是直接的(假定该程序被设计为在所有这样的环境中运行),
也可以是间接的(如果不是那样)。
5. 是否要将运行组成操作,以便对每个操作只执行一个测试案例?
答:将运行组合为操作并不意味着对每个操作只选择一个测试,这只是提供了一个可以非均
匀地在输入空间中取样的框架。如果随机地根据操作剖面选择操作,然后在操作中随机地选择运
行,那么就是选择了匹配操作剖面的非均匀随机测试。如果某个重要的输入变量值已知是非均匀
分布的,可能希望采用以上介绍评判准则确定选择值的范围,然后使用变量值来定义操作。
空80 第3 章空
6. 是否存在“运行剖面”这类东西?
答:在理论上可以开发一个由运行集合和运行所对应的概率组成的运行剖面。执行所有的
运行可以达到理想的完全测试。这当然是不切实际的,不过这个概念在考虑对运行集合进行采
样的不同策略时,可能会有帮助。
7. 某个环境条件可以成为操作的启动者吗?
答:只会间接地,通过某个可以感知这个条件的系统来发起操作。
8. 开发操作剖面怎么会是实际的呢?能够使用一个程序的方法个数可以是天文数字。谁能
够对所有这些来确定出现概率呢? #p#分页标题#e#
答:操作剖面所基于的操作个数通常不超过几百个。根据操作所做的处理的不同,它们之
间差别很大。在一个操作内,有许多可能的不同的输入状态,每一个都可能引起细微的不同的
处理。我们并不在一个操作内部确定出现率,而是以均匀的概率选择不同的运行。
9. 两个不同的操作可以执行某些相同的模块吗?
答:可以。
10. 列举出来的功能性需求对操作剖面有什么有影响吗?如果有,是什么影响?
答:功能性需求的枚举,通常意味着需要将功能性需求与实现它们的代码和验证它们的测
试案例联系起来。枚举可提高可追踪性。因此,枚举出来的需求应该相当重要,需要将对应的
操作列入操作剖面。
11. 非功能性需求可以提出操作吗?
答:否。非功能性需求提出的是诸如可靠性、进度、费用目标、文档内容及格式和改变控
制过程之类的内容。
12. 可以混合使用表格和图形表示法吗?在我们的一个系统中,有些操作以多个属性来描述,
有些以单属性来描述。
答:是的。可以将具有单属性的操作加入到图形表示法中,作为没有子节点的单分支路经。
同样,也可以将图形表示法中只有单分支节点的路径作为操作加入到表格表示法中。后一种方
法对于关键操作特别方便,使用图形表示法可以更加方便地处理关键操作。
3.4.3 应用
1. 回归测试会妨碍根据操作剖面进行测试吗?
答:不会。事实上,如果根据操作剖面进行测试的话,回归测试会更有效。
2. 怎样处理不停地随时间变化的操作剖面呢?
答:将操作剖面表示为两个组件操作剖面的加权和。其中一个组件的权重以时间的函数来
表示(另一个的权重就是1减去第一个权重)。确定两个不同的组件操作剖面的失效强度l1 和l2。
于是,总的失效强度可由下式给出:
l=r(t)l1+(1-r(t))l2 (3 . 2)
其中,r(t)是第一个组件的权重, t 是时间。像这样的一个操作剖面只是在调用测试案例时使
用。为了选择测试案例,应该使用时间的平均值。
空开发操作剖面8 1空
3. 我们有一个基于数据库的系统,实效的一个重要影响是造成数据库的退化。这可能会增加
其他失效发生的可能性。这种相互作用在定义操作剖面和度量软件可靠性的时候会造成问题吗?
答:通常在开发操作剖面时不考虑数据的退化。应该在负载测试中处理这种问题,在现场
需要多少可能的相同数据清理过程,就精确地重现多少过程,而这些过程可能是定期的(例如
每日的重启动),也可能是连续的。
4. 将运行组成操作时,可以使用什么方法呢?
答:通常,需要寻找具有紧密相关的功能的运行,或是执行相同或相近的代码路径的运行。
例如,在飞机订座系统中,可以将所有的“单边”旅行(波士顿—纽约,芝加哥—纽约,芝加
哥—丹佛,旧金山—洛杉矶)组合起来。这个方法对于独立的测试小组可能是最好的。不使用这
种方法,小组必须通过对程序的研究得到关于程序结构的知识,并且将运行映射到程序结构上。
5. 怎样估计操作剖面中没有被测试覆盖到的部分?
答:如果全部或几乎全部在测试中发现的失效都被解决了,那么在这之后的操作中发现的
失效就指示了操作剖面中遗漏的那一部分。假定操作中的失效强度是系统测试开始时的2 %。于
是,假定操作剖面保持不变,遗漏运行的出现率之和至少是0 . 0 2。
6. 对于正确输入的命令,可以很容易地定义操作剖面,但是对错误的输入,怎么定义呢?
答:应该不需要为了处理错误的输入而定义单独的操作,但是在关于某个操作的测试案例
中应该包括它们。最好的方法是从人员因素的角度来看某个系统,使用关于人员出错的特性和
频率的研究,来帮助获取测试案例中包含错误输入的比例。当为某个操作选择测试案例的时候,
选择合适的错误输入比例。
7. 我们正在开发一个将要在一系列一次性任务中使用的系统。这是一个操作控制中心,要
在不同的深度空间飞行器上使用。我们该如何定义其操作剖面呢?
答:应该对每个任务建立一个不同的操作剖面,然而这可能很费时间而且也没有必要。可
能可以定义对大多数或所有任务都使用的功能,并且开发一个总的操作剖面,这可以节约很大
的工作量。
8. 如果不同操作的持续时间差别很大,是否需要对操作剖面做一些专门的处理?
答:可能不需要,因为操作剖面仍然反映不同操作被启动的概率,从而可重现真实的现场
环境。但是,有些操作可能会被定义得太长了。
9. 我们想收集产品被怎样使用的现场数据,以便确定不同操作模式的操作剖面。但是,在
使用中的产品所处的安装平台太多了,收集所有数据的成本太高了。应该怎么办?
答:随机选择一个安装样本,然后收集这些样本的数据。
10. 现场的失效数据对确定操作剖面的出现概率有帮助吗?我们一般通过用户报告得到这部
分数据,但是让用户收集使用数据要困难得多。
答:是的,有帮助。尽管不如直接得到的使用数据精确。请注意,如果错误均匀地分布在
代码中,并且各种运行的长度几乎相等,那么每个操作经历的失效比例将等于它的出现概率,
从而可以被用作出现概率的一个估计。对于大多数系统,均匀分布的假设都是有效的。均匀的
运行长度可能不是这样,不过可以通过调整失效数据来补偿。用户的报告通常是与失效相关的,
不过也可能有不相关的因素起作用。因此所得到的关于出现概率的估计只能是近似的。
空82 第3 章空
11. 我们是否应该挑选操作来表示由用户启动的工作段或完整的工作序列?
答:如果用户几乎总是启动标准的工作序列,并且很少发起单独的工作段,那么将工作序
列定义为操作。如果用户几乎总是启动工作段,并且段之间相互独立,那么将工作段定义为操
作。如果用户发起工作段,但是它们之间有很多依赖关系可以考虑将操作定义为工作序列,并
且在操作剖面中使用图形表示法,其中工作段以图中的分支来表示。
12. 我们正在开发一套软件包,它要与许多不同的生产商提供的硬件和软件组件一起工作。
测试每一种可能的组合是不切实际的。是否有合理的方法可以减少需要测试的组合数量? #p#分页标题#e#
答:是的。确定与每种组件的选择相关的用户比例。将这些比例乘起来以确定使用每种配
置的用户比例。然后只测试那些具有最高使用比例的配置。例如,假没某软件具有如表3 – 11所示
的接口组件的选择,用户比例也列在其中。
表3 – 11 一部分用户的组件和组件选项
选项
组件1 2 3 4 5
个人计算机(硬件) 0 . 3 0 0 . 2 5 0 . 2 5 0 . 1 5 0 . 0 5
操作系统0 . 9 0 0 . 0 8 0 . 0 2
数据库0 . 7 0 0 . 2 5 0 . 0 5
共有4 5种可能的配置,但其中2 0 %(9)表示了8 4 %的用户,如表3 – 1 2所示。如果只测试这9
个配置,可以大量地减少测试量。另一种方法是也测试一些较少使用的配置,但只使用有限的
包含最常用操作的操作剖面。
表3-12 最常使用配置
配置
个人计算机操作系统数据库使用比例
1 1 1 0 . 1 8 9
2 1 1 0 . 1 5 7 5
3 1 1 0 . 1 5 7 5
4 1 1 0 . 0 9 4 5
1 1 2 0 . 0 6 7 5
2 1 2 0 . 0 5 6 2 5
3 1 2 0 . 0 5 6 2 5
4 1 2 0 . 0 3 3 7 5
5 1 1 0 . 0 3 1 5
13. 为什么操作的出现率是以时钟时间而不是以执行时间来度量?
答:以时钟时间来度量操作的出现率,是因为在测试中调用运行时使用的是时钟时间。
14. 在我们的系统中,许多操作是有限制的,这些操作只能由某些特定类型的用户来启动。
这会影响我们开发操作剖面的方式吗?
答:不会。对每个操作,每个启动者的案例会减少,但这并不会影响开发操作剖面的过程。
15. 在某些情况下,是否绝对不能将两个操作模式合并为一个?
空开发操作剖面8 3空
答:是的。如果在一个模式下的操作与另一个模式下的操作实际上完全不同,那么将两种
模式合并将产生许多在现场条件下不会发生的交互作用和可能的失效。这会浪费宝贵的测试和
调试时间和资金。
16. 我们有几个产品,它们的功能很相似。它们之间最主要的区别是速度,速度越快的产品
越贵,是否有某种方法使我们在对它们应用软件可靠性工程时可以节约人力和物力?
答:是的。可以共同开发这些产品的操作剖面。许多操作都是重复的。可以在一个相同的
基础上收集出现率的信息。许多测试的计划可以联合进行,这些产品可以共享许多测试案例。
如果这些产品的软件是共同开发的,则很可能可以执行大量相同的测试。
17. 可以构建操作剖面的层次吗?
答:是的。如果希望对某个操作进行细致的刻画,则可以对其建立一个操作剖面。同样也
可以在原来的操作剖面中将这个操作扩展为多个操作。例如,假设你有一个操作刻画如表3 – 1 3
所示。为了细化操作B,可以创建一个子操作剖面,如表3 – 1 4所示。同样也可以在原操作剖面中
直接扩展操作B,如表3 – 1 5所示。
表3-13 示例操作剖面
操作出现概率
A 0 . 6
B 0 . 3
C 0 . 1
表3-14 操作B的子操作剖面
操作出现概率
B1 0 . 5
B2 0 . 4
B3 0 . 1
表3-15 扩展后的操作剖面
操作出现概率
A 0 . 6
B1 0 . 1 5
B2 0 . 1 2
B3 0 . 0 3
C 0 . 1
18. 我们怎样处理这样一个事实,在现场环境中许多操作并不是互相独立的,而是趋向于形
成工作序列?换句话说,在一个用户发起操作A之后,有很高的概率,他下一步将发起操作D。
根据出现概率对这些操作进行的随机选择可能没有反映真实的现场条件。
答:如果一个操作集真的形成了一个经常发生的序列,那么这些操作应该被重新定义为一
个单独的操作。如果这个序列只是偶尔发生,将这些操作作为单独的实体来随机选择是一个更
空84 第3 章空
好的对真实情况的近似。
19. 在已有的操作和新操作之间,许多用户把重点放在避免已有操作的失效,因为他们的工
作更依赖于已有的操作,而其失效的影响也更大。除了失效严重性分类之外,为适应这种情况
我们还可以做什么呢?
答:可以将输入空间根据已有操作和新操作分开。对操作剖面的相应部分给予可表达操作
相对重要性的相对权重。然后用调整后的操作剖面集中开发力量,确定测试优先级,使现有操
作具有更重要的地位。
3.5 背景
以下将首先给出一些确定操作模式的背景知识,然后更深入地讨论操作和运行概念。
3.5.1 确定操作模式
系统使用的不同模式容易造成操作(系统执行的主要任务)及其运行(操作的实例)之间
的不同的交互作用,这通常是由于诸如资源的不同争用和由操作运行占有或共享的不同数据等
原因造成。实际上,通过改变输入状态(存在于系统外部并且影响其执行的变量集合)可改变
所执行的运行,尽管显式地确定输入状态有哪些变化通常是不实际的。但是,确实需要在这些
不同的使用模式下测试系统,从而需要定义操作模式。
不同的环境条件也会有效地通过改变输入状态来改变所执行的运行,尽管显式地确定输入
状态有哪些变化也同样是不实际的。环境条件的例子如数据退化(长时间运行引起的)和数据
库的数据量。
我们通常并不把数据库退化看作是定义操作模式的一个因素,而是要在测试中表现出在现
场存在的数据库清理过程(例如,每日的数据库重新初始化)。因此,我们让数据库随着每个操
作模式随时间的执行而自然地在可能的范围内退化。
许多拥有操作员的系统,在晚上和周末将会有相当不同的使用模式,那些时候很少或没有
操作员在。从而,通常有主要时段和低谷时段操作模式。
可能发生的失效模式在通常负载和过载的条件下是非常不同的,因为资源不足会造成内存
溢出和队列延迟。因此,需要在这两种条件下分别进行测试。在通常或过载的范围内,变化就
小多了;因此在通常或过载的范围内,没有必要在不同的负载水平下进行测试。
当系统的操作具有不同优先级时,为通常负载和过载定义各自的操作模式就特别重要,因
为使用模式将会不同。例如,在通常负载下,一些低优先级的任务,例如审计和日常内务操作
可以得到执行,而在过载条件下,它们就根本不会得到执行。
类似地,一些系统根据系统的能力状态,控制其所接受的操作,目的是拒绝不能很好完成 #p#分页标题#e#
其功能的操作,而将系统能力提供给更有效率的操作。在这种情况下,应该考虑为每个重要的
系统能力状态建立一个操作模式并且单独测试。
空开发操作剖面8 5空
3.5.2 操作和运行
可以将程序的执行看作一个单独的实体,持续执行数月,实时系统甚至可以持续数年。然
而,如果将执行分解为操作的集合,就可以较容易地刻画环境条件。环境由操作剖面来描述。
操作可能有很多实例,每个实例称为一个运行。在执行过程中,在某个操作内引起某个特殊的
操作和特殊运行的因素数量很多而且很复杂。因此,可以将程序根据环境所需要的操作看作是
根据前面提到的概率随机选择的,然后以相同的概率来选择这些操作中的运行。
运行由输入状态或所接受的输入变量值的集合所规范。输入状态不同于机器状态,机器状
态包含的变量集合要大得多,要包括所有的计算机可以得到的变量值。循环运行具有相同的输
入状态。我们以程序的运行输出状态(所产生的输出变量的值的集合)来判断程序的可靠性。
请注意,运行表示由输入状态到输出状态的转换。多个输入状态可以映射到相同的输出状态,
但是一个给定的输入状态只能有一个输出状态。输入状态惟一地确定将要执行的指令,以及指
令的操作数。因此输入状态可确定程序执行的控制路径,同时惟一地确定所有中间变量的值。
在理论上,某个特定的错误对于某个运行类型是否会造成失效是可以预知的。但是,要确定这
一点所需的分析工作可能是实际上无法做到的。
输入状态不只具有理论意义。完全理解运行的输入变量,并且为了诊断而记录输入变量是
非常重要的,许多难以诊断的失效都是因为间接或“隐藏”的输入变量。这可能是由于以前的
运行而退化的数据库数据项。对某些特定的值,程序可能不能正确地工作。
程序运行的输入变量是处于运行之外,并由运行所使用的所有数据项,并不一定要有一个
可见的输入过程。输入变量可能就是简单地存在于内存中,等待着被访问。相应地,程序运行
的输出变量就是处于运行外部,并由运行所设置的所有数据项。输出变量并不一定要被使用、
打印出来或被转移。输出变量可以是控制信号、命令、打印输出、显示或传递的数据项等。输
入变量不能同时是输出变量,但在不同的时间,两者可以占有相同的内存。一个数据项由一个
或多个数据元素的相关集合组成,它可以是标量、数组或结构。数据项的“值”是其元素的值
的集合。数据元素是一个标量,例如数字量、逻辑变量、字符串、或甚至是抽象的数据类型。
“相关”是由数据元素的功能使用决定的。与某个单独的外部条件相关的多个数据元素可以认为
是相关的。一个例子是在航空交通控制系统中定位飞行器的向量中的元素。
对于一个运行,一个数据元素可以只有一个值。所以,必须考虑每个使用,或设置作为单
独数据元素变化的量。假定相对所使用或设置的量的运行开始时间可以变化,因此非常重要。
于是描述了这个量的数据项就应该包含这个时间作为一个元素。因此,给定类型中断的每次激
活都应该作为一个单独的数据项。因为在一个运行中所发生的中断数量是可以变化的,不同的
输入状态可以有不同数量的输入变量和维度。请注意,数据元素并不是物理或符号内存位置。
通过动态存储分配的“分时共享”,可将相同的物理的或信号位置与多个数据元素相关联。
外部启动的中断,例如由系统时钟、操作员的行为和系统中程序外部的其他组件产生的中
断,被认为是输入变量。中间数据项在运行过程中被程序计算出来,而且不是程序的现有外部
变量,被认为既不是输入变量也不是输出变量。因此,由运行直接产生的中断或由其他输入变
量(例如上溢或下溢)确定的中断都不是输入变量。
空86 第3 章空
作为所选择的输入状态的结果,所有的运行迟早都将结束。“结束”可能是指程序完成了一
项任务,并且到任务队列去寻找一项新任务。有些结束可能是过早的,因为它并没有完成任何
有用的功能。如果运行由于操作员的动作而过早结束,则这个结束动作表示一个中断,这个中
断标志着与正常结束的运行所不同的输入状态。
某个程序的输入空间是可能在该程序的操作过程中出现的输入状态的集合。输入空间是离
散的(假设中断时间只能在某种量化水平上描述),因此可以通过索引数字来辩别输入状态。输
入空间的维度等于输入变量的维度之和。如果程序发生变化,输入空间也可能变化。
如果操作都是独立的,则确定操作的出现率就相对容易。但是,操作可能会依赖于前面某
个操作。例如,对于将某个操作定义为循环操作的控制系统就可能是对的。在这种情况下,人
们可能会忽视这种依赖关系,并且使用在一段长时间中计算得出的每一个操作的出现率。这个
过程是可以接受的,因为人们可以手工设置输入状态。对有依赖关系的工作序列中的一个特定
操作,在测试中可以不必真地执行在现场中通常在它前面出现的操作。
这个方法的有效性可以采用统计方法解释。可以将连续的操作序列看作一个马尔可夫
(M k o v)链,状态之间的关系以迁移概率来表达。迁移概率是指在某个给定状态的系统将迁移
到其他状态的条件概率。我们要使用已经确定的状态的一致环境,这样迁移概率就会是稳定的。
有理由假定每个操作都是可由其他任何操作到达的。因此,只要有足够的时间,马尔可夫链发
生的不同状态的概率将到达一个稳定状态,从而可以使用稳定状态概率来刻画环境。
除了操作剖面,还有另外一种刻画环境的方法( C h e u n g,1 9 8 0)。可以指出程序模块执行的
序列。在操作和模块序列之间有一个多对一的映射。对操作剖面的模拟就是所有可能的模块序列
集合及其相关联的出现概率。除了这些概率之外,使用模块之间的迁移概率更为方便。如果迁移
概率只依赖于所包含的两个模块并且是一致的,则系统会及时地到达一个稳定状态。每个模块都
有一个被执行的概率。从模块的可靠性和迁移概率可以得到程序的总的可靠性。上述方法强调了
程序的结构特征。可以通过敏感系数来指出在影响系统可靠性方面,哪些模块最关键。关键模块 #p#分页标题#e#
的识别在推荐最有效的测试方式和进化策略方面是有效的。在前一种情况下,可以以关键性的递
减顺序测试模块。在后一种情况下,当加入新功能时,可以试图避免关键模块的变化。
实际上,上述方法的实践意义远小于操作剖面方法。操作的出现概率是关于程序使用情况
的自然的原始保息,与程序结构无关并且可以在设计之前确定,而模块迁移概率不行。要确定
模块之间的迁移概率,可能必须通过程序指令和大量执行,后者实质上等价于基于操作的测试。
组件可靠性的估计通常是困难的,因为与模块相关的失效样本通常较小。因此模块序列方法主
要只具有概念上的价值。
3.6 问题
1. 假定某个产品的基本开发费用是C0,每个操作的费用是CP。共有P 个操作。每个操作k
的出现率是pk。如果没有操作剖面信息,则可以将相同的开发资源提供给每个操作。但是,我
们将使用操作剖面来调整提供给较少使用的操作的资源,以减少总的费用。以k = 1 来表示最常
空开发操作剖面8 7空
用的操作。每个其他操作的费用将减少到单个操作的基本费用CP0 加上一个变量成份( pk /p1)
(CP-CP0)。
a. 现在总的开发费用是多少?
b. 所节省费用的百分比是多少?
c. 如果在减少资源之前该项目的基本开发费用是总费用的1 0 %,共有4 5个操作,每个操作的
基本费用是每个操作费用的一半(也是在减少资源之前)。p1= 0 . 2,那么节省下来的费用的百分
比是多少?
d. 当p1=0.5 时节省的费用的百分比是多少?当p1=0.1 时呢?
e. 如果有1 8个操作,节省的费用的百分比是多少?如果是9 0个操作呢?
2. 假设你是Fone Follower的产品经理。在计划该产品的两个版本时,希望应用操作开发的
概念。在每个版本要实现什么能力?请参阅表3 – 5。
3. 计划对Fone Follower的语音呼叫需求做5小时的评审。如何在有寻呼服务和没有寻呼服务
的处理之间分配时间呢?请参阅表3 – 5。
4. 你正在开发一种两栖装甲车,它将被新兵和有经验的老兵使用。需要建立什么样的操作
模式?