软件测试实战:微软技术专家经验总结(txt+pdf+epub+mobi电子书下载)


发布时间:2020-06-29 14:27:38

点击下载

作者:史亮编著

出版社:北京图灵文化发展有限公司

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

软件测试实战:微软技术专家经验总结

软件测试实战:微软技术专家经验总结试读:

前言

我在攻读博士学位时开始研究软件测试,毕业后一直任职测试工程师,从事第一线的测试工作,不知不觉已有十余年的光阴。在此期间,我阅读过大量的测试文献,参与过多个不同类型的测试项目,既学到了许多有价值的方法,也观察到了一些不太有效的实践,既通过努力获得过成功的经验,也从错误中得到了宝贵的教训。随着经历的增长,我渐渐构建出自己的知识体系,从实践中打磨出一批指导测试工作的策略与经验。自然而然,一个朴素的想法浮现出来:如果将我的所学所知分享给更多的测试工程师,想必能帮助他们节省学习与积累的时间,以更快地提高测试水平。在该想法的驱动下,我广泛地阅读了测试文献,深入地反思了自己的实践,并开始了漫长的写作。成果就是您所读到的这本书。

本书分享了我从事软件测试工作所学到的知识和所总结的经验,旨在帮助测试人员建立正确的观念,并掌握一批切合实战的测试技术。一方面,我总结了测试专家的见解和方法,将其精华内容综述在本书之中,以帮助读者提高学习效率、快速地掌握综合性的技能。另一方面,我努力将自己的经验和反思融入书稿,使它反映出我在工作中使用的策略、方法和技巧。总之,这是一本注重实效的书,尝试用理论结合实践的方式来解决现实的问题。

本书的组织方式

在概述一些基本测试观点(第1章)之后,本书按照“启发式测试策略模型”(参见4.2.1节)的基本元素来展开论述:观察到的质量(第2章)、测试设计(第3、4、5、6章)、产品元素(第7章)和项目环境(第8章)。随后,讨论了测试人员如何参与团队工作(第9章)并实施个人管理(第10章)。

第1章阐述我对软件测试的基本观点,介绍了我的测试价值观。作为指导原则,它们将贯穿全书的内容。

第2章讨论了测试人员最主要的工作产出——缺陷报告,介绍了一批实践方法,帮助测试人员高质量地报告缺陷,并利用该过程来改进测试设计。

第3章讨论作为测试辅助工具的测试文档,介绍了一些编写和维护文档的原则和方法。通过分析一批具体的测试文档,展示出测试设计的迭代性和多样性。

第4章介绍指导测试设计的模型,通过应用组合测试,阐述了如何根据项目语境来完善测试模型,然后介绍了测试建模的基本原则和常用方法。

第5章介绍一个测试技术分类系统,以概览各类测试技术。然后,讨论了一批有价值的测试技术,包括启发式测试先知、漫游测试、快速测试、情景测试等。在此基础上,强调了测试人员应该多样地选择测试技术,以动态地优化测试的价值。

第6章讨论了测试开发的基本分类,然后针对自动化测试、计算机辅助测试和大规模自动化测试,阐述了它们的基本概念、设计目标、开发策略和实作方法。

第7章讨论如何从测试视角来研究软件产品和业务领域,介绍了静态分析、动态分析、关系人研究、需求评审、测试调查、网络调研、领域研究等研究方法。

第8章讨论如何从测试视角来研究项目环境,介绍了团队分析、缺陷分析、源码分析、构建分析、自动化测试分析、基于风险的测试等研究方法。

第9章探讨测试人员如何有效地在团队中工作,以及如何恰当地实施测试管理。针对一些常见任务,如小组协作、测试计划、工作量估算、软件度量等,提出了一批注重实效的方法。

第10章分享了我实施个人管理的基本方法,包含时间管理、个人学习、经验积累、专业发展等。

目标读者

本书的主要读者是具备一定测试经验、想要进一步提高测试能力的测试工程师。全书综合了测试行家的专业建议和我的实践经验,探讨了测试价值观、测试设计、产品研究、项目研究、团队协作、个人管理等多个方面,能够帮助读者更好地理解软件测试,并提高实践水平。本书的内容面向广大的测试社区,并不要求读者掌握特定的背景知识。我希望它能够适合大多数测试人员,并通过解决现实问题来引起读者的共鸣。

此外,本书是很好的软件工程课程、软件测试课程和测试培训的参考资料,能帮助本科生、研究生和测试学员更好地理解真实的软件测试。一些测试人员在工作后会发现,课程教材和培训教程所描述的内容并不切合实际的测试工作。例如,课本中的测试设计和执行是线性实施的,真实测试流程却是迭代展开的;缺陷报告常常是测试工作的核心产出,教材却没有讨论如何有效地管理缺陷报告;测试人员被要求撰写文档,其成果又被束之高阁,却少有教程讨论如何编写有价值的文档。这时,他们可以参考本书所提出的建议,从而发展出更有效的工作策略。

如何阅读本书

本书第1章讨论软件测试的基本事实和价值观,是全书内容的基础,需要首先阅读。在读完第1章后,读者可以按任意顺序阅读本书。您既可以顺序浏览,以概观软件测试,也可以有选择地阅读感兴趣的章节,并在阅读的过程中参考相关内容。

这是一本关于实践的书,许多建议和方法来自于实践。软件开发专家Ralph E. Johnson 指出,“从实践中来的知识在没有实践之前是无法被真正理解的”(practical knowledge has to be experienced to fully understood),测试专家Cem Kaner、James Bach等也认为“你不能掌握测试,除非你重新发明它”(You can’t master testing unless you reinvent it)。在阅读过程中,读者需要积极思考本书的方法是否适用于自己的项目,然后将恰当的方法应用于真实的测试,并认真评估其效果。通过练习、评估和反思,读者能够掌握方法的原理和细节,并混入自身经验和其他技术,以演化出新的方法。坚持这样的研究和创新将帮助测试人员走上精通之路。

致谢

作为作者,我诚挚感谢人民邮电出版社和北京图灵文化发展有限公司为我提供创作的平台。感谢本书的编辑王军花、张霞等,你们的专业态度和细致工作提升了本书的品质。

我还要感谢审稿人和推荐人的批评指教,你们的细心评阅和宝贵意见令我受益匪浅。谢谢你们的时间和智慧。

最后,我要感谢妻子汤红红,没有你的理解和支持,我无法完成此书。我还要感谢儿子史泰德用欢笑带给我快乐与能量,你令我想成为一个更好的人。感谢你们让我梦想。第1章软件测试基础

本章将阐述一些软件测试的基本观点,它们是全书的基石。虽然它们并没有得到所有人的认可,但是我认为它们反映了软件测试的基本事实。测试人员需要仔细分析它们,并用于实践,才能有效地实施软件测试。1.1 软件的复杂度已经超越了人的理解能力[1]

必应词典 是我常用的一款桌面软件(如图1-1所示),它将用户输入的英文单词发送给必应服务器,然后接受服务器所返回的中文解释,最后将中译显示在界面上。图1-1 必应词典[2]

必应词典是一个.NET程序 。它会启动一个专属线程来接受服务器的返回结果,其托管代码(managed code)的调用栈类如代码清单1-1所示。

代码清单1-1 必应词典的调用栈

System.Net.UnsafeNclNativeMethods+OSSOCK.recv(IntPtr, Byte*, Int32,

System.Net.Sockets.SocketFlags)

System.Net.Sockets.Socket.Receive(Byte[], Int32, Int32,

System.Net.Sockets.SocketFlags, 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.Connection.PollAndRead(System.Net.HttpWebRequest, Boolean)

System.Net.ConnectStream.PollAndRead(Boolean)

System.Net.HttpWebRequest.EndWriteHeaders(Boolean)

System.Net.HttpWebRequest.WriteHeadersCallback(System.Net.WebExceptionStatus,

System.Net.ConnectStream, Boolean)

System.Net.ConnectStream.WriteHeaders(Boolean)

System.Net.HttpWebRequest.EndSubmitRequest()

System.Net.HttpWebRequest.CheckDeferredCallDone(System.Net.ConnectStream)

System.Net.HttpWebRequest.GetResponse()

System.Web.Services.Protocols.WebClientProtocol.GetWebResponse

(System.Net.WebRequest)

System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse

(System.Net.WebRequest)

System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(System.String,

System.Object[])

Engkoo.Ehc.Core.EhcAPI.EhcDataServiceV1.GetEditModeResult(System.String,

System.String, System.String, System.String, Int32, Boolean)

Engkoo.Ehc.Core.OnlineDictionaryV2.ProcessEditRequest(DataRequest)

Engkoo.Ehc.Core.OnlineDictionaryV2.AsyncProc()

System.Threading.ThreadHelper.ThreadStart_Context(System.Object)

System.Threading.ExecutionContext.runTryCode(System.Object)

[HelperMethodFrame_PROTECTOBJ: 0da8f3f8]

System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup

(TryCode, CleanupCode, System.Object)

System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext,

System.Threading.ContextCallback, System.Object)

System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,

System.Threading.ContextCallback, System.Object)

System.Threading.ThreadHelper.ThreadStart()

该调用栈涉及26个函数,使用了一些典型的开发技术,具体如下所示。

Socket通信(System.Net.Socket)

HTTP通信(System.Net.HttpWebRequest)

SOAP通信协议(System.Web.Services.Protocols.SoapHttpClientProtocol)

该调用栈涉及26个函数,使用了一些典型的开发技术,具体如下所示。

Socket通信(System.Net.Socket)

HTTP通信(System.Net.HttpWebRequest)

SOAP通信协议(System.Web.Services.Protocols.SoapHttpClientProtocol)

异步调用(Engkoo.Ehc.Core.OnlineDictionaryV2.AsyncProc)

线程(System.Threading)

随着开发技术的发展,现在开发人员不必理解这些技术细节,只要调用程序库,就可以完成客户端(必应词典)与服务端(必应服务器)的通信。相比于底层技术,这些程序库提供了更高的抽象层次。然而,软件专家Jole Spolsky提出了经验法则“抽象漏洞定律”:“所有非平凡的抽象,在某种程度上,都存在漏洞。”[Spolsky02]他敏锐地指出,虽然高抽象层次的语言、程序库和框架等技术提高了开发者的生产力,使他们不必总是关心技术细节,然而总是存在一些情况,需要开发者深入底层,去研究那些为了提高生产率而省略的细节问题。高抽象级别的技术虽然可以减少编写代码的时间,但是并不能减少开发者学习整个技术栈的时间。只停留在高抽象层次的开发者将难以解决复杂的实际问题,且有可能引入更多的设计错误。

对于必应词典,与服务器通信是相对简单的任务,它使用了一些常见的重要技术,开发者完全理解这些技术需要付出很大的努力。然而,必应词典所涉及的技术细节远不止于此,它拥有40多个线程,加载170多个动态链接库,拥有1000多个Windows句柄。毫不夸张地说,几乎没有人可以完全理解它使用的所有技术,也无法掌握它任意时刻的状态。

不过,软件技术只是软件复杂性的一部分。成功的软件必须帮助用户解决实际问题,使他们获得成功。因此,项目团队需要研究用户情景和领域知识,然后创造性地提出解决方案,并选择合适的技术来实现。在这个研究、创造、应用的过程中,项目团队会面临更多的挑战和困难,而能否处理领域复杂度和设计复杂度是决定产品成败的关键。例如,对于必应词典而言,发送请求并接受响应是相对容易的,困难的是为一个单词提供准确的定义、例句、搭配、同义词等信息,更困难的是为一个句子提供恰当的翻译,并流畅地将它朗读出来。这些困难的任务恰恰是用户选择词典软件的重要参考。

由以上讨论不难看出,软件复杂度包含技术、领域、设计等多个方面。随着软件行业的快速发展,软件复杂度已经超越了个人的理解能力。那么,从测试的角度来说,测试人员应该如何应对这一情况呢?本书所介绍的大部分实践都是为了解决该问题的。在这里,我简单陈述一些基本态度和方法。

对于复杂的软件,任何人都不可能掌握全部的信息。如果测试人员对软件的理解存在许多偏差,他的测试策略一定会包含错误。为了更好地理解软件,他需要与产品经理、程序员、领域专家、测试同事等协作,还需要研究项目文档、技术资料、领域专著等文献,并通过实际测试去获得第一手知识。测试人员不应该依赖单一的或局限的信息源,他应该从各种渠道获得信息,多角度地研究软件。

由于软件如此复杂,大多数测试人员在项目之初都不甚了解软件,其拟定的初始测试方案或多或少都存在错漏,有些甚至存在严重错误。注重实效的测试人员,会承认测试方案是不完备的,并迭代地实施测试,通过持续地评估和反思来逐步增强测试方案。

对于现实世界的软件,穷举测试是不可行的。任何实用的测试技术都是基于一定策略的采样,即从无限多的测试输入中选择一个数量有限的子集,通过运行这批测试来评估软件的整体情况。考虑到软件的复杂度,任何一种测试技术都存在不能正确评估软件的风险。而且,在测试之初,测试人员也很难预料究竟哪些测试技术才适合当前项目。为此,测试人员应该积累多种测试技术,综合运用它们,并随着项目发展积极调整测试策略,才能避免重大测试遗漏。

人们处理复杂问题的常用策略是“分而治之”。在软件领域,建立合理的抽象模型是应对软件复杂性的常见方式。在测试领域,测试人员可以建立产品的模型来帮助测试。在建模过程中,他们以当前测试目标为指导,省略无关的产品细节,突出重要的产品元素。面对简化后的产品模型,可以更有针对性地实施测试设计。

在大规模软件中,对于少量代码的变更都不可以掉以轻心,因为修改者、代码评审者、测试者都很难预料这段代码被调用的语境和执行后的影响。例如,程序员要修改网页浏览器(如IE、Chrome、Firefox等)排版引擎的一个排版缺陷,通常需要运行大规模的回归测试。因为全世界的网页千差万别,很难预测这段代码会排版何种网页,也很难预测这段代码是否会破坏某些精心排版的页面。只有运行大规模测试,才能保证代码变更的正确性。

单凭人的脑力已经难以应对软件的复杂度了,测试人员需要考虑利用自动化测试开发强力的测试策略。1.2 软件测试是获取信息的技术调查

不同的人有不同的背景、不同的目标、不同的任务,对软件测试也会给出不同的定义,因此不存在放之四海皆准的软件测试定义。不过,对于软件测试工程师而言,我认为有3个软件测试的定义很有启发性。

定义1:测试是为了发现错误而执行程序的过程[Myers79]。

该定义是Glenford J. Myers在1979年提出的,历经30多年的考验,至今仍被广泛引用和讨论。这是一句简短而有力的论述,它紧扣测试的基本活动——执行程序和寻找错误,符合大多数测试人员的工作内容,因此更容易获得广泛认可。此外,它揭示了软件测试的根本原因,即某些重要的东西可能出错[Kaner01],软件测试就是要发现这些错误。

它给测试人员的启示是,测试人员应该始终质疑并挑战软件。有些测试任务的字面内容类似于“检查本次代码变更是正确的”,好像要求测试人员去验证软件行为是正确的。对于此类任务,测试人员应该假定代码变更引入了未知的错误,然后想尽办法去攻击软件。即便测试人员最后的结论是“我没有发现错误”,攻击性的测试过程也使这个结论更有可信度。

定义2:测试是一个获取信息的过程,用来降低决策风险[Weinberg08]。

Genald M. Weinberg认为人不是完美的思考者,面对复杂的情况会作出许多错误的决定。在采购、选择、使用、开发软件的过程中,人们需要作出许多决定。不完美的思考导致有风险的决策,可能造成巨大的损失。他指出测试可以获得更多的信息,使人们更周全地思考,从而降低错误决策的风险。

该定义给了我(一个测试人员)一系列启示。

测试是服务性的工作。通过测试,我向整个团队提供关于产品质量和项目环境的信息,帮助他们作出决定。

低质量的信息不但无助于决策,还可能浪费团队的时间,甚至作出错误的决策。因此,我应该总是提供高质量的信息。这通常体现为及时地交流、周密地测试、仔细地报告。

团队的决定可能与我的期望不一致,要去理解导致该决定的其他信息。例如,我提交了一个严重的缺陷,团队领导却决定不予修复。此时,应该提供更多的信息,据理力争,同时要去理解不予修复背后的原因,从而更好地理解软件和项目。

为了更全面地提供信息,除了运行软件,我还需要更多的获取信息的方法。常见的手段包括与程序员交谈、研究项目资料、学习领域知识、阅读源代码、在调试器中观察软件等。

除了软件缺陷,测试还可以提供关于项目环境的信息。例如,在项目过程中,产品安装总是遇到许多问题。在报告缺陷的同时,我还可以向团队领导反馈:“开发小组是否在产品安装上投入了足够多的资源?因为安装是任何测试的先决条件,安装的错误将阻碍或延缓测试,测试小组建议将它视作第一等的功能需求。”

定义3:软件测试是一种技术调查,其目的是向关系人提供有关产品(软件、系统或服务)质量的实验信息 [Kaner06]。

该定义是Cem Kaner教授提出的,他也认为测试是一种服务。服务的客户是项目关系人,服务的内容是提供产品质量的实验信息。质量就是对某个(某些)人而言的价值 [Gause89]。不同的人对于质量有不同的评判标准,对于信息有不同的需求。常见的项目关系人包括客户(购买产品的人)、用户(使用产品的人)、程序员、产品经理、运维人员、市场营销人员、管理人员等,他们对信息的需求是测试人员主要的工作内容。请看如下案例。

测试经理对测试人员说:“你刚提交了一个严重的缺陷,做得好!但是,现在临近发布,修复它的风险很高。你能不能调查一下这个缺陷在哪些情况下出现,会影响哪些用户,导致的最坏结果是什么?我们会根据这些信息来决定是否修复和修复策略。”

程序员对测试人员说:“我完成了一个补丁的开发,下周将部署到产品环境中。你能否在预发布环境中部署它,并跑一些系统测试?它只是缺陷修复,没有引入新功能,应该不会破坏当前系统的运行。”

产品经理对测试人员说:“我们在当前版本中启用了新的图形渲染引擎,能够明显提高画质,但是试用者反映这个版本的性能不如上一版。你能不能做一些实验,看看当前版本在哪些场景中比较慢,慢多少?”

运维人员对测试人员说:“一个用户在产品论坛上发帖说,软件在启动时会弹出一个报错对话框,跟帖的几个人也说遇到过相同的情况。我从没有见过该问题,所以不知如何解决。你能不能看一下这个帖子,试着在测试环境中复现?这个缺陷在下一版已经修复了吗?”

以上案例都表明,除了发现缺陷外,测试人员还通过多种方式向不同的关系人提供信息:向管理人员提供调查报告,向程序员提供代码的质量反馈,向产品经理提供技术支持,向运维人员提供已知缺陷的信息,在邮件组中回答用户提问等。为了更有效地测试,测试人员需要与测试经理讨论,设定测试服务的优先级,为关系人提供满足其要求的高质量的信息。例如,提供给测试经理的信息要面向项目风险,提供给程序员的信息要包含更多的技术细节,提供给产品经理的信息要侧重于用户体验和产品价值,提供给运维人员的信息要建议可能的解决方案。

此外,Cem Kaner还强调软件测试的主要工作是技术调查,即以职业的态度、专业的技能对产品的未知领域进行探索。与地质勘查、罪案侦查、事故调查等调查活动相似,测试具有系统性、客观性、探索性和机动性。

测试应该系统地调查被测试对象。测试人员需要对产品进行周密的分析与检查。地质勘查结束后,勘查人员会给出详细的地质图,以描绘该地区的全貌。测试结束后,测试人员也应该全面掌握被测试对象的情况。

测试所提供的信息应该来自科学实验和中立观察。在真实和客观的基础上,包含合理的推测和建议。

刑侦人员会利用多种方法,从各个信息源收集情报,因为很难预测何处会有重大发现。当突破性情报浮现时,他们会转移工作重点,顺着新线索紧追不舍。测试人员也需要综合运用多种技术和工具,去探究新的信息,并根据新发现及时调整测试方向。

优秀的潜水员既能够通过浮潜去游历宽阔的水域,也可以利用水肺潜水去探索深海水域[DeMarco08]。测试人需要交替使用广度调查和深度调查,从而更有效地提供信息。广度调查有助于发现高风险的区域,深度调查能够提供详细的信息,以支持项目关系人作出正确的决定。1.3 测试是迭代过程

测试是一个贯穿项目周期的调查过程。为了阐述技术细节,许多测试文献只讨论了该过程的一小部分。因此,它们无意中将测试描绘为一个线性过程:测试人员获得测试任务,对被测软件进行分析,制订测试计划,确定测试用例,然后……没有“然后”了,因为大多数文献只写完第一轮测试设计便结束了。

但是测试并不是一个线性过程。《计算机软件测试》[Kaner01]第1章的目录更符合测试人员的工作方式。

1. 第一个测试周期

1.1 第1步:从显而易见的简单测试开始

1.2 第2步:记录还需要测试什么

1.3 第3步:检查有效用例并观察发生了什么

1.4 第4步:做一些“快速”测试

1.5 第5步:总结对程序和问题的认识

2. 第二个测试周期

2.1 第1步:在进行任何测试之前应该仔细评审对问题报告的反馈,以确定哪些部分值得深入测试

2.2 第2步:评审对不予修复的问题的意见,它们可能建议进一步的测试

2.3 第3步:找出上次的测试笔记,加入新笔记,并开始测试

3. 后续测试周期中可能会发生的事情

该目录列举了两个测试周期中测试人员的典型活动。测试周期是一个相对于测试人员而言的概念,它包含获得可测试的新版本、测试、报告问题(即bug)、反思总结等活动。无论项目采用何种开发模型,测试人员总是一个版本接一个版本地测试,其测试活动总是迭代向前的:测试版本1→提交缺陷→修复缺陷→测试版本2→提交新缺陷→修复新缺陷→测试版本3→……

即便在测试周期内部,测试活动也是迭代的。以“第一个测试周期”为例,测试人员不熟悉软件,所以第1步是运行一些简单的测试,来了解软件的行为。在第2步和第3步,测试人员根据第1步获得的信息设计了更多的测试,并记录在案。他使用了一些经典的测试设计方法,如边界值分析和等价类划分。在第4步,他使用了一些启发式测试方法对软件进行快速攻击。在第5步,他对被测软件和测试策略进行了反思,以挖掘软件的风险和测试的不足。可见,整个测试过程是螺旋向上的:初始的测试提供了正式测试设计所需的信息;正式的测试用例较系统地检查了系统;当正式测试揭示出软件风险时,快速测试机动地探索相关领域,以确定是否存在严重的问题,并为后续的正式测试提供信息。

后续的测试周期会利用先前测试所产生的信息。以“第二个测试周期”为例,测试人员分析对问题报告的反馈,了解团队中其他人对软件行为的看法。利用这些新信息,他可以确定测试的重点。他还会参考第一个周期的测试笔记,但是不会照本宣科地重新执行一遍,而是利用新信息设计新的测试。从这个角度来看,测试类似于移动的军舰向另一艘移动的军舰开火。开火的军舰在移动是因为测试人员对被测软件的认识在不断地增强,他知道哪些测试不太容易找到错误,哪些测试更可能找到问题。目标军舰在移动是因为程序员在持续提交新功能和修复缺陷,导致软件也在不停地变化。因此,测试策略也需要保持动态变化,使得炮口一直瞄准飞驰的目标。

迭代的最大优点是能够快速获得测试设计的反馈,从而逐步完善测试设计。程序员已经认识到软件开发过程会引入大量的错误,应该利用快速反馈来发现设计中的错误。因此,测试驱动开发、结对编程、持续集成、自动化测试等技术得到了普遍认可和应用。测试设计与软件设计相似,都是高智力的创造性工作,也可能会产生错误的设计。测试人员也需要快速获得测试设计的反馈,有意识地利用迭代可以为此奠定良好的基础。1.4 测试人员的工作效率取决于他对软件和项目的理解,而不是他掌握的测试技术

我曾经长期测试一个网络应用。当我离开这个项目时,测试经理安排一个测试员工来接替我。他刚刚入职,对被测软件和业务领域都不了解,在工作中遇到了许多困难。在我加入新团队后,我还通过电话数次回答了他的问题。后来,我反思了当时的情况。作为一个测试工程师,我的工作效率明显优于接替我的同事,主要原因包括以下几点。

我理解产品。我知道它的业务目标,了解它通过什么方法去实现目标。因此,我能够快速地制定测试方案。

我理解用户的期望。我知道哪些功能绝对不能出错,需要仔细测试,也知道哪些功能允许一些瑕疵,即便出错,也可以在下一个版本(通常在3个月之后发布)中修复。因此,我能够更好地分配测试时间。

我理解产品的架构。通过阅读产品源代码,我知道哪些模块容易出现哪些缺陷。因此,我可以针对不同的模块采用有针对性的测试策略。

我知晓如何回避浪费时间却没有收益的任务。例如,我曾经尝试用自动化测试用例去测试用户界面,但是发现此类自动化测试很不稳定,需要很高的维护代价,却不能发现错误。于是,我只为Web服务编写自动化测试用例,用手工测试来测试用户界面。

我了解产品元素和项目团队。当出现缺陷时,我知道如何阅读系统日志发掘蛛丝马迹;当我遇到困难时,我知道向哪位程序员或测试人员求助。因此,我可以深入挖掘并快速推进。

我在原先的团队工作了很长的时间,与同事建立了良好的关系。当我提出一些可测试性的建议时,比较容易得到程序员的支持。

从以上几点不难看出,我能够更有效地测试,其主要原因不是我掌握更多的测试技术,而是我更了解软件产品、业务领域和项目环境。通过逐点分析,可以得到如下启示。

产品是一种解决方案,如果没有解决问题,它就是无用的[Kaner12]。测试人员需要了解软件产品和业务领域,才能设计有效的测试。

测试是一种信息服务,要了解服务对象的需求。如果用户不能容忍某些错误,测试人员就需要仔细测试相关功能;如果用户对一些瑕疵并不在意,测试人员就不必在此花费过多的时间。只有了解服务对象的优先级,才能更好地设定测试工作的优先级。

不同的模块采用不同的技术,拥有不同的典型错误。只有了解软件实现,才能设计差异化且有针对性的测试用例。

测试设计可能包含错误,测试人员需要从错误中吸取经验和教训,避免重蹈覆辙。

当测试工作遇到困难时,测试人员需要知道从哪里寻找信息。了解被测产品和测试工具能够提供的信息,了解哪位同事知道更多内幕,会节省时间。“人脉”有时候会极大地提高测试人员的工作效率。测试人员需要与程序员和测试同事保持良好的关系。达成协作关系的关键之一是测试人员能够为同事们提供高质量的信息服务。

在职业生涯中,测试人员总是会遇到新的软件、项目和团队。他应该养成一种好的思维方法和测试风格,以便快速地学习并理解产品和项目。

实施高效的测试需要很多条件。熟练地掌握测试技术是一个很重要的因素,但很少会是决定性的因素。只有充分掌握软件产品和项目环境,测试技术才能找到大放光彩的舞台。1.5 小结

本章介绍了软件测试的基本价值观。作为指导原则,它们将贯穿全书。

软件复杂性来自于领域、设计、技术、开发过程等多个方面。为了应对高度复杂且持续变动的软件,测试人员需要从多个来源收集信息,并在项目全程收集对测试设计的反馈。

软件测试的基本目标是发现软件错误,并予以修正。

软件测试是一种信息服务。以技术调查和科学实验的方式实施软件测试,能够提供高质量的服务。

无论测试人员是否意识到,软件测试都是迭代展开的。有意识地利用软件测试的迭代性,可以更好地测试。

高效的软件测试要求测试人员理解软件和项目的方方面面。学习与实践要伴随测试全程。注释

[1]. http://dict.bing.msn.cn。

[2].本章讨论的是必应词典1.7版。自2.0版开始,必应词典的主程序(BingDict.exe)不再是.NET程序,而是C/C++程序。第2章缺陷报告

在许多项目环境中,缺陷报告是测试人员最主要的工作产出,是将测试人员和项目团队广泛联系在一起的纽带。

程序员会阅读缺陷报告,以了解缺陷的症状和重现步骤。好的缺陷报告能帮助他快速地定位问题;差的缺陷报告会浪费他的调试时间。

产品经理会阅读缺陷报告,以了解缺陷的症状和严重性。好的缺陷报告准确地传递了用户质量的信息,帮助他设定修复优先级;差的缺陷报告会误导他作出错误决定,甚至将一些严重的缺陷标记为“不予修复”。

在一些团队,产品经理、开发经理和测试经理会举行缺陷评审会议,对缺陷是否修复进行“最终判决”。好的缺陷报告会提高会议效率;差的缺陷报告会降低会议效率,甚至让评审小组作出错误的决策。

在一些大型项目中,缺陷报告是测试小组以外的人了解测试人员工作的主要途径。他们会根据缺陷报告的质量评价测试人员的工作能力和职业素养。

可见,测试人员应该认真对待缺陷报告,因为它们关乎整个团队的工作效率和测试人员的个人声誉。编写高质量的缺陷报告是测试人员最重要的基本功之一。本章将介绍一些编写和处理缺陷报告的方法,帮助测试人员更有效地与项目团队交流。2.1 报告缺陷是为了让缺陷得到修复

报告缺陷的首要目标是“使正确的缺陷得到修复”[Kaner08a]。所谓“正确的缺陷”,是那些值得修复的错误、局限、失败等降低软件价值的问题。测试人员面临的挑战“对软件价值的影响”和“是否值得修复”都是主观判断,不同的人基于不同的背景和立场很可能得出不同的结论。测试人员需要说服程序员和缺陷评审小组,使他们相信修复当前的缺陷是正确的。因为测试人员通常不负责修复缺陷,为了使缺陷得到修复,需要提交和维护高质量的缺陷报告,将正确的信息传递给团队。这需要测试人员持续地努力和长期地积累。在此过程中,以下策略会有所帮助。

清楚地说明此问题对用户价值的危害。

提供尽可能多的技术信息,方便程序员调试。

尽早提交缺陷报告。

报告发现的所有缺陷,即便有些缺陷难以重现。

第一,缺陷报告要重点说明该缺陷对用户价值的损害。许多软件项目都进度紧张、资源有限,项目团队修复一个严重的缺陷,可能需要考虑多个因素。例如:修复该缺陷可能需要2天,而实现一个用户建议的新功能也需要2天,是修复缺陷还是增加功能对用户更有价值?目前,软件即将发布,修复该缺陷会不会引入新的问题?为了修复该缺陷而推迟发布是否值得?这些问题的核心因素是该缺陷是否显著地降低了软件对用户的价值,以至于开发人员与测试人员愿意占用开发活动的时间、冒着引入更多缺陷的风险来修复它。如果缺陷报告没有写清楚缺陷的影响,产品经理或缺陷评审小组有可能会错误地认为这是一个不重要的问题,并将它标记为“不予修复”。

为了让缺陷评审者了解真实的情况,测试人员需要从多个角度思考如何有效地传递缺陷信息。

测试人员在提交缺陷时最好使用自制的缺陷模板。缺陷模板为一些常用缺陷字段提供了默认值,减少了输入的工作量。更重要的是,缺陷模板可以提供缺陷报告的结构,提醒测试人员输入必要的内容。例如,缺陷模板可以包含“用户影响”一节,提醒测试人员输入缺陷对于用户价值的危害。如果缺陷对用户的影响非常明显,测试人员可以忽略该节,但这是测试人员思考后的决定,而不是由于忙碌忘记填写。

要为使用软件的人“仗义执言”。测试人员很可能是第一个完整使用软件的人,能够发现一些用户在日常使用中遇到的问题。某些问题不是严格意义上的计算错误(例如某个常用按钮没有键盘快捷键),某些问题来自于开发技术的限制(例如32位程序只能利用2GB的内存,一些需要大量内存的操作可能因为该限制而失败),某些问题在以前的版本中也存在。无论如何,这些问题使用户受到挫折,降低了软件对他们的价值。测试人员需要报告这些问题,并阐述它们给用户带来的困扰。

要“放大格局”,软件的“关系人”还包括程序员、测试人员、运维人员、销售人员等。如果软件存在一些问题或局限,使得他们的生活变得困难,测试人员也应该提交缺陷报告。例如,如果测试人员发现被测的网络服务没有记录足够的日志,以致整个业务流程类似于一个黑盒,测试检查变得很困难。他应该报告该问题,建议服务日志还需要记录哪些内容,并解释理由。测试人员可以指出,从长远看更多的日志不但能够帮助测试人员更快地发现错误,而且有利于运维人员发现在线系统的问题,也有利于程序员根据日志定位问题,从而提高整个团队的效率。

为了提供有说服力的证据,测试人员可能需要做一些“研究”。例如,测试人员发现一个杀毒软件兼容性问题——在被测软件执行特定操作时,某个杀毒软件会报告发现病毒。为了评估该问题的严重性,他需要分析该操作的重要性和使用频率,可能的手段包括阅读规格说明、查询用户日志、询问产品经理等。此外,他还可以通过搜索引擎查询该杀毒软件的市场份额,估算有多少用户可能遇到该问题。

测试人员还可以寻找“专家”支持。所谓专家是受到整个项目团队认可和信任的人,他的意见会有更大的影响力。他可能是一位资深员工,经历了多次产品发布;也可能是一位领域专家,对业务领域有深刻的理解;还可能是一位用户代表,能够提供真实的用户反馈。测试人员可以与他讨论所发现的问题,获得他的支持。如果他可以在缺陷报告中写下有份量的评论,或在缺陷评审会议上支持修复问题,该缺陷将很可能得到修复。

第二,缺陷报告应该提供尽可能多的信息,以便程序员修复缺陷。缺陷不被修复或没有被及时修复的常见原因是程序员没能重现该缺陷。对于难以重现的问题,测试人员应该收集并报告尽可能多的信息,例如有可能重现缺陷的操作步骤、屏幕截图、视频录像、所使用的数据文件、软件的内存转储、追踪日志、网络通信记录等。软件测试是技术调查,缺陷报告作为调查结果,应该包含业务层面的信息,让缺陷评审者了解软件价值的损失,还应该包含技术层面的信息,帮助程序员更快地修复问题。

第三,缺陷越早被报告,越有可能被修复。当项目临近发布时,项目团队会对代码变更采取谨慎的态度,因为最后时刻的代码修改可能会引入一些新的缺陷,而短时间的测试不能发现这些缺陷。因此,缺陷评审会议常常因为风险较高而拒绝修复一些缺陷。这样的情况我遇到过多次,如果能早一些提交该缺陷,哪怕是早一个星期,它就能得到修复。这给我两个启示:一是要第一时间提交发现的缺陷;二是在规划测试时,要使测试策略能够尽早地发现严重的缺陷。

第四,为了提供完整的信息,测试人员应该报告发现的所有问题。这并不意味着提交重复的信息。在提交缺陷报告之前,测试人员可以查询一下缺陷管理系统,了解被测功能有哪些活跃的缺陷。如果其他测试人员已经提交了这个缺陷,那么测试人员可以跳过报告,继续测试。我建议测试人员在查询相似缺陷上不必花费太多的时间,只要避

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载