精通软件性能测试与LoadRunner实战 第2版

978-7-115-52241-2
作者: 于涌王磊曹向志高楼于跃
译者:
编辑: 曹修山

图书目录:

详情

本书在介绍软件性能测试概念的基础上,结合对实际测试案例的剖析,重点讲解了性能测试实战技术、LoadRunner工具的使用技巧和实际工作中的问题解答。 全书分为15章,内容从测试项目实战需求出发,除讲述了软件测试的分类以及测试的流程等外,还重点讲述了性能测试技术和LoadRunner 11.0与12.60工具应用的实战知识。为了有效地解决工作中遇到的问题,本书基于实践中经常遇到的问题汇总了几十个解决方案。详细的项目案例、完整的性能测试方案、计划、用例设计、性能总结及相关交付文档为您做好实际项目测试提供了很好的帮助,基于LoadRunner和第三方工具对象的开发为您进行性能测试锦上添花,相信本书一定会对您进行性能测试理论学习和实践大有裨益。 本书图文并茂,通俗易懂,适合性能测试设计人员、性能测试开发人员、性能测试分析人员、项目经理和测试组长参考学习,也可作为大专院校相关专业师生的学习用书,以及培训学校的教材。

图书摘要

版权信息

书名:精通软件性能测试与LoadRunner实战(第2版)

ISBN:978-7-115-52241-2

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

编  著 于 涌 王 磊 曹向志 高 楼 于 跃

责任编辑 张 涛

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315


本书在介绍软件性能测试概念的基础上,结合对实际测试案例的剖析,重点讲解了性能测试实战技术、LoadRunner 工具的使用技巧和实际工作中的问题解答。

全书分为15 章,内容从测试项目实战需求出发,除讲述了软件测试的分类以及测试的流程等外,还重点讲述了性能测试技术和LoadRunner 11.0 与12.60 工具应用的实战知识。为了有效地解决工作中遇到的问题,本书基于实践中经常遇到的问题汇总了几十个解决方案。详细的项目案例、完整的性能测试方案、计划、用例设计、性能总结及相关交付文档为您做好实际项目测试提供了很好的帮助,基于LoadRunner 和第三方工具对象的开发为您进行性能测试锦上添花,相信本书一定会对您进行性能测试理论学习和实践大有裨益。

本书图文并茂,通俗易懂,适合性能测试设计人员、性能测试开发人员、性能测试分析人员、项目经理和测试组长参考学习,也可作为大专院校相关专业师生的学习用书,以及培训学校的教材。


随着计算机行业的蓬勃发展和用户要求不断的提高,现行的应用软件功能已经变得越来越强大,系统也越来越复杂。软件用户关注的内容不再仅仅是功能实现的正确性,系统的性能表现也同样是用户关注的重点,而性能测试是测试系统性能的主要手段,所以它是软件测试的重中之重。另外,性能测试通常和应用程序、操作系统、数据库服务器、中间件服务器、网络设备等有关,定位问题也很难,如何能够快速、有效地定位并解决性能问题,无疑是性能测试人员面临的一个重要任务。为了帮助测试人员快速掌握软件测试特点、性能测试技术及性能测试工具的实际应用,作者精心编写了本书。

作者前两本书《软件性能测试与LoadRunner实战教程》和《精通软件性能测试与LoadRunner最佳实战》上市后,受到广大软件测试和开发人员的关注与好评。目前LoadRunner最新版本为LoadRunner 12.60,而市场上应用的主流版本为LoadRunner 11. 0,故本书主要基于LoadRunner 11.0版本进行讲解,同时考虑到仍有很多读者对LoadRunner最新版本感兴趣,本书也专门用一章来详细讲述在LoadRunner 12.60版本中出现的一些新功能、新的解决方案和使用方法。很多热心的读者也针对该书提出了一些好的建议,故本书在前两本书的基础上,针对读者提出的所有问题,进行了修改、完善。但值得强调的是,本书不是《精通软件性能测试与LoadRunner实战》内容的简单增减,而是在丰富了内容并充分考虑不同层次读者需求的基础上,添加了更多的性能测试实战知识,如LoadRunner工具使用技巧,性能瓶颈分析方法,Nmon与Spotlight性能监控工具,Citrix性能测试工具EdgeSight,性能指标分析,前端性能测试,前端性能测试工具开发,Flex、Citrix、Web Services等多种协议的脚本开发,基于LoadRunner的场景控制器开发等。随着敏捷思想及实践深入地应用于软件开发过程,越来越多的软件企业更加注重接口测试、开源的性能测试工具(如JMeter)和自动化测试工具(如Selenium)的应用,来提升测试的工作质量和工作效率,这也是持续集成不可或缺的重要过程,LoadRunner 12.60版本新增了很多功能和解决方案来对这些内容进行支持。这些新增内容使得本书在结构和内容上都更加系统化、完整化,实用性更强,希望通过我们的努力,能开阔您在性能测试、接口测试、自动化测试等方面的视野,有助于您开展性能测试工作。

本书的目的是为从事软件测试、性能测试及LoadRunner工具应用的读者答疑解惑,并结合案例讲解性能测试中的实战技术。

第1章介绍了软件测试的现状以及发展前景、软件测试相关概念、软件生命周期、软件测试定义与分类、软件开发与软件测试的关系,以及软件测试流程和自动化测试的意义等内容。

第2章介绍了性能测试的基本过程,以及性能测试需求分析、性能测试计划、性能测试用例、测试脚本编写、测试场景设计、测试场景运行、场景运行监控、运行结果分析、系统性能调优、性能测试总结的内容与注意事项。

第3章介绍了典型的性能测试场景、性能测试的概念以及分类,详细介绍了工具及其样例程序的安装过程,重点介绍了工具的运行机制及组成部分,同时结合生动的生活场景深入浅出地解释了工具中的集合点、事务、检查点、思考时间等重要概念。

第4章基于一个Web样例程序,将工具的VuGen、Controller、Analysis这3者有机地结合起来,把集合点、事务、检查点、参数化等技术的应用集中在此实例得以体现,讲述了从性能测试需求提出、需求分析、脚本编写、完善、数据准备、场景设计、监控、执行到分析的完整过程。

第5章介绍了LoadRunner脚本语言、LoadRunner重要的关联问题、关联技术应用、动态链接库函数调用、特殊函数的应用注意事项、自定义函数应用和IP欺骗技术等。这部分是从事测试脚本开发的基础,建议读者认真阅读。

第6章介绍了协议的类型、协议理解误区、协议选择的方法,同时以C/S、B/S两种构架的应用作为实例,详细讲解了协议的选择和脚本的录制,讲述了参数化的方法及其应用技巧、数据分配方式和更新方法,并对脚本录制、负载(场景设计、执行)、结果分析、断点设置、单步跟踪、日志输出等调试技术进行了详细阐述,还对工具产生的相关指标的由来进行了系统的分析,并解释相关图表的用途和拐点分析方法等。

第7章结合作者工作经验、学员以及网上论坛经常提出的问题,总结了关于工具设置、使用、结果分析等问题的解决方案,旨在起到举一反三的作用,指导读者实际应用于工作当中。

第8章结合目前最新版的LoadRunner 12.60,介绍了Vugen功能改进与实用操作、同步录制和异步录制以及如何在Controller中实现对JMeter脚本的支持、应用Vugen开发Selenium脚本等实用方法。

强大的LoadRunner不仅在性能测试方面表现卓越,它也是接口测试利器。第9章详细讲解了接口测试的执行过程(包括接口测试需求、接口测试功能性用例设计、测试用例脚本实现、接口性能测试用例设计、接口性能测试脚本实现、性能测试场景执行和性能测试执行结果分析与总结)。

第10章结合主流的Windows操作系统和Linux操作系统介绍了如何监控进程、CPU、内存、磁盘I/O等性能,并结合系统提供的工具以及第三方工具,讨论如何监控测试中的相关项目,重点讲解了Nmon和Spotlight工具及其相关指标的含义等。

第11章详细地介绍了外包性能测试项目的实施完整过程与其项目性能测试的实施过程,以及“性能测试计划”“性能测试用例”“测试脚本编写”“测试场景设计”“测试场景运行”“场景运行监控”“运行结果分析”“系统性能调优”“性能测试总结”等文档内容的编写和实施过程中各环节的注意事项。

第12章以讲解完整的系统框架性能对比测试的案例为线索,全面介绍了LoadRunner在性能测试中的应用过程。具体包括模型建立、性能测试用例设计、工具的引入、脚本代码的编写、场景设计、性能结果分析等重要环节,培养读者独立进行项目测试的能力。

第13章介绍了前端性能测试的一些知识和前端性能测试分析工具HttpWatch、DynaTrace Ajax、Firebug、YSlow的使用方法和案例分析。

第14章介绍了FTP、SMTP、Sockets、RTE、Flex、Real、Web Services等协议的实际应用和注意事项,同时还介绍了EdgeSlight等其他性能测试工具的应用。

第15章介绍了如何利用高级语言进行性能测试辅助工具的开发,介绍了利用Windows计划和LoadRunner控制台命令来完成性能测试任务的思想和操作方法,并借助Delphi实现,同时还介绍了如何在高级语言中应用第三方工具提供的插件,并结合HttpWatch插件,展示了如何完成一个前端性能测试小工具。

附录部分(见配套资源)提供了一些测试模板文件,具体包括测试计划、测试总结、测试日志、功能测试用例及性能测试用例等模板、样例文档。

本书图文并茂、通俗易懂,同时在配书资源中提供了样例程序和脚本代码。希望读者在阅读本书的同时,能够边看边实践,深入理解脚本,这样可以提高学习效率,尽快将实战知识应用于项目的性能测试中。

本书遵循如下行文约定。

符号和术语

含 义

示 例

>

表示按此层次结构,主要应用于菜单项

如:选择菜单项【Edit】>【Find】

“”

表示使用者键入双引号中的文字或引用的系统界面中的术语/表达

如:在“Update value on”列表中选择一个数据更新方式

【】

代表屏幕对象名(菜单名或按钮)

如:选择菜单项【Edit】>【Find】,单击【OK】按钮

【重点提示】

知识点总结内容

(1)事务必须成对出现,即一个事务有开始,必然要求也有结束 (2)……

于涌,具有近20年软件开发和软件测试方面的工作经验,先后担任程序员、高级程序员、测试分析师、高级测试经理、测试总监等职务,拥有多年的软件开发、软件测试项目实践和教学经验,尤其擅长自动化测试、工具应用、单元测试等方面的工作,曾为多个软件公司提供软件测试知识、软件性能测试、性能测试工具LoadRunner、功能测试工具QTP、WinRunner、JMeter等内容的培训工作。

如果您在阅读过程中发现本书有什么错误,欢迎与作者联系,以便作者及时纠正。本书的勘误、更新信息、答疑信息都可以从作者的博客—测试者家园上获得。您有疑问,也可以在作者的博客中直接留言,作者也会在博客中公布本书中涉及的一些演示工具的相关下载信息。如果您在阅读本书过程中,发现错误或者疑问也可以和本书编辑联系,联系邮箱为zhangtao@ptpress.com.cn。

本书内容建立在前人研究成果的基础上。因此,在本书完成之际,我对那些为本书提供帮助的网络作者、图书作者、读者和朋友表示衷心的感谢。目前已经有很多高校使用《软件性能测试与LoadRunner实战教程》作为性能测试课程的教材,这令我非常骄傲和自豪,我衷心希望通过高校老师和我的共同努力,能增强学生的综合能力,使得理论学习和实际工作应用齐头并进,让毕业生尽快融入社会工作并成为企业的中坚力量。

在本书编写过程中,很多测试同行为本书的编写提供了很多宝贵建议;我的学员和网友提供了很多写作素材与资料,特别是我的好友高楼(7 点测试网站创建人)为本书的创作提供了宝贵的建议,并撰写了第12章系统性能测试案例,在此一并表示感谢。

于涌


本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。

本书提供如下资源:

要获得以上配套资源,请在异步社区本书页面中点击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。

如果您是教师,希望获得教学配套资源,请在社区本书页面中直接联系本书的责任编辑。

作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,点击“提交勘误”,输入勘误信息,单击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/submission即可)。

如果您是学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。

“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。

“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。

异步社区

微信服务号


本书的主要内容是关于软件性能测试相关理论和工具应用方面的知识,但考虑到有很多阅读本书的读者刚开始从事测试工作,这里用一章的内容,对软件测试的基础内容进行了概括性的介绍,如果您已经熟悉了这些基本知识,可以略过此章,直接阅读后续章节。

1.朝阳行业——软件测试

随着软件行业的蓬勃发展,市场竞争也越来越激烈,软件质量越来越受到软件企业的重视。软件测试是软件质量的重要保证,关于软件质量标准和认证,国内虽然制定了有限的软件技术标准,但无法从根本上对软件这种特殊商品实施有效的质量监督和认证。在国际上通行的做法是,软件的质量标准和认证工作由独立的软件测试机构来完成。但由于我国这方面起步较晚,以及这方面教育培养不足,因而在测试行业形成了测试人才缺口巨大的现象,许多单位备以优厚的薪金也很难找到有丰富工作经验的人才,人才的短缺严重制约了我国软件测试行业的发展,所以,软件测试人员越来越被看好,地位也越来越高,软件测试现已成为IT技术中的热门行业。

2.软件测试发展现状

随着计算机和通信技术近十年来的蓬勃发展,国家的进一步改革开放,不仅很多国内软件公司投身IT行业,如联想、用友、华为等,国外也有很多软件大公司将研发机构设在中国,如微软、IBM、西门子等知名企业。国内软件业和国外相比,最大的差异就在:对质量和质量控制方面投入不够。特别是软件的测试领域,与国外相比,国内软件产品的质量掌控体系和标准都是模糊的。因此,加强软件测试理论和实践内容的学习就显得尤其必要,它是提高软件质量水平的重要手段。现在,基于市场需求量大、理论和实践需要结合的特点,一些大学开设了此专业,同时社会上也应运而生了许多专业的测试培训机构,可以预测,在未来的几年中软件测试人才会越来越多。

3.软件测试背景

软件产品是人脑高强度智力劳动的结晶。由于软件系统的规模和复杂性日益增长,软件系统的开发人员少则几人,多则几千人,甚至上万人,所以在编写代码和沟通协作过程中难免会出现这样或者那样的问题,出现的问题将直接导致软件中存在缺陷。以下是两例软件缺陷和故障的分析,借此来说明由于这些缺陷和故障而引起的严重损失。

案例一:美国迪士尼公司的狮子王游戏软件的兼容性问题。

1994年,美国迪士尼公司发布面向少年儿童的多媒体游戏软件——“狮子王动画故事书”。经过迪士尼公司的大力促销,该游戏软件销售情况异常火暴,几乎成为当年秋季全美青少年儿童必买的游戏。但产品销售后不久,该公司客户支持部门的电话就一直不断,儿童家长和玩不成游戏的孩子们大量投诉该游戏软件,后来经过调查核实,发现造成这一严重后果的原因是,迪士尼公司没有对该游戏软件在已投入市场上适用的各种PC上进行正确的测试,也就是说游戏软件对硬件环境的兼容性没有得到保证。软件故障使迪士尼公司的声誉受到影响,公司为改正软件缺陷和故障付出了很大的代价。

案例二:售票系统性能问题。

某奥运会第二阶段门票开始预售,公众的奥运热情很高,承担此次售票的票务网站一小时浏览量达800万次、每秒提交的门票申请达20万张;呼叫中心一小时呼入200万人次……由于访问量过大,票务销售系统数据处理能力相对有所不足,造成各售票渠道出现售票速度慢、不能登录系统的情况。虽然访问者不停地刷新订票系统的页面,但上面总是显示“系统故障,无法处理你的请求”。由于庞大的订票人数超出预期,奥运票务系统“开工”后不久便出现问题。

从上面的例子中大家不难发现,正是由于软件中存在着或多或少的问题,直接导致了各方的损失,同时,从另外一方面也反映了充分、有效地对软件实施测试的重要意义。

大家从上面的软件故障或缺陷的实例中不难发现,这些软件故障和缺陷拥有很多的共同特点。首先,软件的开发过程与预期设计目标不一致。其次,闭门造车,没有实际考察客户的真正应用环境,仅仅按照自己的想法实施,尽管进行了测试,但是并没有覆盖到大多数用户应用软件的所有场景,如《狮子王》游戏软件就是因为研发出来的软件没有考虑用户的实际应用环境而引发的问题;而奥运售票系统的重大的事故也反映出没有考虑到实际用户的访问量。

那么什么是软件?什么是缺陷呢?什么是软件生命周期?在学习软件测试之前,大家应对这些概念有一个清晰的认识。

1.软件的概念

简单地说,软件就是程序与文档的集合。程序指实现某种功能的指令集合,如目前广泛被应用于各行各业的Java程序、Delphi程序、Visual Basic程序、C#程序等。文档是指在软件从无到有这个完整的生命周期中产生的各类图文的集合。具体可以包括《用户需求规格说明书》《需求分析》《系统概要设计》《系统详细设计》《数据库设计》《用户操作手册》等相关文字及图片内容。

2.软件缺陷的概念

软件缺陷是指计算机的硬件、软件系统(如操作系统)或应用软件(如办公软件、进销存系统、财务系统等)出现的错误,大家经常会把这些错误叫作“Bug”。“Bug”在英语中是臭虫的意思。在以前的大型机器中,经常出现有些臭虫破坏了系统的硬件结构,导致硬件运行出现问题,甚至崩溃。后来,Bug这个名词就沿用下来,引伸为错误的意思,什么地方出了问题,就说什么地方出了Bug,也就用Bug来表示计算机系统或程序中隐藏的错误、缺陷或问题。

硬件的出错有两个原因,一种原因是设计错误,另一种原因是硬件部件老化失效等。软件的错误基本上是由于软件开发企业设计错误而引发的。设计完善的软件不会因用户可能的误操作产生Bug,如本来是做加法运算,但错按了乘法键,这样用户会得到一个不正确的结果,这个误操作产生错误的结果,但不是Bug。

3.软件生命周期的概念

软件生命周期是从软件需求的定义、产生直到被废弃的生命周期,生命周期内包括软件的需求定义、可行性分析、软件概要设计、软件详细设计、编码实现、调试和测试、软件验收与应用、维护升级到废弃的各个阶段,这种按时间分为各个阶段的方法是软件工程中的一种思想,即按部就班、逐步推进,每个阶段都要有定义、工作、审查、形成文档以供交流或备查,从而提高软件的质量。

随着计算机行业的不断发展,软件系统规模和复杂性不断扩大,先前由一两个人就可以完成的中小型项目已经不再适用于现在软件项目的开发模式和系统的规模。现行软件项目通常业务功能复杂,操作人数较多,软件厂商在激烈的市场竞争中不仅需要考虑产品的功能实用性、界面的美观性、易用性等,产品的健壮性,以及快速及时的响应、支持多用户的并发请求等性能测试方面的要求也越来越受到关注,软件的性能测试可以说是软件测试的重中之重。它是测试人员从用户角度出发对软件系统功能、性能等方面进行测试的行为,是一种非常重要的软件质量保证的手段。

软件测试就是在软件投入正式运行前期,对软件需求文档、设计文档、代码实现的最终产品以及用户操作手册等方面审查过程。软件测试通常主要描述了两项内容。

描述1:软件测试是为了发现软件中的错误而执行程序的过程。

描述2:软件测试是根据软件开发各个阶段的规格说明和程序的内部结构而精心设计的多组测试用例(即输入数据及其预期的输出结果),并利用这些测试用例运行程序以发现错误的过程,即执行测试步骤。

这里又提到了两个概念:测试和测试用例。

测试包含硬件测试和软件测试,在这里如没有特殊说明,测试仅指软件测试。它是为了找出软件中的缺陷而执行多组软件测试用例的活动。

软件测试用例是针对需求规格说明书中相关功能描述和系统实现而设计的,用于测试输入、执行条件和预期输出,测试用例是执行软件测试的最小实体。

关于软件测试还有一个概念,就是测试环境。测试环境包括很多内容,具体如下。

(1)硬件环境(PC、笔记本电脑、服务器、小型机、大型机等)。

(2)软件环境(操作系统,如Windows 2000、Windows 9x、Windows XP、Windows NT、UNIX、Linux等;Web应用服务器,如Tomcat、Weblogic、IIS、WebSphere等;数据库,如Oracle、SQL Server、MySQL、DB2等;还有一些其他的软件,如办公软件,杀毒软件等)。软件环境的配置还需要考虑软件的具体版本和补丁的安装情况。

(3)网络环境(如局域网、城域网或因特网,局域网是10Mbit/s、100Mbit/s的,还是其他类型的)。

有时在进行软件测试的时候,同一个应用系统,因为测试环境的不同将直接导致软件运行结果的不同(如界面不同、运行结果不同等),为了保证不再出现类似《狮子王》游戏软件兼容性测试方面的问题发生,在进行测试环境搭建的时候,需要注意以下几点。

(1)尽量模拟用户的真实场景。

就是测试环境尽量模拟用户应用的网络应用、软件、硬件使用环境,全面仿真用户的真实场景测试,与用户的各项配置均一致。有些情况下,完全模拟用户的场景是有困难的,这时可以通过与客户沟通,在特定的时间段(如节假日、下班以后等时间)应用客户的环境来达到测试的目的。

(2)干净的环境。

有时为了考查一款软件是否可以在新安装的操作系统下正常运行,就需要在干净的机器上考查这个软件相关的动态链接库(DLL文件),相应组件是否能够正常注册、复制到相应路径下;有些情况下由于程序的运行需要第三方组件或者动态链接库的支持,然而,在打包的时候忘记把这些内容打进去,而导致在干净的系统中会出现问题。在干净的系统下测试还可以有效避免由于安装了其他软件,产生冲突,影响问题定位方面的事情发生。

(3)没有病毒的影响。

有时,测试人员会发现系统在本机上出现文件无法写入、网络不通、驱动错误、IE浏览器和其他软件的设置频繁被改变等一系列莫名其妙的问题,而这些问题在别的计算机上没有,遇到这些问题,一般情况下可能是您的计算机感染上了病毒,需要杀毒以后再进行测试。在有病毒的计算机上进行测试是没有意义的事情,因为不知道这是系统的问题还是病毒原因而产生的问题。

(4)独立的测试环境。

做过测试的读者可能经常都会被研发和测试共用一套测试环境而困扰,因为测试和研发的数据互相影响。例如,一个进销存软件,测试人员做了进货处理,进了10口电饭锅,进货单价为100元/口,接下来进入库存统计时发现库存金额为800元,原来是因为开发人员销售了两口电饭锅,致使库存统计的结果数据不对。在共用一套环境情况下,研发、测试相互影响的事情比比皆是,不利于缺陷的定位,也不利于项目或者产品任务的进度控制。

软件测试按照测试阶段、是否运行程序、是否查看源代码以及其他方式,可以用图1-1所示来描述软件测试的各种分类。

图1-1 测试的各种分类结构图

1.黑盒测试

黑盒测试(Black-box Testing)是软件测试的主要方法之一,也可以称为功能测试、数据驱动测试或基于规格说明的测试。测试者不了解程序的内部情况,只知道程序的输入、输出和系统的功能,这是从用户的角度对程序进行的测试。软件的黑盒测试意味着测试要在软件的接口处进行。这种方法是把测试对象看做一个黑盒子,测试人员完全不考虑程序内部的逻辑结构和内部特性,只依据程序的需求规格说明书,检查程序的功能是否符合它的功能说明。

黑盒测试的随机性比较大,在大部分案例执行完成以后,大概能够测试40%的功能。据美国一个官方的数据说,20%的问题是在开发过程中发现的;80%的问题是在系统测试和集成测试过程中发现的,其中80%的比例我们还是需要再细分,20%的是使用的问题,20%是程序的问题,5%逻辑问题,剩下的都是莫名其妙的问题。这样的数据对测试的一个引导是:要想发现更多的问题,需要更多的思考,更多的组合。这样增加了很多工作量,人们在疲惫地执行着测试用例,渴望从中发现新的问题。

这样的用例设计思想使得我们在开发一个大型的产品或者延续性产品的时候,整个测试用例的延续性很差,重用性也很差。所以我们在这里需要纠正一个概念,黑盒测试不是简单地使用,用例设计也不是无谓地组合。

那么如何设计好的测试用例呢?如何在开发过程中很好地结合2/8原则呢?不可能出现一个完美无瑕的产品,但是作为软件工程师和软件测试工程师,肯定希望自己参与开发的产品稳定、易用并且能够受到用户的好评;希望自己参与的产品能够满足当前大多数人的需求,是否更合理呢?我相信通过软件工程师、测试工程师以及质量保证人员等的不断努力,我们的软件产品会让用户感到满意的。

2.白盒测试

白盒测试(White-box Testing)是另一种软件测试的主要方法,又称为结构测试、逻辑驱动测试或基于程序本身的测试,它着重于程序的内部结构及算法,通常不关心功能与性能指标。软件的白盒测试是对软件的过程性细节做细致的检查。这种方法是把测试对象看做一个打开的盒子,它允许白盒测试人员利用程序内部的逻辑结构及有关信息,设计或选择测试用例,对程序所有逻辑路径进行测试。通过在不同点检查程序状态,确定实际状态是否与预期的状态一致。

白盒测试是一种基于对源代码中的控制结构、处理过程等进行分析,检查程序内部处理是否正确、包括异常处理、语句结构、分支、循环结构等。很多控制软件,还要考虑有无冗余的代码,因为程序运行时,可能进入这些代码而无法再进行正常的执行(如进入了死循环状态,程序永远无法终止)。这种测试要求测试人员对程序的理解能力和编码能力很高,需要了解程序的构架、具体需求,以及一些编写程序的技巧,能够检查一些程序规范,以及指针、变量、数组越界等问题,使得问题在前期就暴露出来。

白盒测试一般是以单元或者模块为基础的。目前的做法是把它归结为开发的范畴。通常由资深的程序员、专职的白盒测试人员或利用专业的代码分析工具,如Boundchecker、Jtest、C++ Test等工具,这些工具可以帮助开发人员发现变量没有初始化、空指针、内存泄露以及代码不规范等问题。

白盒测试的主要方法包括以下几种。

3.灰盒测试

灰盒测试(Gray-box Testing)是基于程序运行时刻的外部表现同时又结合程序内部逻辑结构来设计用例,执行程序并采集程序路径执行信息和外部用户接口结果的测试技术。这种测试技术介于白盒测试与黑盒测试之间,可以这样理解,灰盒测试关注输出对于输入的正确性,同时也关注内部表现。但这种关注不像白盒那样详细、完整,只是通过一些表征性的现象、事件、标志来判断内部的运行状态,有时候输出是正确的,但内部其实已经错误了,这种情况非常多,如果每次都通过白盒测试来操作,效率会很低,因此需要采取这样的一种灰盒的方法。

灰盒测试结合了白盒测试和黑盒测试的要素。它考虑了用户端、特定的系统知识和操作环境。灰盒测试由方法和工具组成,这些方法和工具取材于应用程序的内部知识和与之交互的环境,能够用于黑盒测试以增强测试效率、错误发现和错误分析的效率。灰盒测试涉及输入和输出,但使用关于代码和程序操作等通常在测试人员视野之外的信息设计测试。

静态测试和动态测试的概念在很多书中被提到,在这里也给大家介绍一下这两个概念。

1.静态测试

所谓静态测试(Static Testing),是指不运行被测试的软件,而只是静态地检查程序代码、界面或者文档中可能存在的错误的过程。

从概念中,大家不难发现静态测试主要包括三个方面内容的测试工作,即程序代码、界面和文档。

(1)程序代码测试:主要是程序员通过代码检查、代码评审等方式,对程序中是否存在编码不规范、代码编写是否和业务实现不一致,以及代码中是否有内存泄露、空指针等问题的测试。

(2)界面测试:主要是指测试人员从用户角度出发,根据公司的UI(User Interface,用户界面)设计规范检查被测试软件的界面是否符合用户的要求,在这里,非常赞同在开发软件产品之前,提供一个界面原型给用户参考,听取用户意见,而后不断完善原型,最后依照通过的原型实现软件的做法。

(3)文档测试:主要是测试人员对需求规格说明书、用户手册是否符合用户要求的检查过程。

为了能够说明静态测试是如果进行的,我们现在仅以对程序代码测试为例,给大家介绍一下。

首先,请大家看一段由C语言实现的小程序,代码如下所示。

void msg(char *explanation)
{
  char p1;

  p1 = malloc(100);
  .(void) sprintf(p1,"The error occurred because of '%s'.",explanation);
}

不知道您看到问题了吗?如果您对C语言有一定了解的话,应该清楚内存申请完成以后,在完成任务后,必须要把申请的内存回收,否则就会造成内存的泄露发生。从上面的代码我们不难发现,每次应用msg()函数都会泄露100字节的内存。在内存充裕的情况下,一两次泄露是微不足道的,但是连续操作数小时后,特别是在多用户并发的情况下,持续运行一段时间之后,则即使如此小的泄露也会削弱应用程序的处理能力,最后的结果必将是内存资源耗尽!

在实际的C、C++编程中,您在代码中对内存malloc()(分配)以后,在完成任务以后一定要记得把那部分申请的内存通过free()给释放掉,当然您还需要注意应用文件操作的时候,也要把文件给关闭,建立一个连接以后也要把连接给关掉等问题。上面提及的情况,如果没有及时关闭申请的资源同样是会出现内存泄露情况的。

除了上面说到的代码方面的问题以外,文档中缺少注释信息也是一个问题。大家知道一个软件在编写过程中,通常都是多个人相互协作,每个人编写一部分功能模块,每个人可能都非常清楚自己编写模块的内容,但是有时候难免会碰到您去修改别人代码的时候(如某个研发人员离职了,您需要维护他编写的那部分代码),这时如果没有注释信息,您可能理解几十万、上百万行的代码是极其困难的,但是在有注释的情况下,您就能很快了解作者的意图,方便后期代码的维护。

2.动态测试

与静态测试相对应的就是动态测试。所谓动态测试(Dynamic Testing),是指实际运行被测试的软件,输入相应的测试数据,检查实际输出结果是否和预期结果相一致的过程。从静态测试和动态测试的概念我们不难发现,静态测试和动态测试的唯一区别就是是否运行程序。

为了能够说明动态测试是如何进行的,我们现在也举一个具体的实例,给大家介绍一下。以Windows自带的计算器程序为例,如我们输入“5+50=”,在设计用例的时候,预期结果应该为“55”,如果结果不等于“55”则说明程序是错误的,请参见图1-2。

图1-2 计算器程序

1.单元测试

单元测试是测试过程中的最小粒度,它在执行的过程中紧密地依照程序框架对产品的函数和模块进行测试,包含入口和出口的参数,输入和输出信息,错误处理信息,部分边界数值测试。

这个部分的测试工作,目前,在国内大多数情况下是由开发人员进行的。我相信未来的发展应该是测试工程师来做这个事情。这和目前国内软件测试刚刚起步的阶段是有密切关系的,随着软件行业的蓬勃发展,越来越多的软件企业已经意识到白盒测试的重要程度,特别是在军工、航天以及一些对人身、财产安全影响重大的项目中,白盒测试的重要意义不言而喻。当然,这样意义重大的事情,对白盒测试人员的综合能力也提出了更高的要求,从业人员必须对需求、系统框架、代码以及测试技术等方面都要有深刻的理解,这样才能发现问题。

还有一种大家坐在一起讨论评审的方法,就是当一个模块给某个开发工程师以后,需要他给大家讲解,他要完成这个模块或者函数的整体流程和思路,进行统一评审,使得问题能够暴露得更充分些,这样做的目的有以下几个原因。第一,使得大家对设计者思路明晰的理解,以便以后调用或者配合的时候能够真切地提出需求或者相对完美配合。第二,在评审的过程中,如果发现问题,那么大家可能没有遇见过,这样就会更加提高警惕,如果遇见过,就会回想当时自己怎么解决的或者规避的,使得大家能够避免错误的发生,减少解决问题的周期。第三,可以对平常所犯错误进行一个积累,这是生动的教科书,可以使得新的人员在上手的时候就借鉴前人的一些经验,遇到这样的问题以后,可以给他们一个解决问题的方法或者方向。

上面给大家介绍了两种方法,第一种就是通过在开发的过程中进行测试,由开发(白盒测试)工程师写测试代码,对所编写的函数或者模块进行测试;第二种就是通过代码互评发现问题,将问题进行积累,形成知识积累库,以便使得其他开发人员在遇到同样问题时不至于再犯错误。

单元测试非常重要,因为它影响的范围和宽度比较大,也许由于一个函数或者参数问题,造成后面暴露出很多表象问题出现。而且如果单元测试做不好,使得集成测试或者后面系统测试的压力很大,这样项目的费用和进度可能就会受到影响。

对单元测试,有很多工具可以应用,现在主流是Xunit系列(即针对Java的单元测试主要用Junit,.Net则有Nunit,Delphi有Dunit等工具),当然,除了Xunit系列的单元测试工具,也有其他的工具,如Cppunit、Comunit、ParaSoft的Jtest等。测试人员应该在单元测试工作中不断积累工作经验,不断加强、改进工作方法,增强单元测试力度。

保证单元测试顺利进行,需要渗透软件工程的很多思想,把CMM(能力成熟度模型)和跟踪机制建立起来,把问题进行分类与跟踪,如果把软件环节整个活动都渗透了,那么产品质量的意识自然就增强了。

单元测试做什么呢?

单元测试主要任务包括:

① 模块接口测试;

② 模块局部数据结构测试;

③ 模块中所有独立执行路径测试;

④ 模块的各条错误处理路径测试;

⑤ 模块边界条件测试。

(1)模块接口测试。

模块接口测试是单元测试的基础,主要检查数据能否正确地通过模块。只有在数据能正确流入、流出模块的前提下,其他测试才有意义。

测试接口正确与否应该考虑下列因素:

① 输入的实际参数与形式参数的个数是否相同;

② 输入的实际参数与形式参数的属性是否匹配;

③ 输入的实际参数与形式参数的量纲是否一致;

④ 调用其他模块时所给实际参数的个数是否与被调模块的形参个数相同;

⑤ 调用其他模块时所给实际参数的属性是否与被调模块的形参属性匹配;

⑥ 调用其他模块时所给实际参数的量纲是否与被调模块的形参量纲一致;

⑦ 调用预定义函数时所用参数的个数、属性和次序是否正确;

⑧ 是否存在与当前入口点无关的参数引用;

⑨ 是否修改了只读型参数;

⑩ 对全程变量的定义各模块是否一致;

⑪ 是否把某些约束作为参数传递。

如果模块内包括外部输入输出,还应该考虑下列因素:

① 文件属性是否正确;

② 打开或关闭语句是否正确;

③ 格式说明与输入输出语句是否匹配;

④ 缓冲区大小与记录长度是否匹配;

⑤ 文件使用前是否已经打开;

⑥ 是否处理了文件尾;

⑦ 是否处理了输入/输出错误;

⑧ 输出信息中是否有文字性错误。

(2)局部数据结构测试。

检查局部数据结构是为了保证临时存储在模块内的数据在程序执行过程中完整、正确。局部数据结构往往是错误的根源,应仔细设计测试用例,力求发现下面几类错误:

① 不合适或不相容的类型说明;

② 变量无初值;

③ 变量初始化或默认值有错;

④ 不正确的变量名(拼错或不正确地截断);

⑤ 出现上溢、下溢和地址异常;

⑥ 除了局部数据结构外,如果可能,单元测试时还应该查清全局数据(如Fortran的公用区)对模块的影响。

(3)独立执行路径测试。

在模块中应对每一条独立执行路径进行测试,单元测试的基本任务是保证模块中每条语句至少执行一次。此时设计测试用例是为了发现因错误计算、不正确的比较和不适当的控制流造成的错误,其中基本路径测试和循环测试是最常用且最有效的测试技术,常见的错误包括:

① 误解或用错算符优先级;

② 混合类型运算;

③ 变量初值错;

④ 精度不够;

⑤ 表达式符号错。

比较判断与控制流常常紧密相关,测试用例还应致力于发现下列错误:

① 不同数据类型的对象之间进行比较;

② 错误地使用逻辑运算符或优先级;

③ 因计算机表示的局限性,期望理论上相等而实际上不相等的两个量相等;

④ 比较运算或变量出错;

⑤ 循环终止条件或不可能出现;

⑥ 错误地修改了循环变量。

(4)错误处理路径测试。

一个好的设计应能预见各种出错情况,并对这些出错的情况预设各种出错处理路径,出错处理路径同样需要认真测试,在测试时应着重检查下列问题:

① 输出的出错信息难以理解;

② 记录的错误与实际遇到的错误不相符;

③ 在程序自定义的出错处理段运行之前,系统已介入进行处理;

④ 异常处理不当,导致数据不一致等情况发生;

⑤ 错误陈述中未能提供足够的定位出错信息。

(5)边界条件测试。

边界条件测试是单元测试中重要的一项任务。众所周知,软件经常在边界上失效,采用边界值分析技术,针对边界值及其边界值的左、右设计测试用例,很有可能发现新的错误。

(6)单元测试方法。

一般认为单元测试应紧接在编码之后,当源程序编制完成并通过复审和编译检查,便可开始单元测试。测试用例的设计应与复审工作相结合,根据设计信息选取测试数据,将增大发现上述各类错误的可能性。在确定测试用例的同时,应给出期望结果。

由于被测试的模块往往不是独立的程序,它处于整个软件结构的某一层上,被其他模块调用或调用其他模块,其本身不能单独运行,因此在单元测试时,应为测试模块开发一个驱动(Driver)模块和(或)若干个桩(Stub)模块,图1-3显示了一般单元测试的环境。

图1-3 单元测试环境

驱动模块的作用是用来模拟被测模块的上级调用模块,功能要比真正的上级模块简单得多,它接收测试数据并将这些数据传递到被测试模块,被测试模块被调用后,可以打印“进入-退出”消息。桩模块用来代替被测模块所调用的模块,用以返回被测模块所需的信息。

驱动模块和桩模块是测试使用的软件,而不是软件产品的组成部分,其编写需要一定的开发费用。若驱动和桩模块比较简单,实际开发成本相对低些。遗憾的是,仅用简单的驱动模块和桩模块不能完成某些模块的测试任务,这些模块的单元测试只能采用后面讨论的集成测试方法。

2.集成测试

时常有这样的情况发生,每个模块都能单独工作,但这些模块集成在一起之后却不能正常工作,其主要原因是模块相互调用时接口会引入许多新问题。例如,数据经过接口可能丢失;一个模块对另一模块可能造成不应有的影响;几个子功能组合起来不能实现主功能;误差不断积累,最后,则达到不可接受的程度;全局数据结构出现错误等。集成测试是组装软件的系统测试技术,按设计要求把通过单元测试的各个模块组装在一起之后,进行综合测试以便发现与接口有关的各种错误。

集成测试包括两种不同方法:非增量式集成和增量式集成。研发人员习惯于把所有模块按设计要求一次全部组装起来,然后进行整体测试,这称为非增量式集成。这种方法容易出现混乱,因为测试时可能发现一大堆错误,为每个错误定位和纠正非常困难,并且在改正一个错误的同时又可能引入新的错误,新旧错误混杂,更难断定出错的原因和位置。与之相反的是增量式集成方法,程序一段一段地扩展,测试的范围一步一步地加强,错误易于定位和纠正,界面的测试也可做到完全彻底。

(1)增量式集成方法的两种类型。

增量式集成方法主要包括自顶向下集成和自底向上集成两种类型。

自顶向下增量式测试表示逐步集成和逐步测试是按结构图自上而下进行的。即模块集成的顺序是首先集成主控模块(主程序),然后按照软件控制层次结构向下进行集成。

自底向上增量式测试是从最底层的模块开始,按结构图自下而上逐步进行集成和测试。

集成测试主要测试软件的结构问题,因为测试建立在模块的接口上,所以多为黑盒测试,适当辅以白盒测试。

执行集成测试应遵循下面的方法:

① 确认组成一个完整系统的模块之间的关系;

② 评审模块之间的交互和通信需求,确认出模块间的接口;

③ 使用上述信息产生一套测试用例;

④ 采用增量式测试,依次将模块加入到系统,并测试新合并后的系统,这个过程以一个逻辑/功能顺序重复进行,直至所有模块/功能集成进来形成完整的系统为止。

此外,在测试过程中尤其要注意关键模块,所谓关键模块一般都具有下述一个或多个特征:

① 对应几条需求;

② 具有高层控制功能;

③ 复杂,易出错;

④ 有特殊的性能要求。

因为集成测试的主要目的是验证组成软件系统的各模块的接口和交互作用,因此集成测试对数据的要求无论从难度和内容来说一般不是很高。集成测试一般也不使用真实数据,测试人员可以使用手工制作一部分代表性的测试数据。在创建测试数据时,应保证数据充分测试软件系统的边界条件。

在单元测试时,根据需要生成了一些测试数据,在集成测试时可适当地重用这些数据,这样可节省时间和人力。

(2)集成测试遵循的原则。

集成测试很不好把握,应针对总体设计尽早开始筹划。为了做好集成测试,需要遵循以下原则:

① 所有公共接口都要被测试到;

② 关键模块必须进行充分的测试;

③ 集成测试应当按一定的层次进行;

④ 集成测试的策略选择应当综合考虑质量、成本和进度之间的关系;

⑤ 集成测试应当尽早开始,并以总体设计为基础;

⑥ 在模块与接口的划分上,测试人员应当和开发人员进行充分的沟通;

⑦ 当接口发生修改时,涉及的相关接口必须进行再测试;

⑧ 测试执行结果应当如实记录。

3.系统测试

集成测试通过以后,软件已经组装成一个完整的软件包,这时就要进行系统测试。系统测试完全采用黑盒测试技术,因为这时已不需要考虑组件模块的实现细节,而主要是根据需求分析时确定的标准检验软件是否满足功能、性能等方面的要求。系统测试所用的数据必须尽可能地像真实数据一样准确和有代表性,也必须和真实数据的大小和复杂性相当。满足上述测试数据需求的一个方法是使用真实数据。在不使用真实数据的情况下应该考虑使用真实数据的一个复制。复制数据的质量、精度和数据量必须尽可能地代表真实的数据。当使用真实数据或使用真实数据的复制时,仍然有必要引入一些手工数据。在创建手工数据时,测试人员必须采用正规的设计技术,使得提供的数据真正代表正规和异常的测试数据,确保软件系统能充分地测试。

系统测试需要有广泛的知识面,对测试工程师的要求需要了解和掌握很多方面的知识,需要了解问题可能出现的原因,以及出现这个问题可能是由于什么原因造成的,以便我们能够及时地补充测试用例,保证或者降低产品发行后的风险。

系统测试阶段是测试发现问题的主要阶段,系统测试重复的工作量比较大。如果是一个大型的项目,涉及的内容相对比较多。测试本身是一件重复性的工作,很多时候我们要部署同样的测试环境,测试同样的模块功能,反反复复地输入相同的测试数据,这是十分枯燥和乏味的工作。很容易让人厌烦,所以如果能够将部分有规律的重复性工作使用自动化测试工具来进行,会使得我们的工作量减少,提高工作效率。

4.验收测试

系统测试完成之后,软件已完全组装起来,接口方面的错误也已排除,这时可以开始对软件进行最后的确认测试。确认测试主要检查软件能否按合同要求进行工作,即是否满足软件需求规格说明书中的要求。

软件确认要通过一系列黑盒测试。确认测试同样需要制订测试计划和过程,测试计划应规定测试的种类和测试进度,测试过程则定义一些特殊的测试用例,旨在说明软件与需求是否一致。无论是计划还是过程,都应该着重考虑软件是否满足合同规定的所有功能和性能,文档资料是否完整、准确,人机界面和其他方面(例如,可移植性、兼容性、错误恢复能力和可维护性等)是否满足客户要求。

确认测试的结果有两种可能:一种是功能和性能指标满足软件需求说明的要求,用户可以接受;另一种是软件不满足软件需求说明的要求,用户无法接受。项目进行到这个阶段才发现严重错误和偏差一般很难在预定的工期内改正,因此必须与用户协商,寻求一个妥善解决问题的方法。

事实上,软件开发人员不可能完全预见用户实际使用程序的情况。例如,用户可能错误地理解命令,或提供一些奇怪的数据组合,也可能对系统给出的提示信息迷惑不解等。因此,软件是否真正满足最终用户的要求,应由用户进行一系列“验收测试”。验收测试既可以是非正式的测试,也可以有计划有系统的测试。有时,验收测试长达数周甚至数月,不断暴露错误,导致开发延期。一个软件产品可能拥有众多用户,不可能由每个用户验收,此时多采用称为α、β 测试的过程,以期发现那些似乎只有最终用户才能发现的问题。

α测试是指软件开发公司组织内部人员模拟各类用户行为对即将面市软件产品(称为α版本)进行测试,试图发现错误并修正。α测试的关键在于尽可能地模拟实际运行环境和用户对软件产品的操作,并尽最大努力涵盖所有可能的用户操作方式。经过α测试调整的软件产品称为β 版本。紧随其后的β测试是指软件开发公司组织各方面的典型用户(如放到互联网上供用户免费下载,并可以试用一定期限,或者以光盘等形式免费发放给部分期待试用的未来潜在客户群用户,也可以使用一定的期限,这个期限通常可能是几天也可能是几个月)在日常工作中实际使用β版本,并要求用户报告异常情况、提出改进意见,然后软件开发公司再对β版本进行改错和完善。

1.回归测试

无论是进行黑盒测试还是白盒测试都会涉及回归测试,那么什么是回归测试呢?回归测试是指对软件新的版本测试时,重复执行上一个版本测试时使用的测试用例。

在软件生命周期中的任何一个阶段,只要软件发生了改变,就可能给该软件带来问题。软件的改变可能是源于发现了错误并做了修改,也有可能是因为在集成或维护阶段加入了新的模块。当软件中所含错误被发现时,如果错误跟踪与管理系统不够完善,就可能会遗漏对这些错误的修改;而开发者对错误理解得不够透彻,也可能导致所做的修改只修正了错误的外在表现,而没有修复错误本身,从而造成修改失败;修改还有可能产生副作用从而导致软件未被修改的部分产生新的问题,使本来工作正常的功能产生错误。同样,在有新代码加入软件的时候,除了新加入的代码中有可能含有错误外,新代码还有可能对原有的代码带来影响。因此,每当软件发生变化时,我们就必须重新测试现有的功能,以便确定修改是否达到了预期的目的,检查修改是否损害了原有的正常功能。同时,还需要补充新的测试用例来测试新的或被修改了的功能。为了验证修改的正确性及其影响就需要进行回归测试。

回归测试在软件生命周期中扮演着重要的角色,因忽视回归测试而造成严重后果的例子不计其数,导致阿里亚娜V形火箭发射失败的软件缺陷就是由于复用的代码没有经过充分的回归测试造成的。我们平时也经常会听到一些客户的抱怨,说:“以前应用没有问题的功能,现在怎么有问题了?”这些通常是因为鉴于商机、实施等部门对软件开发周期的限制因素,开发人员对软件系统增加或者改动部分系统功能,由于时间紧迫的原因,明确与测试部门说明只进行新增或者变更的模块进行测试,而对其他未修改的模块不需要进行测试或者干脆说不需要测试,由于软件系统各个模块之间存在着或多或少的联系,很有可能因为新增加的功能变化,而引起其他模块不能进行正常的工作,所以只测试新增模块,不对系统进行完整功能的测试,导致以前应用没有问题的功能,现在出现了问题。

2.冒烟测试

冒烟测试的名称可以理解为该种测试耗时短,仅用一袋烟功夫足够了。也有人认为是形象地类比新电路板基本功能检查。任何新电路板焊好后,先通电检查,如果存在设计缺陷,电路板可能会短路,板子冒烟了。

冒烟测试的对象是每一个新编译的需要正式测试的软件版本,目的是确认软件基本功能正常,可以进行后续的正式测试工作。冒烟测试的执行者是版本编译人员或其他研发人员。

在一般软件公司,软件在编写过程中,内部需要编译多个版本,但是只有有限的几个版本需要执行正式测试(根据项目开发计划),这些需要执行的中间测试版本,在刚刚编译出来后,软件编译人员需要进行常规的测试,例如,是否可以正确安装/卸载,主要功能是否实现了,数据是否严重丢失等。如果通过了该测试,则可以根据正式测试文档进行正式测试,否则,就需要重新编译版本,再次执行版本构建、打包和测试,直到成功为止。冒烟测试的好处是可以节省大量的时间成本和人力、物力成本,避免由于打包失误、功能严重缺失、硬件部件损坏导致软件运行失败等严重问题而引起大量测试人员从事没有意义的测试劳动。

3.随机测试

随机测试是这样一种测试,在测试中,测试数据是随机产生的。例如,我们测试一个系统的姓名字段,姓名长度可达12个字符,那么可能随机输入以下12个字符:“ay5%,,i567aj”,显然,没有人叫这样一个名字,并且可能该字段不允许出现%等一些字符,所以对随机产生的输入集合我们要进行提炼,省略掉一些不符合要求的测试集。并且这样随机产生的用例可能还只覆盖了一部分等价类,大量的情况无法覆盖到。这样的测试有时又叫猴子测试(Monkey Testing)。

随机测试有这样一些缺点:

(1)测试往往不太真实;

(2)不能达到一定的覆盖率;

(3)许多测试都是冗余的;

(4)需要使用同样的随机数种子才能重建测试。

这种随机测试在很多时候没有多大的用处,往往被用来作为“防崩溃”的手段,或者被用来验证系统在遭受不利影响时是否能保持正常。作者觉得随机测试在面向网络,特别是因特网、不确定群体时还是非常有用的,因为不仅仅是真正想使用系统的用户,也有很多乐于攻击系统和制造垃圾数据的人,这是考察一个系统健壮性、防止生成大量垃圾数据的情况时非常有用的,有很多系统就因为前期不注重控制垃圾数据的输入,导致数据量急速增长,后来又不得不做一个数据校验程序来限制或删除垃圾数据,无形中又增加了工作量。

前面已经提到软件生命周期,大家已经清楚软件从无到有是需要需求人员、研发人员、测试人员、实施维护等人员相互协作的。作为软件测试人员,在从事软件测试工作的同时,最好对软件的研发过程有一个整体的了解。随着信息技术和各行各业的蓬勃发展,现在的软件系统通常都比较复杂,一个新的软件产品研发过程少则需要几个人,多则需要几百人、数千人来协同完成,下面我们就来看一看软件的开发模式。

从开始构思到正式发布软件产品的过程称为软件开发模式。一个软件系统的顺利完成是和选择正确的、适宜的软件开发方法,严格地按照整个开发进程开发密不可分的。

由于软件开发需求和规模各不相同,因此,在实际工作中也有针对性地运用了多种开发模式,下面给大家介绍一下。

1.直接编写法

在早期的软件开发过程中,通常由于软件的规模比较小,有些开发人员不遵从软件工程的思想,直接编写代码,而不经过前期的概要设计、详细设计等过程,通常会有两种结果。第一种结果是开发出来的软件非常优秀(开发人员思路非常清晰,代码编写能力非常强);第二种结果是软件产品开发失败(毕竟在开发过程中,能够很好掌控整体构架,并能够很好实现细节的开发人员还是很少)。

直接编写法的优点显而易见就是思路简单,对开发人员的要求很高,要求开发人员必须思路清晰,因为多数时候功能模块的实现是依赖于开发人员的“突发奇想”,由于不需要编写相应的需求、设计等文档,软件开发过程有可能会缩短。其缺点也非常明显,就是这种方法没有任何计划、进度安排和规范的开发过程,软件项目组成员的主要精力花费在程序开发的设计和代码编写上,它的开发过程是非工程化的。这种方法的软件测试通常是在开发任务完成后进行,也就是说已经形成了软件产品之后才进行测试。测试工作有的较容易,有的则非常复杂,这是因为软件及其说明书在最初就已完成,待形成产品后,已经无法回头修改存在的问题,所以软件测试的工作只是向客户报告软件产品经过测试后发现的情况。

通过上面的介绍,大家不难发现这种开发软件方法存在着很大的风险,但是,现行软件产品通常都是功能繁多、业务处理复杂的产品,这些软件产品开发工作应当避免采用直接编写法作为软件开发的方法。

2.边写边改法

软件的边写边改开发模式是软件项目小组在没有刻意采用其他开发模式时常用的一种开发模式。它是对直接编写法的一种改进,参考了软件产品的要求。这种方法通常只是在开发人员有了比较粗略的想法就开始进行简单设计,然后进行较长的反复编写、测试与修复这样一个循环的过程,在认为无法更精细地描述软件产品要求时就发布产品。因为从开始就没有计划和文档的编制,项目组织能够较为迅速地展示成果。因此,边写边改模式极其适合用在快速制作的小项目上,如示范程序与演示程序比较适合采用该方法。

处于边写边改开发项目组的软件测试人员要明确的是,测试人员和开发人员有可能长期陷入循环往复的开发过程中。通常,新的软件(程序)版本在不断地产生,而旧的版本的测试工作可能还未完成,新版本软件(程序)还可能又包含了新的或已修改的功能。

在进行软件测试工作期间,边写边改开发模式最有可能遇到。虽然它有缺点,但它是通向采用合理软件开发的路子,有助于理解更正规的软件开发方法。

3.瀑布法

1970年,WinSTon Royce提出了著名的“瀑布模型”,直到20世纪80年代早期,它一直是被广泛采用的软件开发模型。瀑布模式是将软件生命周期的各项活动规定为按照顺序相连的若干个阶段性工作,形如瀑布流水,最终得到软件产品,如图1-4所示。瀑布模式本质上是一种线性顺序模型,因此存在着较明显的缺点,各阶段之间存在着严格的顺序性和依赖性,特别强调预先定义需求的重要性,在着手进行具体的开发工作之前,必须通过需求分析预先定义并“冻结”软件需求,然后再一步一步地实现这些需求。但是实际项目很少遵循着这种线性顺序进行的。虽然瀑布模式也允许迭代,但这种改变往往对项目开发带来混乱。在系统建立之前很难只依靠分析就确定出一套完整、准确、一致、有效的用户需求,这种预先定义需求的方法更不能适应用户需求不断变化的情况。

图1-4 瀑布开发模式

(1)瀑布开发模式优点。

① 各个阶段之间具有顺序性和依赖性。

② 推迟程序的物理实现。

③ 每个阶段必须完成规定的文档;每个阶段结束前完成文档审查,对修正错误起到一定作用。

④ 易于组织,易于管理。

⑤ 是一种严格线性的、按阶段顺序的、逐步细化的过程模型(开发模式)。

(2)瀑布开发模式缺点。

① 在项目开始的时候,用户常常难以清楚地给出所有需求。

② 用户与开发人员对需求理解存在差异。

③ 顺序的开发流程使得开发中的经验教训不能反馈到该项目的开发中去,实际的项目很少按照顺序模式进行。

④ 因为瀑布模式确定了需求分析的绝对重要性,但是在实践中要想获得完善的需求说明是非常困难的,导致出现“阻塞状态”情况发生。

⑤ 开发中出现的问题直到开发后期才能够显露,因此失去及早纠正的机会。

⑥ 不能反映出软件开发过程的反复与迭代性。

(3)瀑布开发模式适用场合。

① 对于有稳定的产品定义和易被理解的技术解决方案时,使用瀑布模式非常适合。

② 对于有明确定义的版本进行维护或将一个产品移植到一个新的平台上,使用瀑布模式也比较适合。

③ 对于那些易理解但很复杂的项目,应用瀑布模式同样比较合适,因为这样的项目可以用顺序方法处理问题。

④ 对于那些质量需求高于成本需求和进度需求的项目,使用瀑布模式处理效果也很理想。

⑤ 对于那种研发队伍的技术力量比较薄弱或者新人较多缺乏实战经验的团队,采用瀑布模式也非常合适。

4.快速原型法

根据客户需求在较短的时间内解决用户最迫切解决的问题,完成可演示的产品。这个产品只实现最重要功能,在得到用户的更加明确的需求之后,原型将丢弃。快速原型模型的第一步是建造一个快速原型,实现客户或未来的用户与系统的交互,用户或客户对原型进行评价,进一步细化待开发软件的需求。通过逐步调整原型使其满足客户的要求,开发人员可以确定客户的真正需求是什么;第二步则在第一步的基础上开发客户满意的软件产品。显然,快速原型方法可以克服瀑布模式的缺点,减少由于软件需求不明确带来的开发风险,具有显著的效果。快速原型实施的关键在于尽可能快速地建造出软件原型,一旦确定了客户的真正需求,所建造的原型将被丢弃。因此,原型系统的内部结构并不重要,重要的是必须迅速建立原型,随之迅速修改原型,以反映客户的需求,如图1-5所示。

图1-5 快速原型开发模式

5.螺旋模式法

1988年,Barry Boehm正式发表了软件系统开发的“螺旋模式”,他将瀑布模式和快速原型结合起来,强调了其他模型所忽视的风险分析,特别适合于大型复杂的系统。

螺旋模型沿着螺线进行若干次迭代,图1-6中的4个象限代表了以下活动。

(1)规划:确定软件目标,选定实施方案,弄清项目开发的限制条件。

(2)风险分析:分析评估所选方案,考虑如何识别和消除风险。

(3)原型开发:实施软件开发和验证。

(4)用户评审:评价开发工作,提出修正建议,制订下一步计划。

图1-6 螺旋模式法

螺旋模式有风险分析,强调可选方案和约束条件,从而支持软件的重用,有助于将软件质量作为特殊目标融入产品开发之中。螺旋模式的第一个阶段是确定该阶段的目标——制订计划,完成这些目标的选择方案及其约束条件,然后从风险角度分析方案的开发策略,努力排除各种潜在的风险,有时需要通过建造原型来完成。如果某些风险不能排除,该方案立即终止,否则启动下一个开发步骤。最后,评价该阶段的结果,并设计下一个阶段。螺旋模式是瀑布模式与边写边改演化模式相结合,并加入风险评估所建立的软件开发模式。主要思想是在开始时不必详细定义所有细节,而是从小开始,定义重要功能,尽量实现,接受客户反馈,进入下一阶段,并重复上述过程,直到获得最终产品。但是,螺旋模式也有一定的限制条件,具体如下。

(1)螺旋模式强调风险分析,但要求许多客户接受和相信这种分析,并做出相关反应是不容易的,因此,这种模式往往适应于内部的大规模软件开发。

(2)如果执行风险分析将大大影响项目的利润,那么进行风险分析毫无意义,因此,螺旋模式只适合于大规模软件项目。

(3)软件开发人员应该擅长寻找可能的风险,准确地分析风险,否则,将会带来更大的风险。

测试应该从生命周期的第一个阶段开始,并且贯穿于整个软件开发的生命周期。生命周期测试是对解决方案的持续测试,即使在软件开发计划完成后或者被测试的系统处于执行状态的时候,都不能中断测试。在开发过程的几个时期,测试团队所进行的测试是为了尽早发现系统中存在的缺陷。软件的开发有其自己的生命周期,在整个软件生命周期中,软件都有各自的相对于各生命周期的阶段性的输出结果,其中也包括需求分析、概要设计、详细设计及程序编码等各阶段所产生的文档,包括需求规格说明、概要设计规格说明、详细设计规格说明以及源程序等,而所有这些输出结果都应成为被测试的对象。测试过程包括了软件开发生命周期的每个阶段。在需求阶段,重点要确认需求定义是否符合用户的需要;在设计和编程阶段,重点要确定设计和编程是否符合需求定义;在测试和安装阶段,重点是审查系统执行是否符合系统规格说明;在维护阶段,要重新测试系统,以确定更改的部分和没有更改的部分是否都正常工作,如图1-7所示。

图1-7 测试与开发各阶段的关系

基于“V”模型,如图1-8所示。在开发周期中的每个阶段都有相关的测试阶段相对应,测试可以在需求分析阶段就及早开始,创建测试的准则。每个阶段都存在质量控制点,对每个阶段的任务、输入和输出都有明确的规定,以便对整个测试过程进行质量控制和配置管理。通常在测试中,使用验证来检查中间可交付的结果,使用确认来评估可执行代码的性能。一般来说,验证回答这样的问题:“是否建立了正确的系统?”,而确认回答的问题是:“建立的系统是否正确”。

图1-8 软件测试“V”模型

所谓验证,是指如何决定软件开发的每个阶段、每个步骤的产品是否正确无误,并与其前面的开发阶段和开发步骤的产品相一致。验证工作意味着在软件开发过程中开展一系列活动,旨在确保软件能够正确无误地实现软件的需求。

所谓确认,是指如何决定最后的软件产品是否正确无误。

随着信息技术的飞速发展,软件产业在国民经济中扮演着越来越重要的角色,各行各业对软件质量要求也越来越高,那么软件企业是不是为了保证产品的质量,测试人员就需要无限期地对软件产品测试下去呢?回答是否定的,从经济学的角度考虑就是确定需要完成多少测试,以及进行什么类型的测试。经济学所做的判断,确定了软件存在的缺陷是否可以接受,是否符合企业产品定义的质量标准。“太少的测试是犯罪,而太多的测试是浪费。”对风险测试得过少,会造成软件的缺陷和系统的瘫痪;而对风险测试得过多,就会使本来没有缺陷的系统进行没有必要的测试,或者是对轻微缺陷的系统所花费的测试费用远远大于它们给系统造成的损失。测试费用的有效性,可以用测试费用的质量曲线来表示,如图1-9所示。随着测试费用的增加,发现的缺陷也会越多,两线相交的地方是过多测试开始的地方,这时,发现缺陷的测试费用超过了缺陷给系统造成的损失费用。

图1-9 测试费用的质量曲线

由于市场和软件研发成本的影响,软件测试不可能无限期地测试下去,软件测试最佳的发布日期通常是在测试多轮以后,在较长的时期发现不了缺陷或者发现很少的缺陷(如2周、3周,甚至1、2个月也发现不了缺陷),但是该阶段耗费的研发成本日益增长的时候终止。

软件测试工作通常要通过制订测试计划、测试设计、执行测试、测试总结几个阶段来完成。

测试计划就是描述所有要完成的测试工作,包括被测试项目的背景、目标、范围、方式、资源、进度安排、测试组织,以及与测试有关的风险等方面。

1.制订测试计划的目的

一个计划一定是为了某种目的而产生的,对于软件质量管理而言,制订测试计划的目的主要有以下几点。

(1)使软件测试工作各个阶段目标更明确,测试工作可以有条不紊顺利进行。

(2)促进项目组成员相互沟通,及时解决由于沟通不畅而引起的问题。

(3)预测在测试过程中可能出现风险并制订合理规避风险措施。

(4)使软件测试工作更易于管理。

2.制订测试计划的原则

制订测试计划是测试中最有挑战性的一个工作,以下原则将有助于制订测试计划工作。

(1)制订测试计划应尽早开始。

(2)保持测试计划的灵活性。

(3)保持测试计划简洁和易读。

(4)尽量争取多渠道测试计划评审工作。

(5)计算测试计划的投入成本。

3.面对的问题

制订测试计划时,测试人员可能面对以下问题,必须认真对待,并妥善予以处理。

(1)与开发者意见不一致,尽量达成一致,必要时企业高层需要介入。

(2)缺乏测试工具,在应用熟练的情况下,大型的项目测试工具的应用会在一定程度上减少测试周期,特别是在性能测试方面,测试工具的应用是非常必要的,大用户量的并发操作,人工模拟困难巨大。

(3)培训/沟通不够,培训工作很重要,有助于测试人员了解需求,了解系统实现的细节等。

(4)管理部门缺乏对测试工作的理解和支持,这是非常困难的事情,如果没有管理部门的支持与理解,我们的测试工作就会阻力重重,处理方法还是要测试部门相关领导要多和管理部门相关领导沟通、交流,阐述测试的重要性,当然,测试人员也要通过自己的不懈努力来证明经过测试的产品和没有测试的产品的具体差别,让管理部门人员真正意识到测试的重要性。

(5)缺乏用户的参与,测试的目的是为了要满足客户的需求。如果有客户的参与,我们可以更加明确客户的操作环境、操作方式等,这些对于我们后期能够合理地设计测试用例都是大有裨益的。

(6)测试时间不足、工期短、资源少是测试部门经常要面临的问题。这也需要和项目组合理确定测试时间,阐述测试时间和产品质量之间的关系以及测试的重点等内容,尽量多争取较长的、合理的测试时间。

4.建议

制订测试计划时,由于各软件公司的背景不同,测试计划文档也略有差异。实践表明,制订测试计划时,使用正规化文档通常比较好,本书的相关配套资源中提供了相关模板请大家借鉴参考。

测试设计阶段要设计测试用例和测试数据,要保证测试用例完全覆盖测试需求。简单地说,测试用例就是设计一个情况,软件程序在这种情况下,必须能够正常运行并且达到程序所设计的执行结果。如果程序在这种情况下不能正常运行,而且这种问题会重现出来,那就表示已经测出软件有缺陷,这时候就必须将这个问题标示出来,并且输入到问题跟踪系统内,通知软件开发人员。软件开发人员接到通知后,将问题修改完成后,在下一个测试版本提交后,测试工程师取得新的测试版本,用同一个测试用例来测试这个问题,确保该问题被修复。在测试时,不可能进行穷举测试,为了节省时间和资源,提高测试效率,必须要从庞大的测试用例中精心挑选出具有代表性的测试数据来进行测试。使用测试用例的好处主要体现在以下几个方面。

(1)在开始实施测试之前设计好测试用例,可以避免盲目测试并提高测试效率。

(2)测试用例使软件测试的实施重点更加突出、目的更加明确。

(3)在软件版本更新后,只需修正少量的测试用例便可开展测试工作,降低工作强度,缩短项目周期。

(4)功能模块的通用化和复用化使软件易于开发,而测试用例的通用化和复用化则会使软件测试易于开展,并随着测试用例的不断精化,其效率也不断提高。

测试用例主要有如下几种。

(1)功能测试用例(包含功能测试、健壮性测试、可靠性测试)。

(2)安全测试用例。

(3)用户界面测试用例。

(4)安装/反安装测试用例。

(5)集成测试用例(包含接口测试)。

(6)性能测试用例(包含性能测试、负载测试、压力测试、容量测试、并发测试、配置测试、可靠性测试、失败测试)。

1.6.2.1 测试用例设计

测试设计阶段最重要的是如何将测试需求分解,如何设计测试用例。

1.如何对测试需求进行分解

对测试需求进行分解需要反复检查并理解各种信息,主要是和需求分析人员进行交流,必要的情况下也可以和用户交流,理解用户的真正需求是什么。

可以按照以下步骤执行。

(1)确定软件提供的主要功能、性能测试项详细内容。

(2)对每个功能进行分解,确定完成该功能所要进行的操作内容。

(3)确定数据的输入和预期的输出结果。

(4)确定会产生性能和压力测试的重要指标,包括硬件资源的利用率,业务的响应时间,并发用户数等重要内容。

(5)确定应用需要处理的数据量,根据业务情况预期未来2、3年内的数据扩展。

(6)确定需要的软件和硬件配置。

……

2.如何设计测试用例

测试用例一般指对一项特定的软件产品进行测试任务的描述,体现测试方案、方法、技术和策略,需要指出的是,测试数据都是从庞大的可用测试数据中精心挑选出具有代表性的用例。测试用例是软件测试系统化、工程化的产物,而测试用例的设计一直是软件测试工作的重点和难点。

设计测试用例也就是设计针对特定功能或功能组合的测试方案,并编写成文档。测试用例应该体现软件工程的思想和原则。

传统的测试用例文档编写有两种方式。

(1)一种是填写操作步骤列表:将在软件上进行的操作步骤一步一步详细记录下来,包括所有被操作的项目和相应的值。

(2)另一种是填写测试矩阵:将被操作项作为矩阵中的一个字段,而矩阵中的一条条记录则是这些字段的值。

评价测试用例的好坏有以下两个标准。

(1)是否可以发现尚未发现的软件缺陷。

(2)是否可以覆盖全部的测试需求。

1.6.2.2 测试用例设计的方法

软件测试设计的重要工作内容就是用例的设计,那么用例设计有哪些方法呢?接下来,就给大家介绍一下用例设计一些常用的方法。

1.等价类划分方法

等价类划分是一种典型的黑盒测试方法。使用这一方法时,完全不考虑程序的内部结构,只依据程序的规格说明来设计测试用例。由于不可能用所有可以输入的数据来测试程序,而只能从全部可供输入的数据中选择一个进行测试。如何选择适当的子集,使其尽可能多地发现错误,解决的办法之一就是等价类划分。

首先,把数目极多的输入数据,包括有效的和无效的,划分为若干等价类,而所谓等价类,是指某个输入域的子集合。在该子集合中,各个输入数据对于揭露程序中的错误都是等效的。并合理地假定:测试某等价类的代表值就等价于对这一类其他值的测试。因此,可以把全部输入数据合理划分为若干等价类,在每一个等价类中取一个数据作为测试的输入条件,就可用少量代表性测试数据,取得较好的测试结果。

等价类的划分有以下两种不同的情况。

(1)有效等价类:是指符合《用户需求规格说明书》的数据规范,合理地输入数据集合。

(2)无效等价类:是指符合《用户需求规格说明书》的数据规范,无效地输入数据集合。

划分等价类的原则如下。

(1)按区间划分。

(2)按数值划分。

(3)按数值集合划分。

(4)按限制条件或规则划分。

在确立了等价类之后,建立等价类表,列出所有划分出的等价类,如表1-1所示。

表1-1 等价类划分列表

输 入 条 件

有效等价类

无效等价类

……

……

……

再从划分出的等价类中按以下原则选择测试用例。

(1)为每一个等价类规定一个唯一的编号。

(2)设计一个新的测试用例,使其尽可能多地覆盖尚未覆盖的有效等价类。重复这一步骤,直到所有的有效等价类都被覆盖为止。

(3)设计一个新的测试用例,使其仅覆盖一个无效等价类,重复这一步骤,直到所有的无效等价类都被覆盖为止。

这里给大家举一个小例子,记得上小学一年级的时候,主要学习两门功课:语文和数学,两门功课单科满分成绩均为100分。期末考试的时候,老师会计算每个学生的总分,即总分=语文分数+数学分数。为了方便老师计算个人总成绩,编写如下C语言代码:

int sumscore(int maths,int chinese)
{
  int sumdata;
  if (((maths>100) || (maths<0)) || ((chinese>100) || (chinese<0))) 
  {
    printf("单科成绩不能小于0或者大于100!");
    return -1;
  }
  sumdata=maths+chinese;
  printf("%d",sumdata);
  return sumdata;
}

我们现在根据“单科成绩只能在0~100的两个数字相加”的需求来设计测试用例,大家可以知道如果想把0~100的所有情况都测试到(仅包含正整数和零),我们需要101×101=10201个用例,显然这种穷举测试的情况是不可行的方法,因此我们尝试用等价类划分的方法来设计用例。

根据单科成绩输入的限制条件,可以将输入区域划分成3个等价类,如图1-10所示。

从图1-10中可以看到,我们将输入区域分成了一个有效等价类(成绩在0~100)和两个无效等价类(成绩<0)和(成绩>100)。下面可以从每一个等价类中选择一组具有代表性的数据来进行函数正确性的测试,详细数据请参见表1-2。

图1-10 单科成绩等价类

表1-2 等价类划分测试数据列表

用例编号

等价类分类

语文

数学

总 成 绩

1

有效等价类

60

90

150

2

无效等价类

-1

70

提示:单科成绩不能小于0或者大于100!

3

无效等价类

101

120

提示:单科成绩不能小于0或者大于100!

细心的朋友们可能会发现一个问题,就是我们刚才等价类的划分并不是很完善,我们只针对整型数据进行用例的设计,如果我们输入的是空格、小数、字母等数据怎么办?所以,测试用例的设计应该尽可能用少量的数据覆盖尽可能多的情况,上面用例的设计我们更多地从输入数据的范围进行了考虑,没有考虑如果参数的类型输入不正确的情况。下面我们将先前没有考虑进去的字母、空格等特殊字符也加入到测试数据列表中,形成比较完善的等价类划分测试数据列表,详细数据请参见表1-3。

表1-3 完善后的等价类划分测试数据列表

用例编号

等价类分类

语文

数学

总 成 绩

1

有效等价类

60

90

150

2

无效等价类

-1

70

提示:单科成绩不能小于0或者大于100!

3

无效等价类

101

120

提示:单科成绩不能小于0或者大于100!

4

无效等价类

91.2

88.2

提示:单科成绩不能小于0或者大于100!

5

无效等价类

A

B

提示:单科成绩不能小于0或者大于100!

……

……

……

……

……

2.边界值分析法

人们从长期的测试工作经验得知,大量的错误是发生在输入或输出范围的边界上,而不是在输入范围的内部。因此针对各种边界情况设计测试用例,可以查出更多的错误。使用边界值分析方法设计测试用例,首先应确定边界情况。

选择测试用例的原则如下。

(1)如果输入条件规定了值的范围,则应该取刚达到这个范围的边界值,以及刚刚超过这个范围边界的值作为测试输入数据。

(2)如果输入条件规定了值的个数,则用最大个数、最小个数、比最大个数多1个、比最小个数少1个的数作为测试数据。

(3)如果程序的规格说明给出的输入域或输出域是有序集合(如有序表、顺序文件等),则应选取集合的第一个和最后一个元素作为测试用例。

(4)如果程序用了一个内部结构,应该选取这个内部数据结构的边界值作为测试用例。

(5)分析规格说明,找出其他可能的边界条件。

3.因果图表法

因果图方法最终生成的就是判定表。它适合于检查程序输入条件的各种组合情况。利用因果图生成测试用例的基本步骤如下。

(1)分析软件需求规格说明描述中哪些是原因,哪些是结果。原因是输入条件或输入条件的等价类,结果是输出条件。

(2)分析软件需求规格说明描述中的语义,找出原因与结果之间、原因与原因之间对应的关系,根据这些关系,画出因果图。

(3)标明约束条件。由于语法或环境的限制,有些原因和结果的组合情况是不可能出现的。为表明这些特定的情况,在因果图上使用若干标准的符号标明约束条件。

(4)把因果图转换成判定表。

(5)为判定表中的每一列设计测试用例。

下面我们列出一些因果关系图常用的表示符号,如图1-11所示。

图1-11 因果图的基本符号

为了使大家对因果关系图方法有一个清晰的了解,这里给大家举一个例子:在一个应用系统中,系统要求能够分类导入进货和销售的数据,对文件的命名有如下要求,文件名第一个字符必须为A(进货)或B(销售),第二个字符必须为数字。满足则导入进货、销售接口文件信息到系统中。第一个字符不正确发出信息X12(“非进货或销售数据!”),第二个字符不正确发出信息X13(“单据信息不正确!”)。

(1)分析规范(如表1-4所示)。

表1-4 文件命名问题分析规范列表

原  因

结  果

条件1:第一个字符为A

结果1:30—导入接口文件数据

条件2:第一个字符为B

结果2:31—发信息X12

条件3:第二个字符为数字

结果3:32—发信息X13

(2)画出因果图(如图1-12所示)。

图1-12 文件命名问题因果图

中间结点是导出结果的进一步原因,考虑到原因1、2不可能同时为1,加上E约束。

(3)将因果图转换为判断表(如表1-5所示)。

从表1-5中可能发现组合情况1、2测试用例是空的,这是为什么呢?这是因为前面已经提到了原因,1、2不可能同时为1,所以条件1和条件2同时为1是没有意义的(即第一个字符既为A又为B这种情况)。

表1-5 文件命名问题判定表

组合情况 1 2 3 4 5 6 7 8
条件原因 1 1 1 1 0 0 0 0
1 1 0 0 1 1 0 0
1 0 1 0 1 0 1 0
1 1 1 1 0 0
动作结果 0 0 0 0 1 1
1 0 1 0 0 0
0 1 0 1 0 1
测试用例 A3 A8 AM A? B5 B4 BN B! C2X 6 DY PI

4.判定表方法

判定表是分析和表达多逻辑条件下执行不同操作的情况的一种方法。判定表的优点是能够将复杂的问题按照各种可能的情况全部列举出来,简明并避免遗漏。因此,利用判定表能够设计出完整的测试用例集合。在一些数据处理问题当中,某些操作的实施依赖于多个逻辑条件的组合,即针对不同逻辑条件的组合值,分别执行不同的操作。判定表很适合于处理这类问题。

判定表通常由4个部分组成,如图1-13所示。

图1-13 判定表的4个组成部分

下面分别描述一下各个组成部分。

这里给大家举一个例子,某个货运公司邮递货物的收费标准如下:如果收件地点在本省,则快件每千克5元,慢件每千克3元;如果收件地点在外省,则在20千克以内(包括20千克)快件每千克7元,慢件每千克5元,而超过20千克时,快件每千克9元,慢件每千克7元。

根据对上面问题的分析以后,我们可以得到条件取值分析表,如表1-6和表1-7所示。

(1)规则及规则合并。

规则:任何一个条件组合的特定取值及其相应要执行的操作称为规则。在判定表中贯穿条件项和动作项的一列就是一条规则。显然,判定表中列出多少组条件取值,也就有多少条规则,即条件项和动作项有多少列。

表1-6 条件取值分析表

条 件 取 值 含 义
收件地址在本省吗 Y 是(本省)
N 否(外省)
邮件重量≤20kg吗 Y 是(小于等于20kg)
N 否(大于20kg)
快件吗 Y 是(快件)
N 否(慢件)

化简:就是规则合并有两条或多条规则具有相同的动作,并且其条件项之间存在着极为相似的关系。

两规则动作项一样,条件项类似,在1、2条件项分别取Y、N时,无论条件3取何值,都执行同一操作。即要执行的动作与条件3无关,于是可合并,这里我们用“-”表示与取值无关,如表1-8所示。

表1-7 判定表

表1-8 化简规则表

Y Y Y
N N N
Y N
X X X

判定表的建立步骤如下(根据软件规格说明)。

① 分析判定问题涉及几个条件。

② 分析每个条件有几个取值区间。

③ 画出条件取值分析表,分析条件的各种可能组合。

④ 分析决策问题涉及几个判定方案。

⑤ 画出有条件组合的判定表。

⑥ 决定各种条件组合的决策方案,即填写判定规则。

⑦ 合并化简判定表,即相同决策方案所对应的各个条件组合是否存在无须判定的条件。

(2)判定表的优点和缺点。

优点:它能把复杂的问题按各种可能的情况一一列举出来,简明而易于理解,也可避免遗漏,如表1-9所示。

表1-9 化简后的判定表

1 2 3 4 5 6
条 件 收件地址在本省 Y Y N N N N 状态
邮件重量≤20kg Y Y N N
快慢件 Y N Y N Y N
决策方案 3元/kg X 决策规则
5元/kg X X
7元/kg X X
9元/kg X

缺点:不能表达重复执行的动作,例如,循环结构。

B. Beizer指出了适合使用判定表设计测试用例的条件:

B. Beizer提出这5个必要条件的目的是为了使操作的执行完全依赖于条件的组合。其实对于某些不满足这几条的判定表,同样可以借以设计测试用例,只不过尚需增加其他的测试用例罢了。

5.错误推测法

有时候,为了发现一些问题,需要个人开发、测试以及其他方面的经验积累才能够发现缺陷。有很多朋友可能发现,一般用人单位都希望同等价位招聘一名有测试工作经验的人,而不愿意招聘一名应届毕业生。原因不仅仅是工作过的同志了解测试工作的流程,作为招聘单位可能考虑更多的是,已工作的朋友在测试方面积累了丰富的经验,将会为公司的软件测试缺陷的定位提供良好的条件。有经验的人靠直觉和经验来推测程序中可能存在的各种错误,从而有针对性地编写检查这些错误的例子,这就是错误推测法。错误推测法的基本想法是:列举出程序中所有可能有的错误和容易发生错误的特殊情况,根据它们选择测试用例。

作者曾经在对一个人事信息管理性能测试的时候,发现内存泄露明显,在使用LoadRunner做性能测试的时候,50个虚拟用户并发的情况下,应用系统会出现内存被耗尽,最后宕机的情况发生。依照以前的开发经验,作者认为有以下几种原因都会导致内存泄露情况的发生:

(1)代码编写时,申请了内存,使用完成以后,没有释放申请的内存;

(2)变量使用完成后,没有清空这些变量的内容,也将会导致内存泄露;

(3)建立数据库连接、网络连接、文件操作等使用完成后,没有断开使用的连接。

上面几种情况都将会出现内存泄露。作者把内存泄露现象以及出现内存泄露的原因信息提供给了开发人员,研发人员通过对代码的审查,很快就发现在显示人员的照片时,申请了内存,使用完成后,没有释放,就是这个原因直接导致宕机情况的发生。

综上所述,对于测试工作来讲,软件开发、软件测试、操作系统、应用服务器、数据库以及网络等方面的经验,都会对您发现系统中的缺陷、定位问题产生的原因、解决问题提供一种思路。

6.场景法

现在的软件几乎都是用事件触发来控制流程的,事件触发时的情景便形成了场景,而同一事件不同的触发顺序和处理结果就形成事件流。这种在软件设计方面的思想也可以引入软件测试中,可以比较生动地描绘出事件触发时的情景,有利于测试设计者设计测试用例,同时使测试用例更容易理解和执行。用例场景用来描述流经用例的路径,从用例开始到结束遍历这条路径上所有基本流和备选流。

如图1-14所示,图中经过用例的每条路径都用基本流和备选流来表示,直线表示基本流,是经过用例的最简单的路径。备选流用曲线表示,一个备选流可能从基本流开始,在某个特定条件下执行,然后重新加入基本流中(如备选流1和3);也可能起源于另一个备选流(如备选流2),或者终止用例而不再重新加入到某个流(如备选流2和4)。

图1-14 基本流和备选流

为了使大家对场景设计方法能够有一个较深入的了解,这里给大家举一个银行ATM机提款操作的例子。下面是银行ATM机操作业务的流程示意图,如图1-15所示。

图1-15 ATM机相关操作流程示意图

根据上面的流程示意图,我们以银行的客户提款为例结合用例设计的方法,设计出如下场景,如表1-10所示。

表1-10 ATM机器提款场景法用例

场  景

PIN

账号

输入 金额

账面 金额

ATM内 的余额

预期结果

场景1:成功提款

T

T

T

T

T

成功提款

场景2:ATM机器内没有现金

T

T

T

T

F

提款选项不可用,结束用例

场景3:ATM机器内现金不足

T

T

T

T

F

警告提示,返回基本流步骤6,重新输入金额

场景4:PIN有错误

F

T

N/A

T

T

警告提示,返回基本流步骤4,重新输入金额

……

…….

……

……

……

……

……

注:T 代表 True(真),F代表 False(假),N/A代表Not Applicable(不适合)。

用例的设计不仅仅是简单地把要做的事情描述出来,通常还需要把每一个场景的测试数据也设计出来,这样再进入测试执行阶段就可以按部就班,做到心中有数了。下面就是针对前面的场景用例而设计出来的数据,如表1-11所示。

表1-11 ATM机器提款场景法用例数据

场  景

PIN

账号

输入 金额

账面 金额

ATM内的余额

预期结果

场景1:成功提款

0001

110~119

60

1000

3000

成功提款

场景2:ATM机器内没有现金

0001

110~119

100

600

0

提款选项不可用,结束用例

场景3:ATM机器内现金不足

0001

110~119

200

500

100

警告提示,反回基本流步骤6,重新输入金额

场景4:PIN有错误

1111

110~119

n/a

300

2000

警告提示,反回基本流步骤4,重新输入金额

……

……

……

……

……

……

……

当然,除了上面讲的这些常用的用例设计方法以外,还有正交试验等设计方法。在实际测试中,往往是综合使用各种方法才能有效地提高测试效率和测试覆盖率,这就需要认真掌握这些方法的原理、认真研读需求规格说明书,了解客户的需求,积累更多的测试经验,以便有效地提高测试水平。

以下是各种测试方法选择的综合策略,可供读者在实际应用过程中参考。

(1)首先进行等价类划分,包括输入条件和输出条件的等价划分,将无限测试变成有限测试,这是减少工作量和提高测试效率最有效的方法。

(2)在任何情况下都必须使用边界值分析方法,经验表明,用这种方法设计出的测试用例发现程序错误的能力最强。

(3)可以用错误推测法追加一些测试用例,这需要依靠测试工程师的智慧和经验。

(4)对照程序逻辑,检查已设计出的测试用例的逻辑覆盖程度,如果没有达到要求的覆盖标准,应当再补充足够的测试用例。

(5)如果程序的功能说明中含有输入条件的组合情况,则一开始就可选用因果图法和判定表驱动法。

(6)对于参数配置类的软件,要用正交实验法选择较少的组合方式达到最佳效果(请关注正交实验法的读者自行查找相关资料进行学习)。

(7)功能图法也是很好的测试用例设计方法,我们可以通过不同时期条件的有效性设计不同的测试数据。

(8)对于业务流清晰的系统,可以利用场景法贯穿整个测试案例过程,在案例中综合使用各种测试方法。

性能测试用例在测试设计阶段也是一项重要的工作,本书重点是讲解性能测试工具LoadRunner的应用,在后续章节对性能测试用例的设计有详细地描述,请大家参看。

用例设计完成之后,通常进行需求、研发、测试、质控人员举行一轮或者多轮对用例的评审工作,评审主要是大家针对设计的用例,考查是否能够覆盖用户的需求。如果用例评审不通过,则需要测试人员对用例进行修改完善、用例补充等工作,直到用例评审通过为止。

测试执行阶段可以划分为两个子阶段,前一个阶段的目的非常清楚,就是发现缺陷,督促大家找出缺陷。测试用例的执行,应该是帮助我们更快地发现缺陷,而不是成为“发现缺陷”的障碍——使发现缺陷的能力降低。从理论上说,如果缺陷都找出来了,质量也就有保证了。所以在这一阶段,就是尽可能发现缺陷,这样不仅对开发团队也非常有利,能尽早地修正大部分缺陷;对测试有利,测试效率高,后面的回归测试也会稳定,信心更充分。在代码冻结或产品发布前的稍后的子阶段,目的是减少风险,增加测试的覆盖度,这时测试的效率会低一些,以损失部分测试效率、获得更高质量的收益。

1.缺陷管理

测试阶段是测试人员和研发人员沟通最频繁的一个阶段。在软件测试过程中,测试人员发现缺陷以后,通常会提交到缺陷管理工具中,常见的缺陷管理工具包括开源免费的测试工具BugZilla、Mantis、JIRA、BugFree等;商业的测试工具有HP TestDirector (QualityCenter)、IBM Rational ClearQuest、Compuware TrackRecord等。测试管理工具能让测试人员、开发人员或其他的IT人员通过一个中央数据仓库,在不同地方就能交互测试信息。一般缺陷管理工具都是测试管理工具的一个重要组成部分,它们都能够将测试过程流水化——从测试需求管理,到测试计划;测试日程安排,测试执行到出错后的错误跟踪——仅在一个基于浏览器的应用中便可完成,而不需要每个客户端都安装一套客户端程序,使用简便。

缺陷提交以后,在大型软件企业或者非常规范企业,测试人员提交缺陷以后,测试负责任人或测试主管首先看一下这个缺陷是不是一个缺陷,如果是缺陷提交给研发的项目经理,研发项目经理将缺陷再分派给具体的研发人员。研发将缺陷修改完成以后,形成一个新的版本,提交给测试组,测试人员对新提交的版本进行问题的验证——这个过程也叫回归测试。如果测试人员经验证所有缺陷均得到修复,则关闭缺陷,那么这个版本就可以作为发布的版本。但是,更多的时候大家可能会遇到对缺陷研发、测试人员之间存在着争议的情况——测试人员认为这个缺陷应该修改,而研发人员认为这个缺陷不需要修改,这时需要质控、研发、测试等相关人员坐到一起,大家对缺陷进行评审来决定缺陷是否需要修改,或者对缺陷是否进行降级处理等,待达到产品的准出条件以后(准出条件举例,如严重等级为中等级别的缺陷不能超过2个),就可以发行产品了。当然,缺陷的处理流程,不同企业对缺陷的处理流程也是各不相同的,这里给大家介绍一下最普遍的缺陷处理流程,如图1-16所示。

图1-16 缺陷处理流程

下面简单给大家介绍一下。

(1)测试人员发现并提交一个Bug,此时Bug的状态为新建(New)状态。

(2)测试负责人、测试主管确认是一个Bug以后,将Bug的状态置为打开(Open)状态,研发经理针对提交的Bug指定研发人员对Bug进行修复,研发人员接受以后,Bug的状态变为已分配(Assigned)状态。

(3)研发人员修改该Bug以后,将Bug的变为已修复(Fixed),待系统Bug修复完成以后,形成一个新的版本提交给测试人员。

(4)测试人员对新版本进行回归测试,如果该Bug确实已经修正,则将Bug的状态修改为已关闭(Closed)状态,如果没有修正,则需要让开发人员继续修改该Bug。

当然,上面的流程还很不完善,在测试过程中还会遇到,新版本中仍然存在与上个版本相同的缺陷,此时就需要将Bug置为重新打开(Reopen)状态,测试人员甲和测试人员乙提交相同Bug,此时就需要将Bug置为重复(Duplicated)状态,还有研发人员认为这不是一个Bug,此时Bug被置为拒绝(Rejected)状态等,这些情况在上面的流程中都没有涉及,所以如果您对缺陷的流程非常关心的话,建议您参考其他的测试书籍,这里限于篇幅,不做过多介绍。

通常在提交一个Bug的时候,都需要输入一些重要的信息,如图1-17所示,包括缺陷的概要信息(Summary)、指派给某人(Assigned To)、缺陷发现者(Detected By)、缺陷发现的版本(Detected in Version)、缺陷发现日期(Detected on Date)、优先级(Priority)、Severity(严重等级)、项目名称(Project)、模块名称(Subject)、状态(Status)、描述(Description)等信息。

图1-17 TestDirector提交一个新的Bug

下面简要描述一下提交Bug时一些重要项的含义。

(1)缺陷概要是用简明扼要的语言表述缺陷的实质性问题。

(2)描述是对概要信息的详细表述,可以包括操作环境、操作步骤、测试数据等信息,这些内容将是您复现问题的重要依据。

(3)缺陷发现的版本是在测试的时候,那个版本的软件中发现的该缺陷。

(4)项目名称是您测试的产品或项目的名称。

(5)模块名称是指产品或项目的具体的功能模块名称,如系统设置模块、业务处理模块等。

(6)状态是指当前缺陷处于何种阶段,如New、Open、Fixed、Closed等。

(7)优先级是处理该缺陷的优先等级,等级高的需要优先处理。

(8)严重等级是指该缺陷将对系统造成的影响程度,在TestDirector(QualityCenter)中主要包括Low(轻微)、Medium(中等)、High(高)、Urgent(严重)等。

2.测试执行

在软件测试执行过程中,因为各个企业的背景不一样,所以实施的手段也各不相同。有的企业非常规范,不仅进行常规的黑盒测试(功能性测试),还进行了白盒测试(如单元测试等),同时进行了系统性能方面的测试;有的企业则主要进行功能性测试和简易的性能测试,这可能是目前国内软件企业最普遍处理方式;有的企业则仅仅进行功能性的测试。

执行测试时应遵循以下步骤。

(1)设置测试环境,确保所需的全部构件(硬件、软件、工具、数据等)都已实施并处于测试环境中。

(2)将测试环境初始化,以确保所有构件都处于正确的初始状态,可以开始测试。

(3)执行测试过程。

测试的执行过程是非常重要,如果测试执行过程处理不得当将会引起软件测试周期变长,测试不完全,人力、物力严重浪费等情况。测试执行阶段是软件测试人员与软件开发人员之间沟通最密切的一个阶段。软件测试是否能够按照计划正常执行和开发人员、IT管理人员、需求人员等的密切配合分不开的。通常,开发人员构建一个版本并制作成一个安装包以后,首先要先运行一下,看看系统的各个功能是否能够正常工作,如果涉及硬件产品还要结合硬件产品进行测试,保证系统大的流程应该是可以运行通的,这也就是我们前面所说的冒烟测试。经过冒烟测试以后,如果没有问题则把该包提交给测试部门进行测试,否则,研发人员需要定位问题产生的原因,修改代码或设置,重新编译、打包以及进行冒烟测试。如果测试部门拿到的是没有经过冒烟测试的产品,则很有可能会出现前面讲的资源浪费、耽误测试进度等情况的发生。笔者管理的测试团队有一次就因为研发人员因为工作任务繁忙,没有对提交的软、硬件结合产品进行冒烟测试,导致测试人员为定位问题而进行业务模块、系统设置等多方面的测试工作,苦苦耗时达5个工作日之久,最后检查到原因,是研发人员提供的硬件的端口是坏的,这个教训很深刻。冒烟测试后的产品提交给测试部门以后,测试人员部署相应的环境,开始依据前期已经通过评审的功能、性能方面的测试用例。在执行用例的过程中,如果发现了缺陷,则提交到缺陷管理工具中,所有的功能、性能测试用例执行完成以后,宣告第一轮测试工作完成。开发人员需要对第一轮测试完成后,出现的缺陷进行修复工作,测试人员也需要在测试过程中修改、完善、补充用例的工作,通常,每轮测试完成以后,测试人员都会给出一个测试的报告,指出当前存在缺陷的严重等级数目,重要的缺陷,缺陷的列表等数据提供给项目经理、研发经理等,目的是让项目组的相关负责人清楚当前系统中存在的主要问题,及时把问题解决掉。等到研发人员对第一轮的缺陷修复完成后,重新编译、打包、冒烟测试,提交给测试部门,测试人员进行第二轮测试,测试人员此时需要进行回归测试,验证上一轮的问题是否已经修复,是不是还有新的问题产生等。如此往复,经过几轮的测试以后,依据项目计划、测试计划以及缺陷的情况等来决定是否终止测试。

测试执行完成以后,我们需要对测试的整个活动进行总结。测试总结工作是非常有意义的一件事情,它不仅能够对本次测试活动进行分析,也能够为以后测试同类产品提供重要的依据。

通常,一份测试总结报告中会包括如下内容:系统的概述、编写目的、参考资料、测试环境、差异、测试充分性评价、残留缺陷、缺陷统计、缺陷分析、测试活动总结、测试结论等方面。

1.编写测试总结报告的目的

测试总结的目的是总结测试活动的结果,并根据这些结果对测试进行评价。这种报告是测试人员对测试工作进行总结,并识别出软件的局限性和发生失效的可能性。在测试执行阶段的末期,应该为每个测试计划准备一份相应的测试总结报告。本质上讲,测试总结报告是测试计划的扩展,起着对测试计划“封闭回路”的作用。

2.重要项说明

表1-12 参考资料列表

序  号

资 料 名 称

作  者

版本和发行时间

获 取 途 径

1

需求规格说明.doc

唐三藏

V2.0/2007-05-30

VSS

2

测试计划.doc

孙悟空

V2.0/2007-05-28

VSS

3

……

……

……

……

 

测试项信息如表1-13所示。

表1-13 测试项列表

测 试 类 型 测试项/被测试的特性
功能测试 批量导入电子档案文件(主执行者:人力资源中心用户)
电子档案(主执行者:人力资源中心用户)
……
性能测试 100个用户并发下载人事数据,响应时间在15s以内(主执行者:代理单位普通用户和人力资源中心用户)
…… ……

 

本次测试的测试环境如下。

软件环境。

操作系统:xx。

服务器端:Windows XP Professional SP2/ Windows 2000 ServerSP4。

客户端:Windows XP ProfessionalSP2。

数据库:SQL Server 2000。

Web应用:Tomcat-5.5.9。

浏览器:Microsoft Internet Explorer 6.0SP2。

硬件环境。

CPU:Intel (R) Pentium (R) 4 CPU 3.00GHz。

内存:1GB以上。

硬盘:80GB。

网卡:100M以太网。

3.覆盖评测

覆盖评测指标是用来度量软件测试的完全程度的,所以可以将覆盖用做测试有效性的一个度量。最常用的覆盖评测是基于需求的测试覆盖和基于代码的测试覆盖,它们分别是指针对需求(基于需求的)或代码的设计/实施标准(基于代码的)而言的完全程度评测。

(1)基于需求的测试覆盖。

基于需求的测试覆盖在测试过程中要评测多次,并在测试过程中,每一个测试阶段结束时给出测试覆盖的度量。例如,计划的测试覆盖、已实施的测试覆盖、已执行成功的测试覆盖等。

(2)基于代码的测试覆盖。

如果您所在的单位做白盒测试,则需要考虑基于代码的测试覆盖。基于代码的测试覆盖评测是测试过程中已经执行的代码的多少,与之相对应的是将要执行测试的剩余代码的多少。许多测试专家认为,一个测试小组在测试工作中所要做的最为重要的事情之一就是度量代码的覆盖情况。很明显,在软件测试工作中,进行基于代码的测试覆盖评测这项工作极有意义,因为任何未经测试的代码都是一个潜在的不利因素。

但是,仅仅凭借执行了所有的代码,并不能为软件质量提供保证。也就是说,即使所有的代码都在测试中得到执行,并不能担保代码是按照客户需求和设计的要求去做了。

4.质量评测

测试覆盖的评测提供了对测试完全程度的评价,而在测试过程中对已发现缺陷的评测提供了最佳的软件质量指标。

常用的测试有效性度量是围绕缺陷分析来构造的。缺陷分析就是分析缺陷在与缺陷相关联的一个或者多个参数值上的分布。缺陷分析提供了一个软件可靠性指标,这些分析为揭示软件可靠性的缺陷趋势或缺陷分布提供了判断依据。

对于缺陷分析,常用的主要缺陷参数有以下4个。

缺陷分析通常用以下3类形式的度量提供缺陷评测。

(1)缺陷发现率。

缺陷发现率是将发现的缺陷数量作为时间的函数来评测,即创建缺陷趋势图,请大家参见图1-18。

图1-18 缺陷趋势图

(2)缺陷潜伏期。

测试有效性的另外一个有用的度量是缺陷潜伏期,通常也称为阶段潜伏期。缺陷潜伏期是一种特殊类型的缺陷分布度量。在实际测试工作中,发现缺陷的时间越晚,这个缺陷所带来的损害就越大,修复这个缺陷所耗费的成本就越多。图1-19显示了一个项目的缺陷潜伏期的度量。

(3)缺陷密度。

软件缺陷密度是一种以平均值估算法来计算出软件缺陷分布的密度值。程序代码通常是以千行为单位的,软件缺陷密度是用下面公式计算的:

软件缺陷密度=软件缺陷数量/代码行或功能点的数量

缺陷 造成 阶段 发现阶段
需求 总体设计 详细设计 编码 单元测试 集成测试 系统测试 验收测试 试运行产品 发布产品
需求 0 1 2 3 4 5 6 7 8 9
总体设计 0 1 2 3 4 5 6 7 8
详细设计 0 1 2 3 4 5 6 7
编码 0 1 2 3 4 5 6
总计

图1-19 缺陷潜伏期的度量

图1-20所示为一个项目的各个模块中每千行代码的缺陷密度分布图。

图1-20 各个模块中每千行代码的缺陷密度

但是,在实际评测中,缺陷密度这种度量方法是极不完善的,度量本身是不充分的。这里边存在的主要问题是:所有的缺陷并不都是均等构造的。各个软件缺陷的恶劣程度及其对产品和用户影响的严重程度,以及修复缺陷的重要程度有很大差别,有必要对缺陷进行“分级、加权”处理,给出软件缺陷在各严重性级别或优先级上的分布作为补充度量,这样将使这种评测更加充分,更有实际应用价值。因为在测试工作中,大多数的缺陷都记录了它的严重程度的等级和优先级,所以这个问题通常都能够很好解决。例如,图1-21所示的缺陷分布图表示软件缺陷在各优先级上所应体现的分布方式。

图1-21 各优先级上软件缺陷分布图

上面讲了一些关于覆盖评测和质量评测内容,下面结合以前做过的项目给大家举一些测试充分性评价方面的示例。

(1)本次测试严格按照软件系统测试规范执行测试任务。

(2)在测试进行过程中,满足执行测试的前置条件,测试计划、测试用例准备齐全,并经过内部评审认可,需求覆盖度达到100%,满足测试准入条件。

(3)测试过程严格按照测试计划实施,测试用例的执行覆盖度达100%,同时,测试过程中根据实际系统的运行方式,对测试用例和数据进行了修改和补充。

(4)测试过程中进行了必要的回归测试和交叉测试。

……

结果概述:总结测试的结果,指出各测试项的测试情况,描述测试用例的执行通过情况,给出最后一次的测试版本号,这里给大家一个示例参考。

(1)本次测试进行了功能测试的检查。最后一次的测试基线为:Build_HHR(α) V2.0.0.014。

(2)功能测试执行情况详见表1-14,缺陷描述详见TD。

表1-14 测试用例执行情况

被测试的特性 对应用例编号 是 否 通 过 备 注
导入电子档案文件 HHR_2.0_TC_导入电子档案文件 功能测试
电子档案 HHR_2.0_TC_电子档案文件 功能测试
单位用户登录 HHR_2.0_TC_单位用户登录 功能测试
预约 HHR_2.0_TC_预约申请 功能测试
HHR_2.0_TC_预约回复
档案转入、转出 HHR_1.0_TC_档案转出 功能测试
下载数据 HHR_2.0_TC_下载数据 性能测试
人员基本信息增加字段 HHR_2.0_TC_填写人事档案数据 功能测试
…… …… …… ……

残留缺陷摘要:简要罗列未被修改的残留缺陷,并附有未修复意见。

缺陷统计:对隶属于各个测试项的缺陷进行统计,通常都需要统计一下两项数据,有的测试部门还有统计其他一些数据信息,请大家根据需要进行选择添加。

各模块下不同解决方案的缺陷统计如表1-15所示。

表1-15 各模块下不同解决方案的缺陷统计表

人事代理系统 有 效 缺 陷 总 计
已 解 决 以 后 解 决 不 解 决
单位管理 1 0 0 1
档案录入 6 0 2 8
档案业务 1 0 0 1
电子档案 8 0 0 8
批量导入 5 0 1 6
下载数据 5 0 0 5
用户管理 1 0 0 1
预约 11 0 1 12
总计 38 0 4 42

各模块下不同严重级别的缺陷统计如表1-16所示。

表1-16 各模块下不同严重级别缺陷所占百分比

高 级 版 2–重要 3–中等 4–次要 5–有待改进
缺陷数目 百分比 缺陷数目 百分比 缺陷数目 百分比 缺陷数目 百分比
单位管理 0 0 1 4.34% 0 0 0 0
档案录入 1 16.67% 2 8.68% 1 12.5% 4 80%
档案业务 0 0 1 4.34% 0 0 0 0
电子档案 2 33.32% 2 8.68% 4 50.0% 0 0
批量导入 1 16.67% 5 21.88% 0 0 0 0
下载数据 1 16.67% 4 17.36% 0 0 0 0
用户管理 0 0 1 4.34% 0 0 0 0
预约 1 16.67% 7 30.38% 3 37.5% 1 20%
总计 6 14.28% 23 54.76% 8 19.00% 5 11.96%

缺陷分析:对有效缺陷进行缺陷分布分析、缺陷趋势分析,以及缺陷龄期分析。

通常都会对以下数据进行分析。

表1-17 模块缺陷分布

模 块 名 称

缺 陷 数 目

单位管理

1

档案录入

8

档案业务

1

电子档案

8

批量导入

6

下载数据

5

用户管理

1

预约

12

由表1-17可知,模块“预约”“电子档案”“批量导入”和“档案录入”占的缺陷相对比较多,主要是异常处理、逻辑控制以及界面易用性问题。

图1-22 缺陷趋势图

由图1-22可知:

(1)整个测试活动持续11天,随着测试时间的推移,新提交的缺陷数减少;

(2)整个测试共提交有效缺陷42个,所有缺陷均已解决、已关闭。

活动总结:总结主要的测试活动和事件。总结资源消耗数据,如人员的总体水平,总机时和每项主要测试活动所花费的时间。同时与《测试计划》中活动进度安排进行比对,如表1-18所示。

表1-18 测试活动时间表

活 动 名 称 提 交 成 果 起 始 时 间 终 止 时 间 执 行 人 员 实际工时(小时)
编写测试用例、准备测试数据 人事代理系统测试用例及其辅助程序的编写和大数据量数据准备 2007-06-18 2007-06-20 张三 24
执行测试 v2.0.0.010 2007-05-30 2007-06-01 张三、李四 48
v2.0.0.011 2007-06-04 2007-06-04 张三、李四 15
v2.0.0.012 2007-06-06 2007-06-07 张三、李四 15
v2.0.0.013 2007-06-12 2007-06-12 王五 3
v2.0.0.014 2007-06-13 2007-06-13 王五 3
编写测试总结报告 人事代理系统测试总结报告 2007-06-20 2007-06-21 张三 12
总计: 136

根据《测试计划》中计划的测试时间和实际测试执行时间进行比对,可得表1-19。

由表1-19可知,计划时间比执行时间偏差较大,主要原因为安排两个测试人员执行测试,但是由于另外一名测试人员配合其他产品的测试相关工作,所以计划时间长于实际测试时间。

测试结论:对每个测试项进行总的评价。本评价必须以测试结果和项的通过准则为依据。说明该项软件的开发是否已达到预定目标。计算代码缺陷率和产品缺陷率。

表1-19 计划时间和执行时间比对表

项 目 名 称 比 对 项 测试计划时间(小时) 实际执行时间(小时) 执行偏差(小时)
人事代理系统 测试用例和测试数据准备 24 22 -2
测试构建和测试执行 240 84 -156
测试总结 12 8 -4
总工时(小时) 276 114 -162

例如:

(1)经测试验证,系统完成需求所要求的全部功能,测试项中各功能的实现与需求描述一致;

(2)测试结果满足测试退出准则;

(3)整个系统在设计结束后定义功能点96个,测试发现的有效缺陷为42个,按功能点对缺陷数进行计算可得,代码缺陷率=42/96=0.4375个/FP(代码缺陷率=有效缺陷/FP总数)。

软件测试的工作量很大,据统计,测试时间会占到总开发时间的20%~40%,一些可靠性要求非常高的软件,测试时间甚至占到总开发时间的60%。但在整个软件测试过程中,极有可能应用计算机进行自动化测试的工作,原因是测试的许多操作是重复性的、非创造性的、需要细致注意力的工作,而计算机最适合于代替我们去完成这些任务。

测试自动化是通过开发和使用一些工具自动测试软件系统,特别适合于测试中重复而烦琐的活动,其好处是显而易见的。

(1)可以使某些测试任务比手工测试执行的效率高,并可以运行更多更频繁的测试。

(2)对程序的新版本可以自动运行已有的测试,特别是在频繁地修改许多程序的环境中,一系列回归测试的开销应是最小的。

(3)可以执行一些手工测试困难或不可能做的测试,例如,对于200个用户的联机系统,用手工进行并发操作的测试几乎是不可能的,但自动测试工具可以模拟来自200个用户的输入。客户端用户通过定义可以自动回放的测试,随时都可以运行用户脚本,即使是不了解整个商业应用复杂内容的技术人员也可以胜任。

(4)更好地利用资源。将烦琐的任务自动化,如重复输入相同的测试输入,可以提高准确性和测试人员的积极性,将测试技术人员解脱出来,投入更多精力设计更好的测试用例。另外,可以利用整夜或周末空闲的机器执行自动测试。

(5)测试具有一致性和可重复性。对于自动重复的测试可以重复多次相同的测试,如不同的硬件配置、使用不同的操作系统或数据库等,从而获得测试的一致性,这在手工测试中是很难保证的。

(6)测试可以重用,而且软件经过自动测试后,人们对其信任度会增加。

(7)一旦一系列测试已经被自动化,则可以更快地重复执行,从而缩短了测试时间,使软件更快地推向市场。

总之,测试自动化通过较少的开销可以获得更彻底的测试,并提高产品的质量。但是,在实际使用自动化测试的过程中,还存在一些普遍的问题。

(1)人们乐观地期望测试工具可以解决目前遇到的所有问题,但无论工具从技术角度实现得多么好,都满足不了这种不现实的期望。

(2)如果缺乏测试实践经验,测试组织差,文档较少或不一致,测试发现缺陷的能力较差,在这种情况下采用自动测试并不是好办法。

(3)人们容易期望自动化测试发现大量的新缺陷。测试执行工具是回归测试工具,用于重复已经运行过的测试,这是一件很有意义的工作,但并不是用来发现大量新的缺陷。

(4)因为测试软件没有发现任何缺陷并不意味着软件没有缺陷,测试不可能全面或测试本身就有缺陷,但人们在使用自动化测试过程中会缺乏这种意识。

(5)当软件修改后,通常需要对修改部分或全部测试,以便可以重新正确地运行,对于自动化测试更是如此。测试维护的开销打击了测试自动化的积极性。

(6)商用测试执行工具是软件产品,由销售商销售,它们往往不具备解决问题的能力和有力的技术支持,因此给用户带来失望,认为测试工具不能很好地测试。

(7)自动化测试实施起来并不简单,必须有管理支持及组织艺术,必须进行选型、培训和实践,并在组织内普遍使用工具。

测试自动化具有局限性,不可能取代手工测试。手工测试可以比自动测试发现更多的缺陷,而测试自动化对期望结果的正确性有极大的依赖性。测试自动化并不能改进测试有效性,并对软件开发有一定的制约作用,测试工具没有创造性,灵活性也较差。然而,测试自动化可以大大提高软件测试的质量。


有的公司招聘性能测试人员时,经常会问一个问题“您能否简单地介绍一下性能测试的过程?”多数应聘者的回答不尽人意,原因是很多人不是十分清楚,以至于回答问题的思路混乱。其实,大家在应聘性能测试职位时,必须清楚这个职位具体是做哪些工作的,并按照工作的流程把每一个环节都表述清楚。下面笔者结合自己多年的工作经验介绍,性能测试的过程。

典型的性能测试过程如图2-1所示。

图2-1 典型的性能测试过程


注意

方框区域为可能存在多次进行的操作部分。


下面对性能测试过程的每个部分进行详细介绍。当测试人员拿到“用户需求规格说明书”以后,文档中会包含功能、性能以及其他方面的要求,性能测试人员最关心的内容就是性能测试相关部分的内容描述。

性能测试的目的是明确客户的真正需求,这是性能测试最关键的部分。很多客户对性能测试不了解,测试人员可能会因为客户提出的“我们需要贵单位对所有的功能都进行性能测试”“系统用户登录响应时间小于3秒”“系统支持10万用户并发访问”等要求所困扰。不知道读者是不是看出了上面几个要求存在的问题,下面让我们逐一来分析这几句话。

1.我们需要贵单位对所有的功能都进行性能测试

从客户的角度来看,肯定都是希望所有的系统应用都有好的系统性能表现,那么是不是所有的功能都要经过性能测试呢?答案当然是否定的,通常性能测试周期较长。首先,全部功能模块都进行性能测试需要非常长的时间;其次,根据218原则,通常系统用户经常使用的功能模块大概占用系统整个功能模块数目的20%,像“参数设置”等类似的功能模块,通常仅需要在应用系统时由管理员进行一次性设置,针对这类设置进行性能测试也是没有任何意义的。通常,性能测试是由客户提出需求内容,性能测试人员针对客户的需求进行系统和专业的分析后,提出相应的性能测试计划、解决方案、性能测试用例等与用户共同分析确定最终的性能测试计划、解决方案、性能测试用例等,性能测试的最终测试内容通常也是结合客户真实的应用场景,客户应用最多、使用最频繁的功能。所以说,“对所有的功能都进行性能测试”是不切实际,也是不科学的做法,作为性能测试人员必须清楚。

2.系统用户登录响应时间小于3秒

从表面看这句话似乎没有什么问题,仔细看看是不是看出点什么门道呢?其实这句话更像一个功能测试的需求,因为其没有指明是在多少用户访问时,系统的响应时间小于3秒,作为性能测试人员必须清楚客户的真实需求,消除不明确的因素。

3.系统支持10万用户并发访问

从表面看这句话似乎也没有什么问题。在进行性能测试时,系统的可扩展性是需要考虑的一个重要内容。例如,一个门户网站,刚开始投入市场时,只有几百个用户,随着广告、推荐等系统宣传力度的加大,在做系统性能测试时,需要对未来两三年内系统的应用用户有初步预期,使系统在两三年后仍然能够提供良好的性能体验。但是,如果系统每天只有几十个用户,在未来的5~10年内,也不过几百个用户,那么还需要进行10万级用户并发访问的性能测试吗?作者的建议是把这种情况向客户表达清楚,在满足当前和未来用户应用系统性能要求的前提下进行测试,能够节省客户的投入,无疑客户会觉得你更加专业,也真正从客户的角度出发,相信一定会取得更好的效果。如果系统用户量很大,考虑到可扩展性需求,确实需要进行10万级用户这种情况的性能测试。我们也需要清楚10万级用户的典型应用场景,以及不同操作人员的比例,这样的性能测试才会更有意义。

性能测试计划是性能测试的重要环节。在对客户提出的需求经过认真分析后,性能测试管理人员需要编写的第一份文档就是性能测试计划,性能测试计划非常重要,需要阐述产品、项目的背景,明确前期的测试性能需求,并落实到文档中。指出性能测试可参考的一些文档,并将这些文档的作者、编写时间、获取途径逐一列出,形成一个表格,这些文档包括用户需求规格说明书、会议纪要(内部讨论、与客户讨论等最终确定的性能测试内容)等性能测试相关需求内容文档。性能测试也是依赖于系统正式上线的软、硬件环境的,因此包括网络的拓扑结构、操作系统、应用服务器、数据库等软件的版本信息、数据库服务器、应用服务器等具体硬件配置,如CPU、内存、硬盘、网卡、网络环境等信息也应该描述。系统性能测试的环境要尽量和客户上线的环境条件相似,在软、硬件环境相差巨大的情况下,对于真正评估系统上线后的性能有一定偏差,有时甚至更坏。为了能够得到需要的性能测试结果,性能测试人员需要认真评估要在本次性能测试中应用的工具, 该工具能否对需求中描述的相关指标进行监控,并得到相关的数据信息。性能测试结果数据信息是否有良好的表现形式,并且可以方便地输出?项目组性能测试人员是否会使用该工具?工具是否简单易用等。当然在条件允许的情况下,把复杂的性能测试交给第三方专业测试机构也是一个不错的选择。人力资源和进度的控制,需要性能测试管理人员认真考虑。很多失败的案例告诉我们,由于项目前期研发周期过长,项目开发周期延长,为了保证系统能够按时发布,不得不缩短测试周期,甚至取消测试,这样的项目质量是得不到保证的,通常其结果也必将以失败而告终。所以要合理安排测试时间和人员,监控并及时修改测试计划,使管理人员和项目组成员及时了解项目测试的情况,及时修正在测试过程中遇到的问题。除了在计划中考虑上述问题以外,还应该考虑如何规避性能测试过程中可能会遇到的一些风险。在性能测试过程中,有可能会遇见一些将会发生的问题,为了保证后期在实施过程中有条不紊,应该考虑如何尽量避免这些风险的发生。当然,性能测试计划中还应该包括性能测试准入、准出标准以及性能测试人员的职责等。一份好的性能测试计划为性能测试成功打下了坚实的基础,所以请读者认真分析测试的需求,将不明确的相关内容弄清楚,制定出一份好的性能测试计划,然后按照此计划执行,如果执行过程与预期不符,则及时修改计划,不要仅仅将计划作为一份文档,而要将其作为性能测试行动的指导性内容。

性能测试需求最终要体现在性能测试用例设计中,应结合用户应用系统的场景,设计出相应的性能测试用例,用例应能覆盖到测试需求。很多人在设计性能测试用例时,有束手无策的感觉。这时,需要考虑是否存在以下几个方面的问题。

(1)你是否更加关注于工具的使用,而忽视了性能测试理论知识的补充。

(2)你是否对客户应用该系统经常处理哪些业务不是很清楚。

(3)你是否对应用该系统的用户数不是很了解。

(4)你是否也陷入公司没有性能测试相关人员可以交流的尴尬境地。

当然,上面只列出了一些典型的问题,实际中可能会碰到更多的问题。这里,作者想和诸位朋友分享一下工作心得。在刚开始从事性能测试工作时,肯定会碰到很多问题。一方面,由于性能测试是软件测试行业的一个新兴分类,随着企业的飞速发展,各种系统规模的日益庞大,软件企业也更加注重性能测试,从招聘网上搜索“性能测试工程师”,可以搜索到几百条招聘性能测试工程师相关职位的信息,如图2-2所示。

图2-2 招聘性能测试工程师相关职位信息

但是,由于性能测试工作在国内刚起步,性能测试方面的知识也不是很多,加之很多单位在招聘性能测试工程师岗位时,对工具的要求更多一些(如图2-3所示的“高级性能测试工程师”岗位要求信息),所以很多测试人员对性能测试工作产生了误解。觉得性能测试的主要工作就是应用性能测试工具,如果性能测试工具方面的知识学得好,做性能测试工作就没有问题。其实,工具是为人服务的,真正指导性能测试工作的还是性能测试的理论和实践知识,要做好性能测试,需要运用工具将学习到的理论知识和深入理解的用户需求这些思想体现出来,做好执行、分析以及调优工作,这样才能够做好测试。性能测试人员可能会遇到客户需求不明确,对客户应用业务不清楚等情况,这时,需要与公司内部负责需求、业务的专家和客户进行询问、讨论,把不明确的内容弄清楚,最重要的是一定要明确用户期望的相关性能指标。在设计用例时,通常需要编写如下内容:测试用例名称、测试用例标识、测试覆盖的需求(测试性能特性)、应用说明、(前置/假设)条件、用例间依赖、用例描述、关键技术、操作步骤、期望结果(明确的指标内容)、记录实际运行结果等内容,当然,上面的内容可以依据需要适当裁减。

图2-3 招聘性能测试工程师岗位要求信息

性能测试用例编写完成后,接下来需要结合用例的需要,编写测试脚本。本书后面将介绍有关LoadRunner协议选择和脚本编写的知识。关于测试脚本的编写这里着重强调以下几点。

(1)协议的选用关系到脚本能否正确录制与执行,十分重要。因此在进行程序的性能测试之前,测试人员必须明确被测试程序使用的协议。

(2)测试脚本不仅可以使用性能测试工具来完成,在必要时,可以使用其他语言编程来完成同样的工作。

(3)通常,在应用工具录制或者编写脚本完成以后,还需要去除脚本不必要的冗余代码,对脚本进行完善,加入集合点、检查点、事务以及对一些数据进行参数化、关联等处理。在编写脚本时,需要注意的还有,为了脚本之间的前后依赖性,如一个进销存管理系统,在销售商品之前,只有先登录系统,对系统进行进货处理,才能够进行销售(本系统不支持红数概念,即不允许负库存情况发生)。这就是前面所讲的脚本间依赖的一个实例。因此在有类似情况发生时,应该考虑脚本的执行顺序,在本例中是先执行登录脚本,再执行业务脚本进货,最后进行销售,系统登出。当然有两种处理方式,一种是录制4个脚本,另一种方式是在一个脚本中进行处理,将登录部分放在vuser_init(),进货、销售部分代码可以放在Acition中,最好建立两个Acition分别存放,而将登出脚本放在vuser_end()部分。参数化时,也要考虑前后数据的一致性。关于参数化相关选项的含义,请参见4.4节。

(4)在编写测试脚本时,还需要注意编码的规范和代码的编写质量问题。软件性能测试不是简单的录制与回放,一名优秀的性能测试人员可能经常需要自行编写脚本,这一方面要提高自己的编码水平,不要使编写的脚本成为性能测试的瓶颈。很多测试人员,由于不是程序员出身,对程序的理解也不够深入,经常会出现如申请内存不释放、打开文件不关闭等情况,却不知这些情况会造成内存泄露。所以要加强编程语言的学习,努力使自己成为一名优秀的“高级程序员”。另外一方面,也要加强编码的规范。测试团队少则几人,多则几十人、上百人,如果大家编写脚本时,标新立异,脚本的可读性势必很差,加之IT行业人员流动性很大,所以测试团队有一套标准的脚本编写规范势在必行。在多人修改维护同一个脚本的情况下,还应该在脚本中记录修改历史。好的脚本应该是不仅自己能看懂,别人也能看懂。

(5)经常听到很多同事追悔莫及地说,“我的那个脚本哪去了,这次性能测试的内容和以前做过的功能一模一样啊!”“以前便写过类似脚本,可惜被我删掉了!”等类似话语。因为企业开发的软件在一定程度上存在类似的功能,所以脚本的复用情况会经常发生,历史脚本的维护同样是很重要的一项工作。作者建议将脚本纳入配置管理,配置管理工具有很多,如Visual Source Safe、Firefly、PVCS、CVS、Havest等都是不错的。

性能测试场景设计以性能测试用例、测试脚本编写为基础,脚本编写完成后需要进行如下;如需进行并发操作,则加入集合点;如需考察某一部分业务处理响应时间,则插入事务;为检查系统是否正确执行相应功能而设置的检查点;输入不同的业务数据,则需要进行参数化。测试场景设计的一个重要原则就是依据测试用例,把测试用例设计的场景展现出来。目前性能测试工具有很多,既有开源性能测试工具、免费性能测试工具,也有功能强大的商业性能测试工具,如表2-1~表2-3所示。

表2-1 开源性能测试工具

工 具 名 称

功 能 简 介

JMeter

JMeter可以完成针对静态资源和动态资源(Servlets、Perl脚本、Java对象、数据查询、FTP服务等)的性能测试,可以模拟大量的服务器负载、网络负载、软件对象负载,通过不同的加载类型全面测试软件的性能、提供图形化的性能分析

OpenSTA

OpenSTA可以模拟大量的虚拟用户,结果分析包括虚拟用户响应时间、Web服务器的资源使用情况、数据库服务器的使用情况,可以精确地度量负载测试的结果

DbMonster

DBMonster是一个生成随机数据,用来测试SQL数据库压力的测试工具

TpTest

TPTest提供测试Internet连接速度的简单方法

……

……

表2-2 商业性能测试工具

工 具 名 称

功 能 简 介

HP LoadRunner

HP LoadRunner是一种预测系统行为和性能的工业级标准性能测试负载测试工具。通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题。LoadRunner能够对整个企业架构进行测试,支持Web(HTTP/HTML)、Windows Sockets、File Transfer Protocol(FTP)、Media Player(MMS)、ODBC、MS SQL Server等协议

IBM Rational Performance Tester

适用于团队验证Web应用程序的可伸缩性的负载和性能测试工具,引入了新的技术进行负载测试的创建、修改、执行和结果分析

……

……

表2-3 免费性能测试工具

工 具 名 称

功 能 简 介

Microsoft Application Center Test

可以对Web服务器进行强度测试,分析Web应用程序(包括ASPX页及其使用的组件)的性能和可伸缩性问题。通过打开多个服务器连接并迅速发送HTTP请求,Application Center Test可以模拟大量用户

Microsoft Web Application Stress Tool

由Microsoft公司的网站测试人员开发,专门用来进行实际网站压力测试的一套工具。可以以数种不同的方式建立测试指令:包含以手工、录制浏览器操作的步骤,或直接录入IIS的记录文件、网站的内容及其他测试程序的指令等方式

……

……

不同性能测试工具的操作界面和应用方法有很大的区别,但是其工作原理有很多相似的地方。关于测试场景的设计这里着重强调以下几点。

(1)性能测试工具都是用进程或者线程来模拟多个虚拟用户。如果按进程运行每个虚拟用户(Vuser),则对于每个Vuser实例,都将反复启动同一驱动程序并将其加载到内存中。将同一驱动程序加载到内存中会占用大量随机存取存储器(RAM)及其他系统资源。这就限制了可以在任意负载生成器上运行的Vuser的数量。如果按线程运行每个Vuser,这些线程Vuser将共享父驱动进程的内存段。这就消除了多次重新加载驱动程序/进程的需要,节省了大量内存空间,从而可以在一个负载生成器上运行更多的Vuser。在应用线程安全的协议时,笔者推荐使用线程模式。

(2)场景设计如果存在有执行次序依赖关系的脚本,则注意在场景设计时顺序不要弄错。

(3)场景的相关设置项也是需要关注的重要内容,这里仅以LoadRunner为例。如果应用虚拟IP时,需要选中项。如果应用了集合点,则需要单击选项,设定集合点策略。如果需要多台负载机进行负载,则可以单击进行负载机的连接测试。此外,还可以为接下来的场景运行、监控、分析设定一些参数,如连接超时、采样频率、网页细分等。

测试场景运行是关系到测试结果是否准确的一个重要过程。经常有很多测试人员花费了大量的时间和精力去做性能测试,可是做出来的测试结果不理想。原因是什么呢?关于测试场景的设计这里着重强调以下几点。

(1)性能测试工具都是用进程或者线程来模拟多个虚拟用户,每个进程或者线程都需要占用一定的内存,因此要保证负载的测试机足够跑完设定的虚拟用户数,如果内存不够,则用多台负载机分担进行负载。

(2)在进行性能测试之前,需要先将应用服务器“预热”,即先运行应用服务器的功能。这是为什么呢?高级语言翻译成机器语言,计算机才能执行高级语言编写的程序。翻译的方式有两种:编译和解释。这两种方式只是翻译的时间不同。编译型语言程序执行前,需要一个专门的编译过程,把程序编译成为机器语言的文件,如可执行文件,以后再运行就不用重新翻译了,直接使用编译的结果文件执行(EXE)即可。因为翻译只做了一次,运行时不需要翻译,所以编译型语言的程序执行效率高。解释则不同,解释性语言的程序不需要编译,省了一道工序,解释性语言在运行程序时才翻译,如解释性语言JSP、ASP、Python等,专门有一个解释器能够直接执行程序,每个语句都是执行时才翻译。这样解释性语言每执行一次就要翻译一次,效率比较低。这也就是很多测试系统的响应时间为什么很长的一个原因,就是没有实现运行测试系统,导致第一次执行编译需要较长时间,从而影响了性能测试结果。

(3)在有条件的情况下,尽量模拟用户的真实环境。经常收到一些测试同行的来信说:“为什么我们性能测试的结果每次都不一样啊?”,经过询问得知,性能测试环境竟与开发环境为同一环境,且同时被应用。很多软件公司为了节约成本,开发与测试使用同一环境进行测试,这种模式有很多弊端。进行性能测试时,若研发和测试共用系统,因性能测试周期通常少则几小时,多则几天,这不仅给研发和测试人员使用系统资源带来一定的麻烦,而且容易导致测试与研发的数据相互影响,所以尽管经过多次测试,但每次测试结果各不相同。随着软件行业的蓬勃发展,市场竞争也日益激励,希望软件企业能够从长远角度出发,为测试部门购置一些与客户群基本相符的硬件设备,如果买不起服务器,可以买一些配置较高的PC代替,但是环境的部署一定要类似。如果条件允许,也可以在客户实际环境进行性能测试。总之,一定要注意测试环境的独立性,以及网络,软、硬件测试环境与用户实际环境的一致性,这样测试的结果才会更贴近真实情况,性能测试才会有意义。

(4)测试工作并不是一个单一的工作,测试人员应该和各个部门保持良好的沟通。例如,在遇到需求不明确时,需要和需求人员、客户以及设计人员进行沟通,把需求弄清楚。在测试过程中,如果遇到自己以前没有遇到过的问题,也可以与同组的测试人员、开发人员进行沟通,及时明确问题产生的原因、解决问题方案。点滴的工作经验积累对测试人员很有帮助,这些经验也是日后问题推测的重要依据。在测试过程中,也需要部门之间相互配合,这就需要开发人员和数据库管理人员与测试人员相互配合完成1年业务数据的初始化工作。因此,测试工作并不是孤立的,需要和各部门进行及时沟通,在需要帮助的时候,一定要及时提出,否则可能会影响项目工期,甚至导致项目失败,在测试中我一直提倡“让最擅长的人做最擅长的事”,在项目开发周期短,人员不是很充足的情况下,这点表现更为突出,不要浪费大量的时间在自己不擅长的事情上。

(5)性能测试的执行,在时间充裕的情况下,最好同样一个性能测试用例执行3次,然后分析结果,只有结果相接近,才可以证明此次测试是成功的。

场景运行监控可以在场景运行时决定要监控哪些数据,便于后期分析性能测试结果。应用性能测试工具的重要目的就是提取本次测试关心的数据指标内容。性能测试工具利用应用服务器、操作系统、数据库等提供的接口,取得在负载过程中相关计数器的性能指标。关于场景的监控有以下几点需要大家在性能测试过程中注意。

(1)性能测试负载机可能有多台,负载机的时钟要一致,以保证监控过程中的数据是同步的。

(2)场景的运行监控也会给系统造成一定的负担,因为在操作过程中需要搜集大量的数据,并存储到数据库中,所以尽量搜集与系统测试目标相关的参数信息,无关内容不必进行监控。

(3)通常只有管理员才能够对系统资源等进行监控,因此,很多朋友会问:“为什么我监控不到数据?为什么提示我没有权限?”等类似问题,作者的建议是:以管理员的身份登录后,如果监控不了相关指标,再去查找原因,不要耗费过多精力做无用功。

(4)运行场景的监控是一门学问,需要对要监控的数据指标有非常清楚的认识,同时还要求非常熟悉性能测试工具,当然这不是一朝一夕的事情,作为性能测试人员,我们只有不断努力,深入学习这些知识,不断积累经验,才能做得更好。

在性能测试执行过程中,性能测试工具搜集相关性能测试数据,待执行完成后,这些数据会存储到数据表或者其他文件中。为了定位系统性能问题,需要系统分析这些性能测试结果。性能测试工具自然能帮助我们生成很多图表,也可以进一步对这些图表进行合并等操作来定位性能问题。是不是在没有专业性能测试工具的情况下,就无法完成性能测试呢?答案是否定的,其实有很多种情况下,性能测试工具会受到一定的限制,这时,需要编写一些测试脚本来完成数据的搜集工作,当然数据存储的介质通常也是数据库或者其他格式的文件,为了便于分析数据,需要先对这些数据进行整理再分析。如何将数据库、文件的杂乱数据变成直观的图表请参见4.15节~4.18节的内容。

目前,被广泛应用的性能分析方法是“拐点分析”。“拐点分析”是一种利用性能计数器曲线图上的拐点进行性能分析的方法。它的基本思想是性能产生瓶颈的主要原因是因为某个资源的使用达到了极限,此时表现为随着压力的增大,系统性能急剧下降,从而产生了“拐点”现象。只要得到“拐点”附近的资源使用情况,就能定位出系统的性能瓶颈。例如,系统随着用户的增多,事务响应时间缓慢增加,当达到100个虚拟用户时,系统响应时间急剧增加,表现为一个明显的“折线”,这就说明系统承载不了如此多的用户做这个事务,也就是存在性能瓶颈。

性能测试分析人员经过分析结果以后,有可能提出系统存在性能瓶颈。这时相关开发人员、数据库管理员、系统管理员、网络管理员等就需要根据性能测试分析人员提出的意见与性能分析人员共同分析确定更细节的内容,相关人员对系统进行调整以后,性能测试人员继续进行第二轮、第三轮……的测试,与以前的测试结果进行对比,从而确定经过调整以后系统的性能是否有提升。有一点需要提醒大家,就是在进行性能调整时,最好一次只调整一项内容或者一类内容,避免一次调整多项内容而引起性能提高却不知道是由于调整哪项关键指标而改善性能的。在系统调优过程中,好的策略是按照由易到难的顺序对系统性能进行调优。系统调优由易到难的先后顺序如下。

(1)硬件问题。

(2)网络问题。

(3)应用服务器、数据库等配置问题。

(4)源代码、数据库脚本问题。

(5)系统构架问题。

硬件发生问题是最显而易见的,如果CPU不能满足复杂的数学逻辑运算,就可以考虑更换CPU,如果硬盘容量很小,承受不了很多的数据,就可以考虑更换高速、大容量硬盘等。如果网络带宽不够,就可以考虑对网络进行升级和改造,将网络更换成高速网络。还可以将系统应用与平时公司日常应用进行隔离等方式,达到提高网络传输速率的目的。很多情况下,系统性能不是十分理想的一个重要原因就是,没有对应用服务器、数据库等软件进行调优和设置,如对Tomcat系统调整堆内存和扩展内存的大小,数据库引入连接池技术等。源代码、数据库脚本是在上述调整无效的情况下,可以选择的一种调优方式,但是因为对源代码的改变有可能会引入缺陷,所以在调优以后,不仅需要性能测试,还要对功能进行验证,以验证是否正确。这种方式需要通过对数据库建立适当的索引,以及运用简单的语句替代复杂的语句,从而达到提高SQL语句运行效率的目的,还可以在编码过程中选择好的算法,减少响应时间,引入缓存等技术。如果在上述尝试都不见效的情况下,就需要考虑现行的构架是否合适,选择效率高的构架,但由于构架的改动比较大,所以应该慎重对待。

性能测试工作完成以后,需要编写性能测试总结报告。

性能测试总结不仅使我们能够了解如下内容:性能测试需求覆盖情况,性能测试过程中出现的问题,又是如何去分析、调优、解决的,测试人员进度控制与实际执行偏差,性能测试过程中遇到的各类风险是如何控制的,经过该产品/项目性能测试后,有哪些经验和教训等内容。随着国内软件企业的发展、壮大,越来越多的企业重视软件产品的质量,而好的软件无疑和良好的软件生命周期过程控制密不可分。在这个过程中,不断规范化软件生命周期各个过程、文档的写作,以及各个产品和项目测试经验的总结是极其重要的。通常一份性能测试总结报告要描述如下内容。

需要阐述产品、项目的背景,将前期的性能测试需求明确,并落实到文档中。指出性能测试可参考的一些文档,并将这些文档的作者、编写时间、获取途径逐一列出,形成一个表格。这些文档包括用户需求规格说明书、会议纪要(内部讨论、与客户讨论等最终确定的关于性能测试内容)等与性能测试相关的需求内容文档。因为性能测试也依赖于系统正式上线的软、硬件环境,所以包括网络的拓扑结构、操作系统、应用服务器、数据库等软件的版本信息,数据库服务器、应用服务器等具体硬件配置(CPU、内存、硬盘、网卡等),网络环境等信息也应该描述。应明确标识出实测环境的相关信息。系统性能测试的环境要尽量和客户软件上线的环境条件相似,在软、硬件环境相差巨大的情况下,测试的结果和系统上线后的性能有一定偏差,有时甚至更坏。在测试执行过程中应用的性能测试相关的工具名称、版本等,如果您有部分内容由第三方专业的测试机构完成,则应让其提供明确的结论性输出物和执行过程相关脚本代码、场景、日报/周报、监控数据等相关文档资料。性能测试总结一定要结合性能测试计划内容来进行比对,实际执行过程的提交的相关文档、准入准出条件、场景设计、性能指标、测试环境、性能测试相关工具应用、执行进度等都是需要考量的内容。如果实际执行过程和测试计划有偏差,则要分析产生偏差的原因,以及是否对结果影响。

“不积跬步无以至千里,不积小流无以成江海”性能测试总结不仅是对本次性能测试执行全过程以及本次性能测试是否达标的一个总结,它应该也是团队总结在项目实施过程中经验和教训(包括时间安排、技术难点、分析方法、沟通协调、团队协作、工具选择等)的积累。

本章概要介绍了性能测试的基本过程,然后详细介绍了性能测试基本过程的各个环节。

执行性能测试的基本过程对于做好性能测试工作具有积极和重要意义,特别是刚开始接触性能测试的人员,请务必在性能测试实施初始阶段就能够坚持、保持良好的流程规范,做好每一个关键步骤,认真总结在性能测试实施过程中的得与失,为后续工作积累更多的经验。

性能测试的理论知识是指导性能测试整个实施过程的重要依据,也是保证性能测试能够顺利实施并取得良好效果的基础,本章的所有内容都非常重要,请认真掌握。

一、章节习题

1.请依据典型的性能测试过程,补全图2-4中空白方框的内容。

2.如果在性能测试需求分析阶段,客户提出了“我们需要贵单位对所有的功能都进行性能测试”的需求,要如何处理?

3.简述在性能测试执行过程中场景运行监控环节,以及应该注意的问题。

图2-4 待补充完整的典型的性能测试过程

二、经典面试试题

1.简述典型的性能测试的基本过程及各过程需要做的工作。

2.在性能测试分析阶段“拐点分析”方法被大家广泛应用,请说明该方法的基本思想是什么?

一、章节习题

1.请依据典型的性能测试过程,补全图2-4中空白方框的内容。

答:如图2-5所示。

图2-5 补充完整的典型的性能测试过程

2.如果在性能测试需求分析阶段,客户提出了“我们需要贵单位对所有的功能都进行性能测试”的需求,要如何处理。

答:首先,全部功能模块都进行性能测试需要非常长的时间;其次,根据218原则,通常系统用户经常使用的功能模块大概占用系统整个功能模块数的20%,像“参数设置”等类似的功能模块,通常仅需要在应用系统时,由管理员一次性设置,针对这类设置进行性能测试也是没有任何意义的。所以说,“对所有的功能都进行性能测试”是不切实际,也是不科学的做法。通常,性能测试是由客户提出需求内容,性能测试人员针对客户的需求进行系统和专业的分析后,提出相应的性能测试计划、解决方案、性能测试用例等与用户共同分析确定最终的性能测试计划、解决方案、性能测试用例等。性能测试的最终测试内容通常也是结合客户真实的应用场景,即客户应用最多,使用最频繁的功能。

3.简述在性能测试执行过程中场景运行监控环节,以及应该注意的问题。

答:关于场景的监控有以下几点需要在性能测试过程中注意。

二、经典面试试题

1.简述典型的性能测试的基本过程及各过程需要做的工作。

答:性能测试的基本过程如图2-5所示,关于各过程需要做哪些工作,在这里只做简单的阐述,详细的具体内容请读者阅读相关过程内容。

2.如果在性能测试需求分析阶段,客户提出了“我们需要贵单位对所有的功能都进行性能测试”的需求,要如何处理。

答:基本思想就是性能产生瓶颈的主要原因是某个资源的使用达到了极限,此时表现为随着压力的增大,系统性能急剧下降,从而产生“拐点”现象。只要得到“拐点”附近资源的使用情况,就能定位出系统的性能瓶颈。


相关图书

现代软件测试技术之美
现代软件测试技术之美
渗透测试技术
渗透测试技术
JUnit实战(第3版)
JUnit实战(第3版)
深入理解软件性能——一种动态视角
深入理解软件性能——一种动态视角
云原生测试实战
云原生测试实战
Android自动化测试实战:Python+Appium +unittest
Android自动化测试实战:Python+Appium +unittest

相关文章

相关课程