软件测试实战 微软技术专家经验总结,一本微软的好书,经验积累目录3.2.13测程表…,.,,,,,,,,,,,61562设计用户角色………………1583.214移交文档…………………………67563情景测试与漫游测试…………16133在测试中发展测试文档675.64肥皂剧测试……3.3.1初始测试文档…67565虚拟业务…164332发展测试文档……………705.7多样地选择测试技术…………………16534小结……………………7158小结………………………166第4章测试建模73第6章测试开发…………………16841从组合测试看建模的重要性7361测试开发分类………164.1.1组合测试简介……7362注重实效的自动化测试……1694.1.2根据语境来完善组合测试的62.1自动化测试的基本策略………169模型…………………………………766,22将测试开发视作软件开发…………1724.1.3测试建模的基本点62.3利用自动化测试金字塔来指导4.2常用测试建模方法测试开发…1754.2.1启发式测试策略模型6.2.4面向调试的测试代码………1774.2.2输入与输出模型……916,2.5系统测试的测试开发………………1824.2.3系统生态图…………………………9662.6让自动化测试服务于项目………1904.2.4实体关系模型……………………10163计算机辅助测试……19342.5状态机模型1056.3.1“交通工具”的隐喻……………1934.2.6多种多样的模型…………109632选择合适的开发技术………1954.3小结……………11364大规模自动化测试204第5章测试技术641基本概念……………204…115642测试设计20651测试技术分类系统………………1156.5小结……………………21152启发式方法.,:,,,,,,1205,3测试先知……122第7章研究产品………………2135.31测试先知的定义…………12271静态分析………2135.3.2 FEW HICCUPPS…………1237.1.1浏览源代码来理解产品实现……213533约束检查1297.1.2分析源代码来帮助测试设计…22154漫游测试…………………133713黑盒测试并不是基于无知的5.4.1基本漫游方法………134测试………………22754.2基于旅行者隐喻的漫游方法……1357.2动态分析……22954.3移动测试漫游方法…………………139721用工具分析产品的行为…………2295.44实施漫游测试……………………142722在调试器中观察软件行为2375.5快速测试……………………1447.3业务研究2415.51 James Bach的方法…………14573.1理解关系人………………2415.52 Cem Kaner的方法…………1477.3.2评审需求文档……………2455.53 James Whittaker的方法…149733通过测试来研究………………25156情景测试…………………154734利用互联网资源………………2555.6.1基本方法………………15573.5领域研究……258XlV·目录74研究策略………,,·,………26093软件估算……………2997.5小结261931测试人员应该估算自己的第8章研究项目任务…………………300…………26293.2用计数和计算作为估算手段……30281项目团队…………………………262933历史数据是估算的重要参考……30381.1了解团队组织……………262934同时估算最差情况和最好情况…3058.1.2语境独立的启发式问题………26494度量………………………………30581.3了解团队成员……………268941理解度量方法的基本元素……3068.2面向测试的项目分析………270942明确度量的目标……30782.1软件缺陷……………270943掌握属性和算法的联系…30982.2源代码…………274944理解度量方法的优点和缺点……311823构建…………………………27794.5密切关注度量的副作用…31824自动化测试………………………2799.46注重实效的计算…………31483基于风险的测试………………28295测试小组…………………3158.3.1通过测试调查风险………………2829.5.1价值观3158.32失败模式…………………………284952团队建设…………………………316833项目级别的风险…………………2859.6小结……………………………31884小结………………………287第10章个人管理…319第9章团队工作…………………28810.1时间管理………………………31991工作风格………28810.1.1利用任务清单记录所有工91.1测试人员通过服务团队来体现作项……………………………319自己的价值………………28810.1.2坚持周计划和每日回顾……3229.1.2测试人员应该正直……………29010.1.3专注是高效工作的前提……3229.3测试人员的影响力来自于出色10.1.4恰到好处的文裆化和自动的工作……292化…………………32491.4信任程序员的努力,并用技术10.2持续学习……328调查检验其工作……………29210.21在工作中学习………………32892测试管理………………………………29310.22持续阅读……………………32992.1个人测试计划应该是项目测试103且行且思…330计划的延伸……………………293104成为专家……333922制订个人测试计划时应该综合10.5小结………………………………335考虑各种项目元素…………29492.3测试需要动态管理………297参考文献…136XV第(Ⅰ章软件测试基础本章将阐述一些软件测试的基本观点,它们是全书的基石。虽然它们并没有得到所有人的认可,但是我认为它们反映了软件测试的基本事实。测试人员需要仔细分析它们,并用于实践,才能有效地实施软件测试。11软件的复杂度已经超越了人的理解能力必应词典是我常用的一款桌面软件(如图1-1所示),它将用户输入的英文单词发送给必应服务器,然后接受服务器所返回的中文解释,最后将中译显示在界面上。必应gD英文热点早知estingtesting us: [test] a ti同义词tests tested testing英汉释义黄汉○英英examnation●寿试測验assa%e【医】医字的)检查医字鉴定化验assessment试验;检测ecperimentation0跟难处境:考验;试金石research●【板】板球赛常用于英式英语imvestigation删式测验challenginge【医】(医学的脸查:化验difficult6(为鉴定面进行脸验:检剩试验taxn考验:考查例句用法tryingAll pupils would have easy access to emergency contraception反义词)eay20分钟测出你的英语能力取词划译图1-1必应词典①htt/ dict. bing. msn.cn第1章软件测试基础必应词典是一个NET程序。它会启动一个专属线程来接受服务器的返回结果,其托管代码( managed code)的调用栈类如代码清单1-1所示。代码清单11必应词典的调用栈System. Net. UnsafeNcINativeMethods+OSSOCK. recv(Intptr, Byte*, Int32,System. Net. Sockets. SocketFlagsSystem. Net. Sockets. Socket Receive(Byte[], Int32, Int32,System. Net. Sockets. Socket Flags, System. Net. Sockets. SocketError ByRef)System. Net. Sockets. Socket Receive(Byte[], Int32, Int32,System. Net. Sockets. SocketFlags)System. Net. Sockets. NetworkStream Read(Byte[], Int32, Int32)System. Net. PooledStream Read(Byte[], Int32, Int32)System. net. Connection Syncread (sYstem. Net. HttpwebrequesT,Boolean,Boolean)System.Net.cOnnectionPollandread(system.Net.httpwebrEquest,BooleanSystem. Net. ConnectStream PollAndRead( Boolean)System Net. Httpwebrequest. EndwriteHeaders(boolean)System Net. HttpwebrequeSt.writehEaderscallback(system.Net.WebexceptIonstatus,System. Net. ConnectStream, Boolean)System. Net. ConnectStream WriteHeaders( BooleanSystem Net. HttpwebrequesT. EndsubmitrEquest()System Net. Httpwebrequest.CheckdeferredcalLdone(system.Net.Connectstream)System Net. HttpwebrequeSt. GetresponsEo)System. Web Services. Protocols. WebclientProtocol. GetwebResponseSystem. Net. WebRequestSystem Web Services Protocols Httpwebclientprotocol. getwebresponse(System. Net. WebRequest)ystemWeb.ServicesProtocolsSoaphttpclieNtprotocol.Invoke(system.StringSystem.Object[D)Engkoo Ehc Core. EhcAPI EhcData ServiceV1 GetEditModeResult(System. String,System. String, System. String, System. String, Int32, BooleanEngkoo Ehc Core. OnlineDictionaryV2 ProcessEditRequest(DataRequest)Engkoo Ehc Core. OnlineDictionaryV2 AsyncProcO)System. Threading. ThreadHelper ThreadStartContext(SystemObject)System. Threading ExecutionContext. runTryCode (System Object)[HelperMethodFrame PROTECTOB]: oda8f3f8System. Runtime CompilerServices. RuntimeHelpers Execute CodewithGuaranteedCleanup(TryCode, CleanupCode, System ObjectSystem. Threading Execution Context. RunInternal(System. Threading ExecutionContextSystem. Threading Context Callback, System ObjectSystem. Threading Execution Context. Run( System. Threading ExecutionContextSystem. Threading. ContextCallback, System Object)System. Threading. ThreadHelper ThreadStarto)该调用栈涉及26个函数,使用了一些典型的开发技术,具体如下所示口 Socket通信( System. Net. Socket)口HTTP通信(System.Net.Httpwebrequest)口SOAP通信协议(System.Web.elves.Protocols.SoaphttpclienTprotoco1)①本章讨论的是必应词典1.7版。自20版开始,必应词典的主程序( BingDict.exe)不再是NET程序,而是CC++程序。1.1软件的复杂度已经超越了人的理解能力口异步调用( Engkoo.Ehc.Core. OnlineDictionaryV2. AsyncProc)口线程( System. Threading)随着开发技术的发展,现在开发人员不必理解这些技术细节,只要调用程序库,就可以完成客户端(必应词典)与服务端(必应服务器)的通信。相比于底层技术,这些程序库提供了更高的抽象层次。然而,软件专家 Jole Spolsky提出了经验法则“抽象漏洞定律”:“所有非平凡的抽象,在某种程度上,都存在漏洞。”[ Spolsky02]他敏锐地指出,虽然高抽象层次的语言、程序库和框架等技术提高了开发者的生产力,使他们不必总是关心技术细节,然而总是存在一些情况,需要开发者深入底层,去研究那些为了提髙生产率而省略的细节问题。高抽象级别的技术虽然可以减少编写代码的时间,但是并不能减少开发者学习整个技术栈的时间。只停留在高抽象层次的开发者将难以解决复杂的实际问题,且有可能引入更多的设计错误对于必应词典,与服务器通信是相对简单的任务,它使用了一些常见的重要技术,开发者完全理解这些技术需要付出很大的努力。然而,必应词典所涉及的技术细节远不止于此,它拥有40多个线程,加载170多个动态链接库,拥有1000多个 Windows句柄。毫不夸张地说,几乎没有人可以完全理解它使用的所有技术,也无法掌握它任意时刻的状态。不过,软件技术只是软件复杂性的一部分。成功的软件必须帮助用户解决实际问题,使他们获得成功。因此,项目团队需要研究用户情景和领域知识,然后创造性地提岀解决方案,并选择合适的技术来实现。在这个研究、创造、应用的过程中,项目团队会面临更多的挑战和困难,而能否处理领域复杂度和设计复杂度是决定产品成败的关键。例如,对于必应词典而言,发送请求并接受响应是相对容易的,困难的是为一个单词提供准确的定义、例句、搭配、同义词等信息,更困难的是为一个句子提供恰当的翻译,并流畅地将它朗读出来。这些困难的任务恰恰是用户选择词典软件的重要参考。由以上讨论不难看出,软件复杂度包含技术、领域、设计等多个方面。随着软件行业的快速发展,软件复杂度已经超越了个人的理解能力。那么,从测试的角度来说,测试人员应该如何应对这一情况呢?本书所介绍的大部分实践都是为了解决该问题的。在这里,我简单陈述一些基本态度和方法。口对于复杂的软件,任何人都不可能掌握全部的信息。如果测试人员对软件的理解存在许多偏差,他的测试策略一定会包含错误。为了更好地理解软件,他需要与产品经理、程序员、领域专家、测试同事等协作,还需要研究项目文档、技术资料、领域专著等文献,并通过实际测试去获得第一手知识。测试人员不应该依赖单一的或局限的信息源,他应该从各种渠道获得信息,多角度地研究软件。口由于软件如此复杂,大多数测试人员在项目之初都不甚了解软件,其拟定的初始测试方案或多或少都存在错漏,有些甚至存在严重错误。注重实效的测试人员,会承认测试方案是不完备的,并迭代地实施测试,通过持续地评估和反思来逐步增强测试方案。第1章软件测试基础口对于现实世界的软件,穷举测试是不可行的。任何实用的测试技术都是基于一定策略的采样,即从无限多的测试输入中选择一个数量有限的子集,通过运行这批测试来评估软件的整体情况。考虑到软件的复杂度,任何一种测试技术都存在不能正确评估软件的风险。而且,在测试之初,测试人员也很难预料究竞哪些测试技术才适合当前项目。为此,测试人员应该积累多种测试技术,综合运用它们,并随着项目发展积极调整测试策略,才能避免重大测试遗漏。口人们处理复杂问题的常用策略是“分而治之”。在软件领域,建立合理的抽象模型是应对软件复杂性的常见方式。在测试领域,测试人员可以建立产品的模型来帮助测试。在建模过程中,他们以当前测试目标为指导,省略无关的产品细节,突出重要的产品元素。面对简化后的产品模型,可以更有针对性地实施测试设计。口在大规模软件中,对于少量代码的变更都不可以掉以轻心,因为修改者、代码评审者、测试者都很难预料这段代码被调用的语境和执行后的影响。例如,程序员要修改网页浏览器(如、 Chrome、 Firefox等)排版引擎的一个排版缺陷,通常需要运行大规模的回归测试。因为全世界的网页千差万别,很难预测这段代码会排版何种网页,也很难预测这段代码是否会破坏某些精心排版的页面。只有运行大规模测试,才能保证代码变更的正确性。口单凭人的脑力已经难以应对软件的复杂度了,测试人员需要考虑利用自动化测试开发强力的测试策略。1.2软件测试是获取信息的技术调查不同的人有不同的背景、不同的目标、不同的任务,对软件测试也会给出不同的定义,因此不存在放之四海皆准的软件测试定义。不过,对于软件测试工程师而言,我认为有3个软件测试的定义很有启发性。定义1:测试是为了发现错误而执行程序的过程[ Myers79。该定义是 Glenford J. Myers在1979年提出的,历经30多年的考验,至今仍被广泛引用和讨论。这是一句简短而有力的论述,它紧扣测试的基本活动——执行程序和寻找错误,符合大多数测试人员的工作内容,因此更容易获得广泛认可。此外,它揭示了软件测试的根本原因,即某些重要的东西可能出错〖 Kaner1,软件测试就是要发现这些错误。它给测试人员的启示是,测试人员应该始终质疑并挑战软件。有些测试任务的字面内容类似于“检查本次代码变更是正确的”,好像要求测试人员去验证软件行为是正确的。对于此类任务,测试人员应该假定代码变更引人了未知的错误,然后想尽办法去攻击软件。即便测试人员最后的结论是“我没有发现错误”,攻击性的测试过程也使这个结论更有可信度。定义2:测试是一个获取信息的过程,用来降低决策风险[ Weinberg08]。Genald m. Weinberg认为人不是完美的思考者,面对复杂的情况会作出许多错误的决定。在41.2软件测试是获取信息的技术调查采购、选择、使用、开发软件的过程中,人们需要作出许多决定。不完美的思考导致有风险的决策,可能造成巨大的损失。他指出测试可以获得更多的信息,使人们更周全地思考,从而降低错误决策的风险。该定义给了我(一个测试人员)一系列启示。口测试是服务性的工作。通过测试,我向整个团队提供关于产品质量和项目环境的信息、帮助他们作出决定。口低质量的信息不但无助于决策,还可能浪费团队的时间,甚至作出错误的决策。因此,我应该总是提供高质量的信息。这通常体现为及时地交流、周密地测试、仔细地报告。口团队的决定可能与我的期望不一致,要去理解导致该决定的其他信息。例如,我提交了一个严重的缺陷,团队领导却决定不予修复。此时,应该提供更多的信息,据理力争,同时要去理解不予修复背后的原因,从而更好地理解软件和项目。口为了更全面地提供信息,除了运行软件,我还需要更多的获取信息的方法。常见的手段包括与程序员交谈、研究项目资料、学习领域知识、阅读源代码、在调试器中观察软件等。口除了软件缺陷,测试还可以提供关于项目环境的信息。例如,在项目过程中,产品安装总是遇到许多问题。在报告缺陷的同时,我还可以向团队领导反馈:“开发小组是否在产品安装上投入了足够多的资源?因为安装是任何测试的先决条件,安装的错误将阻碍或延缓测试,测试小组建议将它视作第一等的功能需求。定义3:软件测试是一种技术调查,其目的是向关系人提供有关产品(软件、系统或服务)质量的实验信息区 Kaner6]该定义是 Cem Kaner教授提出的,他也认为测试是一种服务。服务的客户是项目关系人,服务的内容是提供产品质量的实验信息。质量就是对某个(某些)人而言的价值 Gause89。不同的人对于质量有不同的评判标准,对于信息有不同的需求。常见的项目关系人包括客户(购买产品的人)、用户(使用产品的人)、程序员、产品经理、运维人员、市场营销人员、管理人员等,他们对信息的需求是测试人员主要的工作内容。请看如下案例。口测试经理对测试人员说:“你刚提交了一个严重的缺陷,做得好!但是,现在临近发布,修复它的风险很高。你能不能调查一下这个缺陷在哪些情况下出现,会影响哪些用户,导致的最坏结果是什么?我们会根据这些信息来决定是否修复和修复策略。”口程序员对测试人员说:“我完成了一个补丁的开发,下周将部署到产品环境中。你能否在预发布环境中部署它,并跑一些系统测试?它只是缺陷修复,没有引入新功能,应该不会破坏当前系统的运行。”口产品经理对测试人员说:“我们在当前版本中启用了新的图形渲染引擎,能够明显提高画质,但是试用者反映这个版本的性能不如上一版。你能不能做一些实验,看看当前版本在哪些场景中比较慢,慢多少?Q第1章软件测试基础口运维人员对测试人员说:“一个用户在产品论坛上发帖说,软件在启动时会弹出一个报错对话框,跟帖的几个人也说遇到过相同的情况。我从没有见过该问题,所以不知如何解决。你能不能看一下这个帖子,试着在测试环境中复现?这个缺陷在下一版已经修复了吗?”以上案例都表明,除了发现缺陷外,测试人员还通过多种方式向不同的关系人提供信息:向管理人员提供调査报告,向程序员提供代码的质量反馈,向产品经理提供技术支持,向运维人员提供已知缺陷的信息,在邮件组中回答用户提问等。为了更有效地测试,测试人员需要与测试经理讨论,设定测试服务的优先级,为关系人提供满足其要求的高质量的信息。例如,提供给测试经理的信息要面向项目风险,提供给程序员的信息要包含更多的技术细节,提供给产品经理的信息要侧重于用户体验和产品价值,提供给运维人员的信息要建议可能的解决方案。此外, Cem Kaner还强调软件测试的主要工作是技术调查,即以职业的态度、专业的技能对产品的未知领域进行探索。与地质勘查、罪案侦查、事故调查等调査活动相似,测试具有系统性、客观性、探索性和机动性。口测试应该系统地调查被测试对象。测试人员需要对产品进行周密的分析与检查。地质勘查结束后,勘查人员会给出详细的地质图,以描绘该地区的全貌。测试结束后,测试人员也应该全面掌握被测试对象的情况。口测试所提供的信息应该来自科学实验和中立观察。在真实和客观的基础上,包含合理的推测和建议。口刑侦人员会利用多种方法,从各个信息源收集情报,因为很难预测何处会有重大发现当突破性情报浮现时,他们会转移工作重点,顺着新线索紧追不舍。测试人员也需要综合运用多种技术和工具,去探究新的信息,并根据新发现及时调整测试方向。口优秀的澘水员既能够通过浮潜去游历宽阔的水域,也可以利用水肺澘水去探索深海水域[ Demarco08]。测试人需要交替使用广度调査和深度调查,从而更有效地提供信息。广度调査有助于发现高风险的区域,深度调查能够提供详细的信息,以支持项目关系人作出正确的决定。13测试是迭代过程测试是一个贯穿项目周期的调查过程。为了阐述技术细节,许多测试文献只讨论了该过程的小部分。因此,它们无意中将测试描绘为一个线性过程:测试人员获得测试任务,对被测软件进行分析,制订测试计划,确定测试用例,然后……没有“然后”了,因为大多数文献只写完第一轮测试设计便结束了。但是测试并不是一个线性过程。《计算机软件测试》 Kaner1]第1章的目录更符合测试人员的工作方式