外文资料翻译软件测试的艺术毕业论文

上传人:沈*** 文档编号:90914142 上传时间:2022-05-16 格式:DOC 页数:57 大小:440.04KB
收藏 版权申诉 举报 下载
外文资料翻译软件测试的艺术毕业论文_第1页
第1页 / 共57页
外文资料翻译软件测试的艺术毕业论文_第2页
第2页 / 共57页
外文资料翻译软件测试的艺术毕业论文_第3页
第3页 / 共57页
资源描述:

《外文资料翻译软件测试的艺术毕业论文》由会员分享,可在线阅读,更多相关《外文资料翻译软件测试的艺术毕业论文(57页珍藏版)》请在装配图网上搜索。

1、 软件测试的艺术第1章一次自评价测试子本书25年前首次出版以来,软件测试变得比以前容易得多,也困难德多。软件测试何以变得更困难?原因在于大量编程语言,操作系统以与硬件平台的出现。在20世纪70年代只有相当少的人使用计算机,而今天在商业界和教育界,如果不使用计算机,几乎没有人能完成日常工作。况且,计算机本身的功能也比以前增强了数百倍。因此,我们现在编写的软件会潜在地影响到数以百万计的人,使他们更高地完成工作,反之也会给他们带来数不清的麻烦,导致工作或事业的损失。这并不是说今天的软件比本书第一版发行是更重要,但可以肯定地说,今天的计算机以驱动它的软件无疑已影响到了更多的人、更多的行业。就某些方面而

2、言,软件测试变得容易了,因为大量的软件和操作系统比以往更加复杂,部提供了很多已充分的例程供应程序集成,无须程序员从头进行设计。例如,图形用户界面(GUI)可以从开发语言的类库中建立起来,同时,由于它们是经过充分调试和测试的可编程对象,将其作为用户应用程序测组成部分进行测试 的要求就减少了许多。所谓软件测试就是一个过程或一系列过程,用来确认计算机代码完成了其应该完成的功能,不执行其不该有的操作。软件应当是可预测且稳定的,不会给用户带来意外的惊奇。在本书中,我们将讨论多种方法来达到这个目标。好了,在开始阅读本书之前,我们想让读者做一个小测验。我们要求设计一组测试用例(特定的数据集合),使当地测试一

3、个相当简单的程序。为此要为该程序建立一组测试数据,程序须对数据进行正确处理以证明自身的成功。下面是对程序的描述:这个程序从一个输入对话框中读取三个整数数值。这三个整数数值代表了三角形三边的长度。程序显示提示信息,指出该三角形究竟是不规则三角形、等腰三角形还是等边三角形。注意,所谓不规则三角形是指三角形任意两条边不相等,等腰三角形是指有两条边相等,而等边三角形则是指三条边相等。另外,等腰三角形等边的对角也相等(即任意三角形等边的对角也相等),等边三角形的所有角都相等。用你的测试用例集回答下列问题,借以对其进行评价。对每个回答“是”的答案,可以得1分:1. 是否有这样的测试用例,代表了一个有效的不

4、规则三角形?(注意,如1,2,3,和2,5,10这样的测试用例并不能确保“是”的答案,因为具备这样边长的三角形不存在。)2. 是否有这样的测试用例,代表一个有效的等边三角形?3. 是否有这样的测试用例,代表一个有效的等腰三角形?(注意如2,2,4的测试用例无效,因为这不是一个有效的三角形。)4. 是否至少有三个这样的测试用例,代表有效的等腰三角形,从而可以测试到两等边的所有三种可能情况(如3,3,4;3,4,3;4,3,3)?5. 是否有这样的测试用例,某边的长度等于0?6. 是否有这样的测试用例,某边的长度为负数?7. 是否有这样的测试用例,三个整数皆大于0.其中两个整数之和等于第三个?(也

5、就是说,如果程序判断1,2,3表示一个不规则三角形,它可能就包含一个缺陷。)8. 是否至少有三个地7类的测试用例,列举了一边等于另外两边之和的全部的可能情况(如1,2,3;1,3,2;3,1,2)?9. 是否有这样的测试用例,三个整数皆大于0,其中两个整数之和小于第三个整数(如1,2,4;12,15,30)?10. 是否至少有三个第9类的测试用例,列举了一边大于另外两边之和的全部可能情况(如1,2,4;1,4,2;4,1,2)?11. 是否有这样的测试用例,三边长度皆为0(0,0,0)?12. 是否至少有一个这样的测试用例,输入的边长为非整数(如1.5,3.5,5.5)?13. 是否至少有一个

6、这样的测试用例,输入的边长个数不对(如仅输入了两个而不是三个整数)?14. 对于每一个测试用例,除了定义输入值之外,是否定义了程序针对该输入值的预期输出值?当然,测试用例即使满足了上述条件,也不能确保能查处所有可能的错误。但是,由于问题1至问题13代表了该程序不同版本中已经实际出现的错误,对该程序的充分测试至少应该能够暴露这些错误。开始关注自己的得分之前,请考虑以下情况:以我们的经验来看,高水平的专业程序员平均得分仅7.8(满分14)。如果读者的得分更高,那么祝贺你。如果没那么高,我们将尽力帮助你。这个测验说明,即使测试这样一个小的程序,也不是件容易的事。如果确实是这样,那么想象一下测试一个十

7、万行代码的空通管理系统,一个编译器,甚至一个普通的工资管理程序的难度。随着面向对象编程语言(如Java、C+)的出现,测试也变得更加困难。举例来说,为测试这些语言开发出来的应用程序,测试用例必须要找出与对象实例或存管理有关的错误。从上面这个例子来看,完全地测试一个复杂的、实际运行的程序视乎是 不太可能的。情况并非如此!尽管充分的测试的难度令人望而生畏,但这是软件开发中一项非常必须的任务,也是可以实现的一部分工作,通过本书我们可以认识到这一点。第2章软件测试的心理学和经济学软件测试是一项技术性工作,但同时也涉与经济学和人类心里学的一些重要因素。在理想情况下,我们会测试程序的所有可能情况。然而,在

8、大多数情况下,这几乎是不可能的。即使一个看起来非常简单的程序,其可能输入与输出组合可达到数百种甚至数千种,对多有的可能情况都设计测试用例是不切实际的。对一个复杂的应用程序进行完全的测试,将耗费大量的时间和人力资源,以至于经济上是不可能的。另外,要成功地测试一个软件应用程序,测试人员也需要有正确的态度(也许用“愿景(vision)”这个词会更好一些)。在某些情况下,测试人员的态度可能比实际的测试过程本是还要重要。因此,在深入探讨软件测试更加技术化的本质之前,我们先探讨一下软件测试的心理学和经济学问题。2.1软件测试的心理学测试执行的差,其中一个重要原因在于大多数的程序员一开始就 把“测试”这个术

9、语的定义搞错了。他们可能会认为:“软件测试就是证明软件不存在错误的过程。”“软件测试的目的在于证明软件能够正确完成其预定的功能。”“软件测试就是建立一个软件做了其应该做的信心的过程。”这些定义都是本末倒置的。每当测试一个程序时,总是想为程序增加一些价值。通过测试来增加程序的价值,是指测试提高了程序的可靠性后质量。提高了程序的可靠性,是指找出并最终修改了程序的错误。因此,不要只是为了证明程序能够正确运行而去测试程序;相反,应该一开始就假设程序中隐藏着错误(这种假设对于几乎所有的程序都成立),然而测试程序,发现尽可能多的错误。那么,对于测试,更为适合的定义应该是:“测试是为发现错误而执行程序的过程

10、”。虽然这看起来像是个微妙的文字游戏,但确实有重要的区别。理解软件测试的真正定义,会对成功地进行软件测试有很大的影响。人类行为总是倾向于具有高度目标性,确定一个正确的目标有着重要的心理学影响。如果我们的目的是证明程序中不存在错误,那就会潜在意识中倾向于实现这个目标; 也就是说,我们会倾向于选择可能较少导致程序失效的测试数据。另一方面,如果我们的目标在于证明程序中存在错误,我们设计的测试数就有可能更多地发现问题。与前一种方法相比,后一种方法会更多的增加程序的价值。这种对软件测试的定义,包含着无穷的涵,其中的很多都蕴含在本书各处。举例来说,它暗示了软件测试是一个破坏性的过程,甚至是一个“施虐”的过

11、程,这就是说明为什么大多数人都觉得它困难,这种定义可能是违反我们愿望的;所幸的是,我们大多数人总是对生活充满建设性而不是破坏性的愿景。大多数人都本能地倾向于创造事物,而不是将事物破坏。这个定义还暗示了对于一个特定的程序,应该如何设计测试用例(测试数据),哪些人硬挨而哪些人又不应该执行测试。为增进对软件测试正确定义的理解,另一条途径是分析一下对“成功的”和“不成功的”这两个问题的使用。当项目经理归纳测试用例的结果时,尤其会用到这两个词。大多数的醒目经理没发现错误的测试用例称为一次“成功测试”,而将发现了某个错误的测试称为“不成功的测试”。这不仅是一次本末倒置。“不成功的”表示事情不遂人意或令人失

12、望。我们认为,如果测试某段程序时发现了错误,而且这些错误是可以修复的,就将这次合理设计并得到有效的测试称作是“成功的”。如果本次测试可以最终确定再无其他可查处的错误,同样也被称为是“成功的”。所谓“不成功的”测试,仅指未能适当地对程序检查,在大多数情况下,未能找出错误的测试被认为是“不成功的”。这是因为认为软件中不包含错误的观点基本上是不切实际的。能发现新错误的测试用例不太可能被认为是“不成功的”;相反能发现错误就证明它是值得设计的。一个“不成功的”测试用例,会使程序输出正确的结果,但不能发现人恶化错误。我们可以类比一下病人看医生的情况,病人因为身体不舒服而去看医生。如果医生对病人进行了一些实

13、验检测,却没有诊断出任何病因,我们就不会认为这些实验检测是“成功的”。之所以是“不成功的”检测,是因为病人支付了昂贵的实验检测费用,而病状却依然如故。病人会因此而质疑医生的诊断能力。但是,如果实验检测诊断出病人是胃溃疡,那么这次检测就是“成功的”,医生可以开始进行适当的治疗。因此,医疗行业会使用“成功的”或“不成功的”来表达适当的意思。我们当然可以类推到软件测试中来,当我们开始测试某个程序是,它就是好似我们的病人。“软件测试就是证明软件不存在错误的过程”,这个定义会带来第二个问题。对于几乎所有的程序而言,甚至是非常小的程序,这个目标实际上也就是无法达到的。另外,心理学研究表明,当人们开始一项工

14、作是,如果已经知道他说不可行的或无法实现时,人的表现就会相当糟糕。举例来说,如果要求人们在15分钟之完成星期日纽约时报里的纵横填字游戏,那么我们会观察到10分钟之后的进展非常小,因为大多数人都会却步于这个现实,即这个任务似乎是不可能完成的。但是如果要求在四个小时之完成填字游戏,恶魔很可能有理由期望最初10分钟之的进展会比前一种情况下的大。将软件测试定义为发现程序错误的过程,即使测试是个可以完成的任务,从而克服了这个心理障碍。诸如“软件测试就是证明软件做了其应该做的的过程”此类的定义所带来的第三个问题是,程序即使完成预定的功能,也仍然可能隐藏错误。也也就是说,当程序没有实现预期功能是,错误是清晰

15、地显示出来的;如果做了其不该做的,这同样是一个错误。考虑一下第1章的三角形测试程序。即使我们证明了程序能够识别出不规则三角形,等腰三角形和等边三角形,但是在完成了不该执行的任务后(例如将1,2,3说成是一个不规则三角形后将0,0,0说成是一个等边三角形),程序仍然是错的。如果我们将软件测试视作发现错误的过程,而不是将其视为证明“软件做了其应该做的”的过程,我们发现后一类错误的可能性会大很多。总结一下,软件测试更适合被视为试图发现程序中错误(假设其存在)的破坏性东东过程。一个成功的测试用例,通过诱发程序发生错误,可以在这个方向上促进软件质量的改进。当然,最终我们还是要通过软件测试来建立某种程度的

16、信心:软件做了其该做的,未做其不该做的。但是通过对错误的不断研究是实现这个目的的最佳途径。有人可能会声称“本人的程序完美无缺”(不存在错误),针对这种的情况建立起信心的最好办法就是尽量反驳他,即努力发现不完美之处,而不是确认程序在某些输入情况下能够正确地工作。2.2 软件测试的经济学给出了软件测试的适当定义之后,下一步就是确定软件测试是否能够发现“所以”的错误。我们将证明答案是否定的,即使是规模很小的程序。一般说来,要发现程序中的所以错误也是不切实际的,常常也是不可能的。这个基本的问题反过来暗示出软件的经济学问题,测试人员对被测试的期望,以与测试用例的设计方式。为了应对测试经济学的挑战,应该开

17、始测试之前建立某些策略。黑盒测试和白盒测试是两种最普遍的策略,我们将在下面两节中讨论。2.2.1 黑盒测试黑盒测试是一种重要的测试策略,又称为数据驱动的测试或输入/输出驱动的测试。使用这种测试方法时,将程序视为一个黑盒子。测试目标与程序额部机制和结构完全无关,而是将重点集中放在发现程序不按其规正确运行的环境条件。在这种方法中,测试数据完全来源于软件规(换句话说,不需要去了解程序的部结构)。如果想用这种方法来发现程序的所以错误,判定的标准就是“穷举输入测试”,将所有可能的输入条件作为测试用例。为什么这样做?比如说在三角形测试的程序中,试过了三个等边三角形的测试用例,这不能确保正确地判断出所有的等

18、边三角形。程序中可能包含对边长为3842,3842,3842的特殊检查,并指出此三角形为不规则三角形。由于是个黑盒子,因此能够确定此条语句存在唯一的方法,寄是实验所有的输入情况。要穷举测试这个三角形程序,可能要为所有有效的三角形创建测试用例,只要三角形边长在开发语言允许的最大整数值围。这些测试用例本是就是个天文数字,但这还不是所谓的穷举的;当程序指出一3,4,5是一个不规则三角形或2,A,2是一个等腰三角形时,问题就暴露出来了。为了确保能够发现所有这样的错误,不仅得用所有有效的输入,而且还得用所有可能的输入进行测试。因此,为了穷举测试三角形程序,实际上需要创建无限的测试用例,这当然是不可能的。

19、如果测试这个三角形程序都这么难的话,那么要穷举测试一个稍大些的程序的难度就更大了。设想下,如果要对一个C+编译器进行黑盒穷举测试,不进要创建代表所有有效C+程序的测试用例(实际上,这又是一个无穷数),还需要创建代表所有无效C+程序的测试用例(无穷数),以确定编译器能够检测出他们是无效的。也就是说,编译器必须进行测试,确保其不会执行不该执行的操作如顺利地编译成功一个语法上不正确的程序。如果程序使用到数据存储,如操作系统或数据库应用程序,这个问题会变得尤为严重。举例来说,在航班预定系统这样的数据库应用程序中,诸如数据库查询、航班预约这样的事物处理需要随上一次事务的执行情况而定。因此,不仅要测试所有

20、有效的和无效的事务处理,还要测试所有可能的事物处理顺序。上述讨论说明,穷举输入测试是无法实现的。这有两方面的含义,一是我们无法测试一个程序以确保它是无错的,二是软件测试中需要考虑的一个基本问题是软件测试的经济学。也就是说,由于穷举测试是不可能的,测试投入的目标在于通过有限的测试用例,最大限度地提高发现的问题的数量,以取得最好的测试效果。除了其他因数以外,要实现这个目标,还需要能够窥见软件的部,对测试做些合理但非无懈可击的假设(例如,如果三角形程序将2,2,2视为等边三角形,那就有理由认为程序对3,3,3,也做同样的判断)。这样思路将形成本书第四章中测试用例设计策略的部分方法。2.2.2 白盒测

21、试另一种测试策略称为白盒测试或逻辑驱动的测试,允许我们检查程序的部结构。这种测试策略对程序的逻辑结构进行检查,从中获取测试数据(遗憾的是,常常忽略了程序的规)。这这里我们的目标是针对这种测试策略,建立起与黑盒测试中穷举输入测试相似的方法。也许有一个解决的办法,即将程序中的每条语句至少执行一次。但是我们不难证明,这还是远远不够的。这种方法通常称为穷举路径测试,在本书地4章中将进一步进行深入探讨,在这里就不多加叙述。所谓穷举路径测试,即如果使用测试用例执行了程序中所有可能的控制流路径,那么程序有可能得到完全测试。然而,这个论断存在两个问题。首先,程序中不同逻辑的数量可能达到天文数字。图2-1所示的

22、小程序显示了这一点。该图是一个控制流图,每一个结点或圆圈都代表一个按顺序执行的语句段,通常以一个分支语句结束。每一条边或弧线表示语句段之间的控制(分支)的转换。图2-1描述的是一个有着10-20行语句的程序,包含一个迭代20次的DO循环。在DO循环体中,包含一系列嵌套的IF语句。要确定不同的逻辑路径的数量,也相当于要确定从点a点b之间所有不同路径的数量(假设程序中所有的判断语句都是相互独立的)。这个数量大约是1014,即100万亿,是从520+519+.+51 计算而来,5是循环体的路径数量。由于大多数的人难以对这个数字有一个直观的概念,不妨设想下;如果在每分钟可以编写、执行和确认一个测试用例

23、,那么需要大约10亿年才能测试完所有的路径。假如可以快上300倍,每一秒完成一次测试,也得用漫长的320万年才能完成这项工作。 当然,在实际程序中,判断并非都是彼此独立的,这意味着可能实际执行的路径数量要稍微少一些。但是,从另一方面来讲,实际应用的程序要比图2-1所描述的简单程序复杂得多。因此,穷举路径测试就如同穷举输入测试,非但不可能,也是不切实际的。“穷举路径测试即完全的测试”论断村子的第二个问题是,虽然我们可以测试到程序中的所有路径,但是程序可能仍然存在着错误。这有三个原因。第一, 即使是穷举路径测试也绝不能保证程序符合其设计规。举例来说,如果要编写一个升序排序程序,但却错误地编成了一个

24、降序程序,那么穷举路径测试就没多大价值了;程序仍然存在着一个缺陷;它是个错误的程序,因为不符合设计的规。第二, 程序可能会因为缺少某些路径而存在问题。穷举路径测试当然不能发现缺少了哪呢必须路径。第三, 穷举路径测试可能不会暴露数据敏感错误。这样的例子很多,举一个简单的例子就能说明问题。假设在某个程序中要比较两个数值是否收敛,也就是检查连个数值之间的差异是否小于某个既定的值。比如,我们可能会这样编一条JAVA语言的IF语句:if (a-b c)system.out.println( “a-b c”);当然,这条语句包含一个错误,因为它可能将c与a-b 的绝对值进行比较。然而,要找出这样的错误,取

25、决于a和b所取的值,而仅仅执行程序中的每条路径并 不一定能找出错误来。总之,尽管穷举输入测试要强于穷举路径测试,但两者都不是有效的方法,因为这两种方法都不可行。那么,也许存在别的方法,将黑盒测试和白盒测试的要素结合起来,形成一个合理并不十分完美的测试策略。本书的策略第4章将深入讨论这个问题。2.3 软件测试的原则让我们继续本章的话题基础,即软件测试多数重要的问题是心理学问题。我们可以归纳出一些列重要的测试知道原则。这些原则看上去大多数都是显而易见,但常常总是被我们忽视掉。表2-1总结了这些重要原则,每条原则都将在下面的章节中详细介绍。表2-1 软件测试的重要原则编号原则1测试用例中一个必须部分

26、是对预期输出或结果进行定义2程序员应当避免测试自己编写的程序3编写软件的组织不应当测试自己编写的软件4应当彻底检查每个测试的执行结果5测试用例的编写不仅应当根据有效和预防的输入情况,而且也应当根据无效和未预料的输入情况6检查程序是否“未做应该做的”仅是测试的一半测试的另一半是检查程序是否“做了其不该做的”7应避免测试用例用后即弃,除非软件本身就是一个一次性的软件8计划测试工作时不应该默许假定不会发现错误9程序某部分存在更多错误的可能行与该部分已发现错误的数量成正比10软件测试是一项极高创造性,极其智力挑战性的工作原则1:测试用例中一个必须部分是对预期输出或结果的定义。这条显而易见的原则在软件测

27、试中是最常犯的错误之一。同样,这个问题也是基于人们的心理的。如果某个测试用例的预期结果事先没有得到定义,由于“所见所闻”现象的错在,某个似是而非,实际上是错误的结果可能会被解释成正确的结论。换句话说,尽管“软件测试是破坏性”的定义是合理的,但人们在潜意识中仍然渴望看到正确的结果。克服这种倾向的一种方法,就是通过事先精确定义的程序的预期输出,鼓励人们对所有的输出进行仔细检查。因此,一个测试用例必须包括两个部分:1. 对程序的输入数据的描述。2. 对程序在上述输入数据先的正确的 输出结果的精确描述。所谓“问题”,可以归纳为一个或一组我们不能给出可信服的解释,看上去不太正常或不符合我们期望或预想的事

28、实。殷罡明确的是,在确定事物存在“问题”之前,人们必须已经形成了特定的认识。没有期望,也没有所谓的意外。原则2: 程序员应当避免测试自己编写的程序任何作者都知道或应该知道,亲自编辑或校队对自己的作品确实是个不好的做法。作者清楚某段文字要说明的是什么,实际表达出来的意思却南辕北辙,而自己可能意识不到。况且实际上也不会想自己的作品中找出什么错误来。对程序员而言,也错在同样的问题。如果我们对软件项目关注的重点发生变化,就会产生另外一个问题。当程序员“建设性地设计和编写完程序之后,很难让他突然改变视角以一种“破坏性”的眼光来审查程序。正如许多房屋业主都知道的那样,撕下房屋的墙纸(这是个破坏行的过程)并

29、不容易,如果这些墙纸有恰是业主第一个亲手贴的,尤其令其沮丧不已。同样,大多数程序员都不能有效地测试自己编写的程序,因为他们无法改变思维方式来尽力暴露自己程序的错误。另外,程序员可能会下意思地避免找出错误来,担心受到同事、上司、客户或正在开发的程序员或系统的主管的惩罚。仅次于上面的心理学问题,还有一个重要的外套;由于程序员错误地理解了疑难定义或规,导致程序中存在错误。如果情况是这样,程序员可能会带来同样的误解来测试自己的程序。这并不意味着程序员测试自己的程序员是不可能的。当然,我们的言下之意是,让其他人来测试程序会更加有效,也会更容易测试成功。请注意,我们的论据并不适合于“调试”(纠正已知的错误

30、)。“调试”由程序的编写人员来完成有效得多。原则3:编写软件的组织不应当测试自己编写的软件。这里的论据与前面的论据相似。从很多方面来讲,一个软件项目或编程组织是一个有机的机构,具有与个体程序员相似的心理问题。而且在大多数情况下,主要是根据其在给定时间、特定成本围开发软件的能力来衡量编程组织或项目经理。其中的一个原因是,度量时间和成本目标 比较容易,而定量地衡量软件的可靠性则极其困难。即使是合理规划和实施测试过程,也可能被认为降低了完成进度和成本目标的可能性,因此, 编程组织难以客观地测试自己的软件。同样,我们并不是说编程组织发现程序中的问题是不可能的,事实上很多组织已经在某种程度上成功地做到了

31、这一点。当然,我们的言下之意是,更经济的方法是由客观、独立的第三方来进行测试。原则4:应当彻底检查每个测试的执行结果。这个原则可能是最显而易见的原则,但也同样常常被忽视。我们见过大量的例子,即便错误的状态在输出清单中可以清楚地看到,但还是没有找出那些错误来。换言之,在后续测试中发现的错误,往往是前面的测试遗漏掉的。原则 5:测试用例的编写不仅应当根据有效和预期的输入情况,而且也应当根据无效和未预料到的输入情况。在测试软件是,有一个自然的倾向,即将重点集中在有效和预期的输入情况上,而忽略了无效和未预料到的情况。比如,在本书第1章三角形程序的测试中,总是出现这个倾向。例如,很少有人会向程序输入1,

32、2,5以证明程序不会错误地将其解释为一个不规则三角形,而不是一个无效三角形。此外,在软件产品中突然暴露出来的许多问题是当程序以某些新的或未预料到的方式运行是发现的。因此,针对未预料到的无效输入情况的测试用例,似乎比针对有效输入情况的那些用例更能发现问题。原则6:检查程序是否“未做其应该做的”仅是测试的一半,测试的另一半是检查程序是否“做了其不该做的”。这条原则是上调原则的必然结果。必须检查程序是否有我们不希望的负作用。比如,某个工资管理程序中即便可以生成正确的工资单,但是如果也为非雇员生成工资单或者覆盖掉了人员文件的以一条记录,这样的程序仍然是不正确的程序。原则 7:应避免测试用例用后即弃,除

33、非软件本是就是一个一次性的软件。这个问题在采用交互式系统来测试软件时最常见。人们通常会坐在终端前,匆忙地编写测试用例,然后将这些用例交由程序执行。这样的问题在于,饱含我们宝贵投入的测试用例,还测试结束后就消失了。一旦软件需要重新测试(例如,当改正了某个错误或做了某种改进后),又必须重新设计这些测试用例。情况往往是这样的,由于重新设计测试用例需要投入大量的工作,人们总是避免这样做。因此,对程序的重新测试极少会同上次一样严格。这就意味着,如果对程序的更改导致了程序某个先前可以执行的部分发生了故障,这个故障往往是不会被发现的。保留测试用例,当程序其他部件更动后重新执行,这就是我们所谓的“回归测试”。

34、原则8:计划测试工作时不应默许假定不会发现错误。项目经理经常容易犯这个错误,这也是使用了不正确的测试定义的一个迹象也就是说,假定“测试是一个证明程序正确运行的过程”。我们再一次重申,所谓测试,就是为发现错误而执行的过程原则9:程序某部分存在更多的可能性,与该部分已发现错误的数量成正比。这种现象如图2-2所示。咋看上去,这幅图似乎没有什么意思,但是很多程序都存在这种现象。例如,假如某个程序由两个模块、类或子程序A和B组成,模块A中已经发现了五个错误,而模块B中近近找到了一处错误。如果模块A经过的程序并不是故意设计得更为严格,那么该原则告诉我们,模块A与模块B相比,错在更多错误的可能性要大。该原则

35、的另一个所发是,错误总是倾向于聚集存在,而在一个具体的程序中,某些部分要比其他部分更容易存在错误、尽管没有人能够对这种现象给出很好的解释。这种现象之所以有用,是因为它给予了我们对软件测试过程的洞察或反馈,如果一个程序的某个部分远比其他部分更容易产生错误,那么这种现象告诉我们,为了是测试获得更大的成效,最好对这些容易错在错误的部分进行额外的程序。残存错误的可能性已知错误的数量图22残存错误与已知错误间令人惊奇的联系原则10:软件测试是一项极富创造性、极具挑战性的工作。测试一个大型软件所需要的创造性很可能超过开发软件所需要的创造性。我们已经看到,要充分东欧测试一个软件以确保所有错误都不存在是不可能

36、的。本书 章节讨论的技术是我们能够为某个软件设计出合理的测试用例集,然而这些技术需要大量的创造性。2.4小结在阅读本书接下来的容时,请牢记一下三个重要的一测试原则:u 软件测试是为了发现错误而执行程序的过程。u 一个好的测试用例具有较高的发现某个尚未发现的错误的可能性。u 一个成功的测试用例能够发现某个尚未发现的错误。第3章代码检查、走查与评审多年以来,软件界的大多数人多持有一个想法,即编写程序仅是为了提供给机器执行、并不是提供人们阅读的,软件测试的唯一方法就是在计算机上执行它。20世纪70年代早期,一些程序员最先意思到阅读代码对于构成完善的软件测试和调试手段的价值,通过他们的努力,原有的观念

37、开始发生变化。今天,并不是所有的软件测试人员都要阅读代码,但是研读程序代码作为测试工作的一部分,这个观念已经得到了广泛的认同。一下几个因素会影响到特定的测试和调试工作需要人工实际阅读代码的可能性;软件的规模和复杂度、软件开发团队的规模、软件开发的时限(例如时间安排表是松散 还是紧密)等,当然还有编程小组的技术背景你过河文化。基于这些原因,在深入研究较为传统的基于计算机的测试技术之前,我们首先讨论非基于计算机测试的过程(即“人工测试”)。人工测试技术在查找错误方面非常有效,以至于任何编程项目都应该使用其中的一种或多种技术。应该在程序开始编码之后、基于计算机的测试开始之前使用这些方法。同样,也可以

38、在编码的更早阶段开始设计和应用类似的方法(例如在每个设计阶段的末尾),但是这些容超出了本书讨论的围。在开始讨论人工测试技术之前,有一条重要的注意事项;由于包含了人为因素在,导致很多方法的正规性要差于由计算机执行的数学证明,人们可能会怀疑某些如此简单和不正规的东西是否有用。反之亦然,这些不正规的方法并没有妨碍测试取得成功;相反它们从一吓两个方面显著地提高了测试的功效和可靠性。首先,人们普遍认识到错误发现的越早,改正的成本越底,正确改正的可能性也越大。其次,程序员在开始基于计算机的测试时似乎要经历一个心理上的转变。从部产生的压力似乎会急剧增长,并产生一个趋势,要“尽可能快地修改这个缺陷”。由于这些

39、压力的存在,程序员在改正某个由基于计算机测试发现的错误时所犯的失误,要比改正早期发现的问题时所犯的失误更多一些。3.1 代码检查与走查代码检查与走查是两个主要的人工测试方法。由于这两种方法具有很多的共同之处,在这里我们将一起讨论他们的相似点,而它们的不同之处将在后续章节中进行介绍。代码检查与走查都要求人们组成一个小组来阅读或直观检查特定的程序。无论采用那种方法,参加者都要完成一些准备工作。准备工作的高潮是在参加者会议上进行的所谓“头脑风暴会”。“头脑风暴会”的目标是找出错误了,但不必找出改正的方法。换句话说,是测试,而不是调试。代码检查与走查已经广泛运用了很长时间。我们认为,它们的成功与本书第

40、2章所述的一些原则有关。在代码走查中,一组开发人员(三至四人为最佳)对代码进行审核。参加者当中只有一个人是程序编写者。因此,软件测试的主要工作是有其他人,而不是软件编写者本人来完成,这符合“软件编写者往往不能有效地测试自己编写的软件”的测试原则。代码检查与走查是对过去桌面检查过程(在提交测试前由程序员阅读自己程序的过程)的改进。与原方法相比,代码检查与走查更为有效,同样是因为在实施过程中,除了软件编写者本人,还有其他人参与进来。菜吗走查的另一个有点在于,一旦发现错误,通常就能在代码中对其进行精确定位,这就是降低了调试(错误修改)的成本。另外,这个过程通常发现成批的错误,这样错误就可以一同得到修

41、改。而基于计算机的测试通常只能暴露出错误的某个表征(程序不能停止,或打印出了一个无意义的结束),错误通常是逐个地被发现并的得到纠正的。在典型的程序中,这些方法通常会有效地查找出30%70%的逻辑设计和编码错误。但是,这些方法不能有效地查找出高层次的设计错误,例如在软件需要分析阶段的错误。请注意,所谓30%70%的错误发现率,并不是说所有错误中多达70%可能会被找出来,而是讲这些方法在测试过程结束时可以有效地查找出多大70%的已知错误。请记住,地2章告诉我们,程序中的错误总数始终是未知的。当然,可能存在对这些统计数字的批评,即人工方法只能发现“简单”的错误(即与基于计算机的测试方法相对比,所发现

42、的问题显得微不足道),而困难的、不明显的或微妙的错误只能用于计算机的测试方法才能找到。然而,一些测试人员在使用了人工方法之后发现,对于某些特定的错误,人工方法比基于计算机的方法更有效,而对于其他错误类型,基于计算机的方法更有效。这就意味着,代码检查/走查与基于计算机的测试是互补的。缺少其中任何一种,错误检查的效率都会降低。最后,不但这些测试过程对于测试新开发的程序有着不可估量的作用,而且对于测试更改后的程序,这些测试过程具有一样的作用,甚至更大。根据我们的经验,修改一个现存的程序比编写一个新程序更容易产生错误(以每写一行代码测错误数量计)。因此,出来回归测试方法之外,更改后的程序还要进行这些人

43、工方法的测试。3.2 代码检查所谓代码检查,是以组为单位阅读代码,它是一些列规程和错误检查技术的集合。对代码检查的大多数讨论都集中在规程,所要填写的表格等。这里对整个规程进行简短的概述,之后我们将重点讨论实际的错误检查技术。一个代码检查小组通常由四人组成,其中一个人发挥着协调作用。协调人应该是个职称的程序员,但不是该程序的编码人员,不需要对程序的细节了解的很清楚,协调人的职责包括以下几点:u 为代码检查分发材料、安排进程。u 在代码检查中起主导作用。u 纪录发现的所有错误。u 确保所有错误随后得到改正。协调人就像是质量控制工程师。小组中的第二个成员是该程序的编码人员。小组中的其他成员通常是程序

44、的设计人员(如果设计人员不同于编码人员的话),以与一名测试专家。在代码检查之前的几天,协调人将程序清单和设计规分发给其他成员。所有成员应在检查之前熟悉这些材料。在检查进行时,主要进行两项活动:1由程序编码人员逐条语句讲述程序的逻辑结构。在讲述的过程中,小组其他成员应提问题、判断是否存在错误。在讲述中、很可能是程序编码人员本人而不是其他小组成员发现了大部分错误。换句话说,对着大家大声朗读程序,这种简单的做法看来是一个非常有效的错误检查方法。2.对这历来常见的编码错误列表分析程序(该列表将在下一节中介绍)协调人负责确保检查回忆的讨论高效地进行、每个参与者都将注意力集中于查找错误而不是修改错误(错误

45、的修改正由程序员在检查会议之后完成)。会议结束之后,程序员会得到一份已发现错误的清单。如果发现的错误太多,或者某个错误涉与对程序做根本的改动,协调人可能会在错误修改后安排对程序进行再次检查。这份错误清单也要进行分析、归纳,用以提炼错误列表,以便提高以后代码检查的效率。如上所述,这个代码检查过程通常将注意力集中在发现错误上,而不是纠正错误。然而,有些小组可能会发现,当检查出某个小问题之后,有两三个人(包括负责该代码的程序本人)会建议对设计进行明显的修补以解决这个特例。那么,对这个小问题的讨论,反过来会将整个小组的注意力集中在设计的某个部分。在探讨修补设计来解决这个小问题的最佳方法时,有人可能会注

46、意到另外的问题。既然小组已经发现了设计中同一部分的两个相关问题,那么每隔几段代码就可能需要密集的注释。几分钟之,整个设计就被彻底检查完,任何问题都会一目了然。在代码检查的时间与地点的选择上,应避免所有的外部干扰。代码检查会议的理想时间应在90120分钟之间。由于开会是一项繁重的脑力劳动,会议时间越长效率越低。大多数的代码检查是都是按每小时大约阅读150行代码的数度进行。因此,对大型软件的检查应安排多个代码检查会议同时进行,每个代码检查会议处理一个或几个模块或子程序。请注意,要是检查过程有效,必须树立正确的态度。如果宣传员将代码检查视为对其人格的攻击、采取了防的态度,那么检查过程就不会有效果。正

47、确的做法是,程序员必须怀着非自我本位的态度来对待检查过程,对整个过程采取积极和建设性的态度:代码检查的目标是发现程序中的错误,从而改进软件的质量。正是因为这个原因,大多数人建议应对代码检查的结果进行,仅限于参与者围部。尤其是如果管理人员想利用代码检查结果,那么就与检查过程的目的背道而驰了。出了可以发现错误这个主要作用之外,代码检查还有几个有益的附带作用。其一,程序员通常会得到编程风格、算法选择与编程技术等方面的反馈信息 。其他参与者也可以通过接触其他程序员的错误和编程风格而同样受益匪浅。还有,代码检查还是早期发现程序中最容易出错部分的方法之一,有助于在基于计算机的测试过程中将更多的注意力集中在

48、这些地方(本书地2章中的测试原则之一)。3.3 用于代码检查的错误列表代码检查过程的一个重要部分就是对照一份错误列表,来检查程序发、是否存在常见错误。遗憾的是,有些错误列表更多地注重编程风格而不是错误(例如,“注释是否准确且有意义?”,“IFELSE代码段和DOWHILE代码段是否缩进对齐?”),错误检查太过模糊而实际上没有用(例如,“代码是否满足设计的需求?”)。本节镇南关讨论的错误列表是经多年对软件错误的研究编辑而成的。该错误列表在很大程度上是独立于编程的,也就是说,大多数的错误都可能出现在任意语言编写的程序中。读者可以把自己使用的编程语言中特有的错误,以与代码检查发现的错误补充到这份错误

49、列表中去。3.3.1 数据引用错误1. 是否有引用的变量未赋值或未初始化?这可能是最常见的编程错误,在各种环境中都可能发生。在引用每个数据项(如变量、数据元素、结构中的域)时,应试图非正式地“证明”该数据项在当前位置具有确定的值。2. 对于所有的数组引用,是否每一个下标的值都在相应维规定的界限?3. 对于所有的数组的引用,是否每个下标的值都是整数?虽然在某些语言中这不是错误,但这样做是危险的。4对于所有的通过指针或引用变量的引用,当前引用的存单元是否分配?这就是所谓的“虚调度(dangling reference)”错误。当指针的生命期大于所引用存单元的生命期时,错误就会发生。当指针引用了过程

50、中的一个局部变量,而指针的值有被赋给一个输出参数或一个全局变量,过程返回(释放了引用的存单元)结束,尔后程序试图使用指针的值时,这种错误就会发生。与前面检查的方法类似,应试图非正式地“证明”,对于每个使用指针值的引用,引用的存单元都存在。5.如果一个存区域具有不同属性的别名,当通过别名进行引用时,存域中的数据值是否具有正确的属性?在FORTRAN语言中对EQUIVALENCE语句而成为同一存域的别名。如果程序先对A赋值,然后又引用变量B,由于机器可能会将存中用浮点位表示的实数当作整数,在这种情况下错误就可能发生。6.变量的类型或属性是否与编译所预期的一致?当C、C+或COBOL程序将某个记录读

51、到存中,并使用一个结构来引用它时,由于记录的物理表示与结构定义在差异,这种情况下错误就可能发生。7.在使用的计算机上,当存分配的单元小于存可寻址的单元大小时,是否存在直接或间接的寻址错误?例如,在某些条件下,定长的位串不必以字节边界为起点,但是地址又总是指向字节边界的。如果程序计算一个位串的地址,稍后又通过该地址引用这个位串,可能会指向错误的存位置。将一个位串参数传送给一个子程序时,也可能发生这种情况。8.当使用指针或引用变量时,被引用的存的属性是否编译所预期的一致?这种错误的一个例子是,当一个指向某个数据结构的C+指针,被赋值为另为的数据结构的地址。9.假如一个数据结构在多个过程或子程序中被

52、引用,那么每个过程或子程序对该个、结果的定义是否都一样?10.如果字符串有索引,当对数组进行索引操作或下标引用,字符的边界取值是否有“仅差一个”(offbyone)的错误?11.对于面向对象的语言,是否所有的继承需求都在实现类中得到了满足?3.3.2 数据申明错误1. 是否所有的变量都进行了明确的声明?没有明确声明虽然不一定是错误,但通常却是麻烦的源头。举例来说,如果一个程序的子程序接收一个数组参数,却未将该参数定义为数组(如用DIMENSION 语句),对该数组的引用(如C=A (I)会被解释为一个函数调用,导致计算机试图将此数组当作程序执行。另外,如果某个变量在一个部过程或程序坏中没有明确

53、声明,是否可以理解为该变量在这个程序块中被共用?2. 如果变量所有的属性在声明中没有明确说明,那么说明默认的属性能否被正确理解?举例来说,在JAVA语言中,程序接收到的恶魔人属性往往是导致意外发生的源头。3. 如果变量在声明语句中被初始化,那么它的初始化是否正确?在很多语言中,数组和字符串的初始化比较复杂,因此也成为容易错误的地方。4. 是否每个变量都被赋予了正确的长度和数据类型?5. 变量的初始化是否与其存储空间的类型一致?举例来说,如果FORTRAN语言子程序中的一个变量在每次调用子程序时都需要重新初始化一次,那么必须使用赋值语句对其初始化,而不应该用DATA语句。6. 是否存在着相似名称

54、的变量(如VOLT和VOLTS)?这种情况不一定是错误、但应被视为警告,这些名称可能会在程序中发生混淆。3.3.3 运算错误1. 是否存在不一致的数据类型(如非算术类型)的变量的运算?2. 是否有混合模式的运算?例如,将浮点变量与一个整形变量做加法运算。这种情况并不一定是错误,但应该谨慎使用,确保程序语言的转换规则能够被正确理解。卡看下面的JAVA程序片段,显示了整数运算中可能发生的取整误差:int x = 1;int y = 2;int z = 0;z = x/y;System.out.pirntln(“z = “+ z);Output;Z = 0;3. 是否有一样数据类型、不同字长变量间的

55、运算?4赋值语句的目标变量的数据类型是否小于右边表达的数据类型或结果?5. 在表达式的运算中是否存在表达向上或向下溢出的情况?也就是说,最终的结果看以来是个有效的值、但中间结果对于编程 语言的数据类型可能过大或过小。6. 除法运算中的除数是否可能为0?7 如果计算机表达变量的基本方式是基于二进制的,那么运算结果是否不精确?也就是说,在一个二进制计算机上,10*0.1很少会等于1.0 。.8. 特定场合,变量的值是否超出了有意义的围?例如,对变量PROBABILITY赋值的语句可能需要进行检查,保证赋值始终为正且不大于1.0。9. 对于包含一个以上操作符的表达式,赋值顺序和操作符的优先顺序是否正

56、确?10. 整数的运算是否有使用不当的情况,尤其是除法?举例来说,如果i是一个整形变量,表达式2*i/2= =i是否成立,取决于i是奇数还是偶数,或是先运算乘法,还是先运算除法。3.3.4比较错误1.是否有不同数据的变量之间的比较运算,例如,将字符串与地址、日期或数字相比较?2.是否有混合模式的比较运算,或不同长度的变量间的比较运算?如果有,应确保程序能正确理解转换规则。3.比较运算符是否正确?程序员经常混淆“至多”、“至少”、“大于”、“不大于”、“小于”和“等于”等比较关系。4.每个布尔表达式所叙述的容是否都正确?在编写涉与“与”、“或”或“非”的表达式时,测试员经常犯错。5.布尔运算的操

57、作数是否是布尔类型的?比较运算符和布尔运算符是否错误地混在了一起?这是一类经常会犯的错误,这里我们描述几个典型错误的例子。如果想判断i是否在210之间,表达式2i 10是不正确的;相反,正确的应该是(2 i)&( i x|y也是不正确的,正确的应该是(ix)|(i)y。如果要比较三个数字是否相等,表达式if(a= =b = = c)的实际意思却大相径庭。如果许啊哟验证数学关系xyz,正确的表达式应该是(xy)&(yz)。6.在二进制的计算机上,是否有二进制表示的小数或浮点数的比较运算?由于四舍五入,以与用二进制表示十进制数的近似度,这往往是错误的根源。7.对于那些包含一个以上布尔运算的表达式,

58、赋值顺序以与运算的优先级是否正确?也就是说,如果碰到如同(if ( (a = =2)&(b = =2)|(c= = 3)的表达式,程序能否正确理解是“与”运算在先还是“或”运算在先?8.编译计算布尔表达式的方式是否会对程序产生影响?例如,语句if(x = =0 &( x/y)z)对于有的编译来说是可接受的,因为其认为一旦“与”运算的一侧为FALSE时,另一侧就不用计算;但是对于其他编译来说,却可能起一个被0除的错误。3.3.5 控制流错误 1. 如果测试包好多条分支路径,比如有计算GO TO语句,索引变量的值是否会大于可能的分支数量?例如,在语句GO TO (200 ,300,400),i2.

59、是否所有的循环最终终止了?应设计一个非正式的证明或论据来证明每一个循环打击都会终止。3.程序、模块或子程序是否最终终止了?4.由于实际情况没有满足循环的入口条件,循环是否有可能从未执行过?如果确实发生这种情况,这里是否是一处疏漏?例如,如果循环一下的语句作为开头:For (I = =x; i=z;i +)While (NOTFOUND)当NOTFOUND初始时就为假,或者x大于z时,情况会如何呢?5.如果循环同时由迭代变量和一个布尔条件所控制(如一个搜索循环),如果循环越界(fall-through)了,后果会如何?例如,伪指令循环以DO I=1 TO TABLESIZE WHILE (NOT

60、FOUND)开头,如果NOTFOUND永不为假,会发生什么结果呢?6是否存在“仅差一个”的错误,如迭代数量恰恰多一次或少一次?这在从0开始的循环中是常见的错误。我们会经常忘记将“0”作为一次计数。举例来说,如果想编写一段JAVA代码执行10次循环,下面的语句是错误的,因为它执行了11次:For ( int i=0;i=10;i+)System.out.println( i );正确的应该是执行10次循环:For ( int i = 0 ;Ii =9; i+)System.out.println ( i);7.如果编程语言中有语句组成代码的概念 (例如do-while或),是否每一组语句都有一个

61、明确的while语句,并且do语句也与其相应的语句组对应?或者,是否每一个左括号多对应有一个右括号?目前的大多数编译器都能识别保护这些不匹配的情况。8.是否存在不能穷尽的判断?举例来说,如果一个输入参数测预期值是1.2或3,当参数值不为1或2时,在逻辑上是否假设了参数必定为3?如果是这样的话,这种假设是否有效?3.3.6 接口错误1.被调用模块接收到的参数(parameter)数量是否等于调用模块发送的参数(argument)数量?另外,顺序是否正确?2.参数的属性(如数据类型和大小)是否与相应形参的属性相匹配?3.实参的量纲是否与对应的量纲相匹配?举例来说,是否形参以度为单位而实参以弧度为单

62、位?4.此模块传递给彼此的实参数量,是否等于彼此模块期望的形参数量?5.此模块传递给彼此模块的实参的属性,是否与彼此模块相应形参的属性相匹配?6.此模块传递给彼此模块的实参的量纲,是否与彼此相应形参的量纲相匹配?7.如果调用了置函数,实参的数量,属性,顺序是否正确?8.如果某个模块或类有多个人口点,是否引用了与当前人口点无关的形参?下面PL/I程序的第二个赋值语句就存在这种错误;A: PROCEDURE( W,X); W = X +1;REJURNB:ENTRY ( Y,Z);Y = X+Z;END;9.是否有子程序改变了某个原本仅为输入值的形参?10.如果存在全局变量,所有引用他们额模块中,

63、它们的定义和属性是否形同?11.常量是否以参数形式传递过?在一些用FOTRAN语言编写的程序中,诸如CALL SUBX (J,3)的语句是很危险的,因为如果子程序SUBX对其第二个形参进行赋值,常数3的值将会改变。3.3.7 输入/输出错误1.如果对文件明确声明过,其属性是否正确?2.打开文件的语句中各项属性的设置是否正确?3.格式规是否与I/O语句中相一致(就各项的数量和属性而言)?4.是否有足够的可用存空间,来保留程序将读取额文件?5.是否所有的文件在使用之前都打开了?6.是否所有的文件在使用之后都关闭了?7.是否判断文件结束的条件,并正确处理?8.对I/O出错情况处理是否正确?9.任何打印或显示的文本信息中是否存在拼写或语法错误?3.3.8 其他检查1.如果编译器建立了一个标识符交叉引用列表,那么对该列表进行检查,查看是否有变量从未引用过,或仅被引用过一次。2.如果编译器建立了一个属性列表,那么对每个变量的属性进行检查,确保没有赋予过不希望的默认属性值。3.如果程序编译通过了,但计算机提供了一个或多个“警告”或“提示”信息,应对此逐一进行认真检查。“警告”信息指出编译器对程序某些操作的正确性哟所怀疑;所有这些疑问都应进行检查。“提示”信息可能会罗列出没有声明的变量,或者是不利于代码优化的用法。4.程序或模块是否具有足够的鲁棒性?也就是说,它是否对其

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!