qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

在U盘上安装Linux系统解决方案

  到此为止,U盘就可以成功的启动了。

  插上U盘,把电脑设置成从USB启动即可。

  另外,如果是由于Linux系统驱动不支持导致的启动失败,暂无解决方案,只能换系统。

  既然本文叫做解决方案,就多说一点,再介绍一种方案。

  简介:

  国内有一款比较流行的移动Linux操作系统puppy,支持中文,界面很漂亮,而且很好的支持多媒体,比如QQ、看电影什么的。更重要的是,兼容性很强。

  制作工具:

  制作U盘启动盘很简单,只需要下边两个工具。

  Puppy LiveUSB:把Puppy系统ISO镜像写入U盘的工具,一键完成,这个工具只能写入Puppy系统,普通的系统要用上边讲的方法。

  custom-puppy.iso:Puppy中文定制版ISO镜像。

  注意事项:

  | 写入过程中一定要关闭杀毒软件,万一被拦截了就不爽了。。。。软件均来自官方,无毒无害,放心使用。

  | 如果启动不成功,找到U盘中的“isolinux.cfg”文件,把这个文件中的“pmedia=cd”改成“pmedia=usbflash”即可。

  | 用PuppyLiveUSB写入时,建议把U盘启动模式设置成HDD。

  本菜鸟水平有限,教程就到这了。

  有问题欢迎和我交流!  作为一名IT菜鸟,用PE维护系统已经满足不了我的需求,把windows装进U盘又太俗,只能把目光转向Linux了。

  大致从网上搜索了一下教程,尽是些N年前老掉牙的教程。别的不说,那个麻烦劲就让人吐了。

  时代在发展,科技在进步,其实简单的方法早就有了,虽然网上也有一些,但是并不全面,造成很多问题。现在,本小菜把它总结出来。

  准备工作

  |  Unetbootin:Linux系统写入U盘工具。

  |  BOOTICE:引导设置工具。

  |  你自己的Linux系统ISO镜像。

  |  把U盘格式化成FAT32格式,对着U盘点右键--格式化即可,不需要什么工具。

  第一步,使用unetbootin向U盘写入Linux系统ISO镜像。

  双击启动Unetbootin,看到如下界面。

  选好后点确定。出现如下界面,大约30秒就能完成。

  完成以上步骤,就把Linux系统写入U盘了。

  为什么要用Unetbootin写入呢?UltraISO不行吗?原因是仅仅把系统写入U盘是无法启动的,还需要用syslinux来引导,syslinux实际上是一个极小的Linux系统,只起引导作用。而Unetbootin恰恰自带了syslinux,从上图也可以看到,这样就免去了手动安装的繁琐,UltraISO不具备此功能。

  第二步,使用BOOTICE设置U盘引导。

  启动BOOTICE。选择U盘,千万别选硬盘啊。。。。然后点“主引导记录”。

  在弹出的界面配置主引导为UltraISOUSB-ZIP+。



  设置完成后关掉这个界面,回到主界面点“分区引导记录”。

  看一下分区引导记录是不是syslinux,不是的话配置成syslinux,一般这步都没问题。为了保险起见还是看看比较好。。。。

  再次回到主界面,点击“分区管理”。

  到此为止,U盘就可以成功的启动了。

  插上U盘,把电脑设置成从USB启动即可。

  另外,如果是由于Linux系统驱动不支持导致的启动失败,暂无解决方案,只能换系统。

  既然本文叫做解决方案,就多说一点,再介绍一种方案。

  简介:

  国内有一款比较流行的移动Linux操作系统puppy,支持中文,界面很漂亮,而且很好的支持多媒体,比如QQ、看电影什么的。更重要的是,兼容性很强。

  制作工具:

  制作U盘启动盘很简单,只需要下边两个工具。

  Puppy LiveUSB:把Puppy系统ISO镜像写入U盘的工具,一键完成,这个工具只能写入Puppy系统,普通的系统要用上边讲的方法。

  custom-puppy.iso:Puppy中文定制版ISO镜像。

  注意事项:

  | 写入过程中一定要关闭杀毒软件,万一被拦截了就不爽了。。。。软件均来自官方,无毒无害,放心使用。

  | 如果启动不成功,找到U盘中的“isolinux.cfg”文件,把这个文件中的“pmedia=cd”改成“pmedia=usbflash”即可。

  | 用PuppyLiveUSB写入时,建议把U盘启动模式设置成HDD。

  本菜鸟水平有限,教程就到这了。

  有问题欢迎和我交流!

  看看U盘是否设置成了活动分区,有A标记的就是活动分区,如果没有的话,点“激活”即可。如果没有设置成活动分区,电脑从U盘启动的时候会无限弹出“Start from USB……”





posted @ 2012-07-30 10:38 顺其自然EVO 阅读(800) | 评论 (0)编辑 收藏

大型票务系统性能测试浅析

  其中,优化项所有内容必须满足,附加项可以不满足,在评测结果中Y代表满足、N代表不满足、Null代表无优化项相关技术。评测结果共分为A、B、C、D、E和U六个级别。具体对应关系如下表所示:

表2 评级标准

  4.2 后端性能测试方法

  测试主要采用商业级别的性能测试工具进行测试,如HP Loadrunner。通过大规模模拟实际用户的操作行为,测试核心售票系统中注册、浏览、座位选择、支付等关键业务的响应时间和服务器实时处理能力,重点关注CPU、内存、I/O等信息,为操作系统、中间件和数据库以及服务器的性能优化和调整提供数据依据。

  通常情况下,数据中心中用于支撑售票业务的服务器多达几百台,通过软件在测试中进行监控更容易实现,如UC Berkeley的开源集群监视软件Ganglia。Ganglia的核心包含gmond、gmetad以及一个Web前端,通过自动解析linux操作系统proc目录下的文件来获取操作系统的主要性能指标。Ganglia带来的系统负载非常少,几乎不会影响被监控系统性能。对于中间件和数据库等基础软件,可采用其自带的监视器或命令来获取性能指标。

  在测试场景设计中,应考虑准确模拟混合业务的并发操作,以及过载访问的情况,可借鉴下表中的思路进行测试:

表3后端性能测试场景

  通过测试考察运行环境的抗压能力,在成本和风险可接受范围内对整个运行环境进行合理优化,提高核心售票系统的处理能力。总的来说,高效的核心售票系统在上线前达到以下要求:

  A、核心业务模块中无明显效率低下的模块

  B、多个数据中心间实现了良好的负载均衡,整个运行环境中不存在明显的服务器资源消耗过度的情况

  C、整个运行环境的网络承受负载的能力良好,各银行支付网点进行了合理的组网规划,网站与支付系统的流量实现良好分离

  D、在正常和过载情况下,系统的定单数量/小时指标在合理范围内,代理服务器、交易服务器以及数据库服务器的资源消耗合理

  5、总结

  通过分析大型票务系统的访问特点和规律,提出了大型票务系统的性能测试策略和方法,该方法经具备普遍的合理性和较强的操作性,但是该方法还有待在更多大型票务系统性能测试中进行应用和完善。

  1、引言

 

  随着互联网的普及,越来越多的传统业务转移到了网络进行。但是由于大型票务系统受众访问高峰、持续性等特殊性,使得传统的性能测试策略并不适合该类系统的测试。例如北京奥运会票务系统和伦敦奥运会票务系统的在运营阶段不断的瘫痪、修复、上线运营的循环中,大型票务系统的性能测试显得尤为重要。

  2、关键技术

  2.1 Web应用响应时间

  其中C1是用户发请求前在客户端完成预处理阶段;C2是客户端接收到服务器返响应后,对处理结果展现的阶段;A1是WEB Server或者APP Server对请求进行处理阶段;A2是数据库服务器对请求进行处理阶段;A3是WEB Server或者APP Server对DB Server 返回结果进行处理的阶段;N1是请求由客户端发出并达到Web/App Server 的阶段;N2是如果需要进行数据库相关的操作,由Web/App Server 将请求发送至DB Server 阶段;N3是DB Server 完成处理并将结果返回Web/App Server 阶段;N4是Web/App Server 完成处理并将结果返回给客户端阶段。

  从用户的角度来看,响应时间=(C1+C2)+(A1+A2+A3)+(N1+N2+N3+N4);但是从系统的角度来看,响应时间只包括(A1+A2+A3)+(N1+N2+N3+N4)。

  2.2 前端性能

  所谓前端是相对于后端而言的,后端是用户分析用户请求、执行数据查询并对结果进行组织,形成浏览器可以完全呈现的内容;前端是负责将后端生成的内容通过网络发送给客户段浏览器,展现后端请求处理结果的。前端开发技术主要有(X)HTML/CSS/JavaScript/DOM/Flash等各种Web技术。前端性能主要是在客户端通过浏览器发送了一个请求,除去后端处理消耗的时间的浏览器展示后端访问请求的时间。也就是图1中C1+C2+N1+N2阶段,其中主要衡量接受到的数据的大小、接受响应数据的碎片程度等方面。

  在交互式应用中,响应时间大于15秒,对于大多数人是无法容忍的,相应时间大于4秒时,人的短期记忆会受到影响,工作的连续性就会被破坏。对于一个用户的每次访问来说,80%的响应时间消耗在了前端。而且对于提升网站的访问速度而言,如果通过后端优化将响应速度提升一赔,那么整体的响应时间仅仅只能减少5%到10%;而如果通过优化前端将响应时间减少一半,则整体响应时间至少减少40%到45%。

  2.3 后端性能

  后端性能是指web Server或者APP Server在收到客户端响应后,对其进行处理,通过数据库数据返回结果,经过处理将返回响应发送给客户端的过程。也就是图1中逻辑业务流经过A1、A2、A3、N2、N3的过程中对各个阶段的响应时间、服务器资源利用率、网络负载等方面的衡量。

  性能度量就是通过定义一系列可以反映程序性能的指标,并从程序实际运行的数据中获得度量结果的过程。性能度量的结果可以用于评估系统的性能好坏、分析性能瓶颈和改进系统性能等。针对Web应用性能,有两种常用度量指标:度量资源使用情况,度量响应时间。

  3、大型票务系统性能评价方法

  3.1 前段性能评价方法

  对于大型票务系统而言,前端性能的优化主要是为了加快响应结果在客户端的响应速度,这样能够避免用户误以为无响应而反复的刷新造成服务器端压力。在评测过程中主要从如下几个方面进行考虑:

  A、CSS文件或者代码至于顶部

  B、JavaScript脚本文件或者代码至于文件的底部

  C、CSS文件或者代码中无CSS表达式

  D、JavaScript脚本文件或者代码中无重复脚本

  E、移除无用的CSS

  F、对JavaScript脚本进行了精简

  G、精简CSS脚本

  H、外链JavaScript脚本并且合并多个javascript脚本文件

  I、外链CSS并且合并多个CSS文件

  J、应用图片地图或者CSS Sprites

  K、应用Expires头

  L、无重定向

  M、应用GZip压缩

  N、配置ETag

  在上述的评测内容中主要包括了两方面,其一是脚本文件的优化,资源文件的优化和CSS文件的优化三大方面。服务器文件优化就是降低在客户端访问服务器端时,除去HTML文档外其他所有内容的物理大小,减小传输时间和加载时间。其二是依据HTTP协议特性,通过配置中间件、修改源程序等操作进行的优化。在完成上述14项技术评价指标后,仍有如下4项附加项需要考虑:

  O、应用Ajax缓存

  P、应用CDN

  Q、混淆JavaScript

  R、页面DNS查找最小化

  由于上述四项附加是由相对复杂,风险较大、实现成本较高技术决定的,因此附加项的满足条件就视项目的投入成本情况而定,并不一定要完全满足。

  3.2 后端性能评价方法

  由于票务系统通常在短时间内进行集中售票,存在短时间内访问量陡增、售票期间持续高压力以及与银行支付业务紧密相关等特点,因此保证大压力下的核心售票系统能够提供高性能的服务水平,将直接影响终端用户的购票体验。糟糕的用户体验包括:

  A、超长的等待时间

  B、页面无响应

  C、支付失败

  从性能测试角度看,整个运行环境在承受来自世界各地高强度的并发访问过程中,可能存在以下问题:

  A、网络拥塞导致页面请求响应缓慢或超时报错

  B、页面刷新机制导致在用户锁票、坐席分配以及支付阶段时,用户等待时间增长,订单处理速度急剧下降

  C、大量的金额统计以及票务更新导致交易服务器和后台数据库繁忙

  D、大量的VISA卡支付操作导致支付网点服务器繁忙,处理效率底下

  为准确模拟实际情况,需将历史经验同本次售票方案相结合,预计并发访问人数、网点规模、数据规模等指标,在保证数据中心实现良好数据共享的情况下,测试的重点应涉及一下几个方面:

  A、网络负载

  B、多个数据中心间的负载均衡

  C、峰值期间每小时定单数量

  D、代理服务器、交易服务器、数据库服务器的资源消耗情况

  E、长时间高效服务的能力

  4、大型票务系统性能测试方法

  4.1 前段性能测试方法

  前端性能主要的评测工具有Google的Page Speed和Yahoo的YSlow。Google开发团队针对SteveSounder网页性能最优方法,成功地推出一款基于Firefox/Firebug的开发类插件Page Speed,旨在帮助开发人员分析网站性能存在的主要问题,并有针对性地提出优化改进意见。它支持的操作系统为Linux、Mac、Windows。在此之前, Google内部已经广泛使用PageSpeed优化网页前端性能。YSlow是有雅虎公司开发的免费前端性能检测工具。YSlow通过检测网页上的所有组件,包括JavaScript动态创建的组件,分析网页的前端性能。同时,YSlow依据前端性能的分析结果提出改进建议。

  在应用上述两款任意一款给你工具进行测试后,将测试结果对应的填入下面的前段性能评测记录表中。

表1 前段性能评测记录表


  其中,优化项所有内容必须满足,附加项可以不满足,在评测结果中Y代表满足、N代表不满足、Null代表无优化项相关技术。评测结果共分为A、B、C、D、E和U六个级别。具体对应关系如下表所示:

表2 评级标准

  4.2 后端性能测试方法

  测试主要采用商业级别的性能测试工具进行测试,如HP Loadrunner。通过大规模模拟实际用户的操作行为,测试核心售票系统中注册、浏览、座位选择、支付等关键业务的响应时间和服务器实时处理能力,重点关注CPU、内存、I/O等信息,为操作系统、中间件和数据库以及服务器的性能优化和调整提供数据依据。

  通常情况下,数据中心中用于支撑售票业务的服务器多达几百台,通过软件在测试中进行监控更容易实现,如UC Berkeley的开源集群监视软件Ganglia。Ganglia的核心包含gmond、gmetad以及一个Web前端,通过自动解析linux操作系统proc目录下的文件来获取操作系统的主要性能指标。Ganglia带来的系统负载非常少,几乎不会影响被监控系统性能。对于中间件和数据库等基础软件,可采用其自带的监视器或命令来获取性能指标。

  在测试场景设计中,应考虑准确模拟混合业务的并发操作,以及过载访问的情况,可借鉴下表中的思路进行测试:

表3后端性能测试场景

  通过测试考察运行环境的抗压能力,在成本和风险可接受范围内对整个运行环境进行合理优化,提高核心售票系统的处理能力。总的来说,高效的核心售票系统在上线前达到以下要求:

  A、核心业务模块中无明显效率低下的模块

  B、多个数据中心间实现了良好的负载均衡,整个运行环境中不存在明显的服务器资源消耗过度的情况

  C、整个运行环境的网络承受负载的能力良好,各银行支付网点进行了合理的组网规划,网站与支付系统的流量实现良好分离

  D、在正常和过载情况下,系统的定单数量/小时指标在合理范围内,代理服务器、交易服务器以及数据库服务器的资源消耗合理

  5、总结

  通过分析大型票务系统的访问特点和规律,提出了大型票务系统的性能测试策略和方法,该方法经具备普遍的合理性和较强的操作性,但是该方法还有待在更多大型票务系统性能测试中进行应用和完善。

 

 

posted @ 2012-07-30 10:36 顺其自然EVO 阅读(270) | 评论 (0)编辑 收藏

接口自动化和GUI自动化工具优劣比较

 首先感谢公司,只来了一年,我接触了两种自动化工具,一种是测试接口的,一种是直接从GUI下发的。翻开目前存在的测试资料,能够被企业级应用的自动化工具类型也无非就这两种方式,深入接触了之后,觉得两种方式各有千秋,也各自能够完成自己的使命。当然了,这两种工具公司内部开发,也只能在内部平台上使用。不过没什么,学习了方法和过程,就向看惯了五岳、黄山一样。

  接口测试工具:首先这种方式测试人员自己就可以编写工具,开发人员有一套编码规范,在设计阶段就会提供北向或者南向接口,每个迭代会发布接口属性列表,告诉前端页面开发,我们的这个怎么调用。一般项目比较大一点时,前期都是需要先将后台稳定,过两个迭代才将页面集成进来。可是在没有页面的情况下,测试人员不能根据手工测试,需要自己给接口传参数来测试结果。测试人员在用例撰写完成后,就需要编写脚本了,因为在没有页面的情况下,我们的测试执行就全靠它了。

  简单的举下例子,我们的增删改查对象基本上是每个系统都会有的。那么我们如何去测试这个接口?其实我们在写自动化脚本的时候需要考虑的东西很多,不过核心的只有那么几点,一是要稳定,二是要可重用。我们的脚本和代码一样,我们在写增加对象的时候需要编写一个逻辑,逻辑中调用开发提供的接口,参数值在我们写具体用例时给予传入,例如边界值等等。整个增加功能我们只需要一个逻辑就可以搞定,节省了时间,脚本还不容易出错,后期即使接口变了,我们只需要改一下逻辑,所有的脚本还是可以正常运行了。这个和编码规范一样,通用的东西写在一个方法里,方便扩展和修改。可以想象一下把restclient做成可以连跑的工具。

  下面简单谈谈这种接口测试的适用范围和优势,接口测试更好的适应在中间件开发团队以及更页面弱相关的项目中,首先我们不需要关心页面实现是个什么样子,我们只提供接口,我们关心的接口能否正确的接纳信息并给予正确的返回,其实我们现在还没有页面来调用我们,连我们自己都不知道页面长什么样子,但是我们要保证页面集成之后我们的接口是没有问题的。对于测试人员的角度来看,这种工具有很多好处,一是逻辑抽象化容易,其基本上和写单元测试用例类型,只不过测试对象不是一个函数或者类,是一个功能点罢了,二是这种工具写好的脚本稳定性很高,不受页面变化的影响,后台接口的变更频率比前端页面小的多。

  话又说回来这种工具也是有局限性的,它不关注页面,目前我们市面上能够只提供接口或者API来赚钱的公司毕竟少数,大家还都是做产品的出身,毕竟东西是要拿出去卖钱的,没有页面你让客户看什么?而且这种工具引进项目之后,测试人员没有端到端的打通过产品,还是需要手工在页面上操作,这个工具也不能发现UI和接口未对齐的地方的缺陷。

  那么下面的一种工具就能够满足要求了,那就是GUI的自动化工具,它能直接模拟测试人员触发功能按钮,端到端的测试交付的功能,我们常见的QTP也是属于这一类的。不过这种自动化工具也是有其长处和短处的,具体如何取舍呢?

  下面我们来谈谈时下应用最多的自动化类型工具--GUI类型的自动化工具。

  图形用户接口类型的工具,顾名思义,是从页面直接触发命令,完成测试人员手动执行的步骤。相当与一个不需要休息不需要拿薪水的测试人员,每天孜孜不倦的干着重复的事情,却没有任何抱怨一样。不管是我们的QTP还是公司内部自己开发的自动化工具,无非就是先寻找页面上的ID信息或者脚本定位信息或者XPath信息,定位到某一个按钮或者输入框,点击或者输入测试内容,提交后校验页面能够给予的返回信息,不同的脚本传递不同的参数或者点击不同的按钮,校验最后的输出也好,校验页面的错误提示信息也罢,都是以工具替代人工来执行,例如我们可以编写某个系统的门槛用例、冒烟用例的自动化脚本,在开发人员使用自动编译工具生成最新版本的时候,我们自动获取最新版本执行安装,之后执行自动化脚本,在夜里、第一时间掌握版本的实际信息,是否能够转测试成功,是否存在主干流程上不通的情况,如果附带录像回放工具,那这个工具还能帮助开发人员还原当时错误的情况让开发人员“穿越”到之前的情况查看页面出现的BUG,一举多得。

  既然这种工具这么好,那我们赶紧开展哦~~~

  熟练的测试人员都知道这种工具有个很不好的弱点。这种工具过分依赖页面,可以说页面一旦有个风吹草动这个工具生成的脚本就需要更改;一般情况下展开测试自动化都是在项目的后期,基本功能已经无大碍,连续测试过几轮都没有问题,页面也渐渐趋于稳定。所以,采用这种形式的自动化时,测试人员需要做的首件事情就是和开发的SE确定页面和页面控件的ID。其实这些东西我就在这里说说,这个东西实现起来,推动起来是多么难最后还是要修改,被这个脚本折腾吃过苦头的事还历历在目。其实项目开始的时候,领导一声令下要使用GUI工具自动化时就想到这一点,结果就是迭代一推动到迭代二,在推到迭代四,一直到最后要自动化了,下了最后通牒时才给出一个结果。不是开发的SE故意敷衍你,就算迭代一他费好大的劲搞好了又能怎么样呢?众所周知页面这个东西,都是仁者见仁智者见智,更不用资料和UCD的那一帮子整天觉得这个不爽那个不顺眼的,我不是诋毁他们哈,只是觉得页面这个东西,定的太死后面吃亏的是我们自己,包括测试和开发。即便如此,我们实现了自动化,还是给修改带来了很大的工作量。很难保证开发在某一个迭代页面没有动一点东西,只能祈求不要动主干或者不要添加什么ID或者打乱原来的XPath(有些东西开发是没办法给出ID的)。

  再者这个工具有一个弱点,分析不了逻辑,如果一个页面需要逻辑展示或者时下最流行的图形操作,这个自动化真是鞭长莫及,这个分析能够根本不能胜任的,测试人员你还是老老实实的自己构造条件手工测试吧!

  看到了吧,过分依赖页面的自动化工具的下场了吧。

  但是我们不能因噎废食,自动化工具如果不能提高我们的测试效率,那我们凭什么花那么大力气去定规范和写脚本?自动化工具,不管是接口的还是GUI的,其能够存在都是有其道理的。一般情况下接口是不会随便动的开发人员也害怕领导找他的麻烦,改动接口还得联调,又是一个大工作量,所有接口自动化工具生成的脚本稳定,可执行程度高,基本不会出错,如果里面存在缺陷可以很大程度上能够校验出来,缺点是不能结合页面不知道最后集成后会有什么问题;GUI类型的工具强大的地方在端到端的验证,能够像人一样操作被测系统,给测试人员最好的结论,缺点就是维护成本高,易变更(这一点高手测试人员可以尽量减少)。此处比较罗列,想让使用自动化的项目组有个参考,看哪一点舍弃损失最少或者采用哪种收益和成本最大。其实说了这么多,其实自动化工具再好也替代不了人,自动化脚本跑动的脚本依赖用例,用例设计依赖测试人员,用例才是测试根本!

  测试,你做好设计准备了吗?

posted @ 2012-07-30 10:05 顺其自然EVO 阅读(806) | 评论 (1)编辑 收藏

迈出单元测试的第一步

 单元测试不仅是软件行业的最佳实践,在敏捷方法的推动下,它也成为了可持续软件生产的支柱。根据最新的年度敏捷调查,70%的参与者会对他们的代码进行单元测试。

  单元测试和其他敏捷实践密切相关,所以开始编写测试是组织向敏捷转型的踏脚石。道路漫长,但值得去做。我将在本文介绍符合要求的小技巧,以及在开发周期里进行单元测试的步骤。

  有效的单元测试默认要能自动化。没有自动化,生产力就会下降。没有自动化,单元测试的习惯也不会持续太久。依靠手工测试(由测试人员或开发人员完成)并不能持续太长时间;在有压力的情况下,没人会记得去运行所有的测试,或者去覆盖所有的场景。自动化是我们的朋友,所有的单元测试框架都支持自动化,而且集成了其他自动化系统。

  单元测试对现代开发来说至关重要

  有代码相关的测试,我们就有一个天然的安全保障。我们修改的代码要是带来了什么问题,测试会告诉我们。这个安全保障越健全,我们对代码正常运行的信心就越大,对按需修改代码的能力也就越有信心。

  和其他类型的测试相比,单元测试的主要优点是反馈迅速。在几秒钟内运行数百个成套的测试,这对开发流程很有帮助。我们会形成“添加一些代码,添加测试,测试运行通过,前进”的节奏。小步前进、确保一切正常也意味着调试时间会大大减少。测试能提高生产力也就不足为奇了——在Bug上少花时间,把更多的时间用到新功能的推出上。

  依赖关系的壁垒

  给新建项目添加测试相当容易——毕竟代码不会阻碍测试。不过这种情况绝对不常见。大多数人都是在处理遗留代码,这些代码不太容易测试,有时候甚至运行不起来——它需要的数据或配置可能只存在于生产服务器上。我们或许要为不同的场景创建不同的设置,这也许会花费过多的精力。在很多情况下,我们可能还会为了测试修改代码。这让人无法理解:我们编写测试就是为了能有修改代码的信心,还没有测试又该如何去稳妥地修改代码呢?

  代码可测性是语言和工具的功能。大家认为Ruby等动态语言是可测的。对于测试的内部代码,我们可以改变其依赖关系的行为,而不用修改生产代码。C#或Java等静态类型语言则不太容易去测试。

  下面有个例子:一个C#的过期检查方法,检查是否超过了特定日期:

public class ExpirationChecker
{
    private readonly DateTime expirationDate = new DateTime(2012, 1, 1);

    public bool IsExpired()
    {

        if (DateTime.Now > expirationDate)
        {
            return true;
        }
        return false;
    }
}

  在这个例子里,IsExpired方法的DateTime属性对测试运行时间有强依赖。Now返回的是实际时间。这个方法有两种情况,它会根据日期返回不同的值。修改计算机时间是绝对不行的,因为我们要在任何时候到任何计算机上去测试场景,并且不能带来任何副作用。

  要测试到两种情况,一种可能的解决方案是修改代码。比如说,我们可以把代码修改成:

public bool IsExpired(DateTime now)
{
    if (now > expirationDate)
    {
        return true;
    }
    return false;
}

  这样,测试可以注入不同、可控的DateTime值,而不用在生产代码里写定一个值。我们要是不能修改代码,可以利用Typemock Isolator等Mocking框架,模拟静态属性和方法。针对先前的代码,测试可以写成:

[TestMethod]
public void IsExpired_BeforeExpirationDate_ReturnFalse()
{
    Isolate.WhenCalled(() => DateTime.Now)
        .WillReturn(new DateTime(2000, 1, 1));

    ExpirationChecker checker = new ExpirationChecker();
    var result = checker.IsExpired();

    Assert.IsFalse(result);
}

  现有的遗留代码不能轻易修改,因为我们没有针对它的测试。开始测试遗留代码之后,我们就能明白:代码越丑陋,测试越困难。工具可以减轻一些痛苦,但我们要努力去构建安全的环境。

  依赖关系并不是唯一的内容……

  我们很快会遇到的另一个问题是测试维护:测试和被测试代码耦合在一起。有耦合关系,修改生产代码就有可能破坏测试。要是代码修改引起测试失败,我们就需要回去解决这些问题。很多开发人员害怕维护两个代码库,这种恐惧甚至会让他们干脆不进行单元测试。真正的维护工作既取决于工具,也取决于技巧。

  编写好的测试是通过实践获得的技能。编写的测试越多,我们就越精于此,同时会提升测试质量,维护也越来越少。有了测试,我们就有机会重构代码,这反过来又会让测试更简洁、更易读、更健壮。

  工具对实践的难易程度有极大的影响。在基础层,我们需要一个测试框架和一个Mocking框架。在.Net领域,两种框架的选择都很丰富。

  编写第一个测试的准则

  开始的时候,我们通常会试用不同的工具,来理解他们的工作原理。我们往往不会在实际的工作代码上开始编写测试。但很快就要给代码编写真正的测试。有一些小提示届时会有用:

  ● 从哪里开始:一般来说,我们编写测试是针对工作代码的,无论代码是Bug修复还是新功能。对Bug修复来说,编写的测试要检查修复。对功能来说,测试应检查正确的行为。

  ● 支架:以我们掌握的知识来看,明智的做法是先添加能确保当前实现运行的测试。添加新的代码之前先写测试,因为我们希望在修改现有代码之前,能有安全的保障。这些测试被称为“特征测试”,这个术语来自Michael Feathers编写的《修改代码的艺术》。

  ● 命名:测试最重要的属性是它的名字。我们一般不会去看运行通过的测试。但当它失败时,我们看的就是它的名字。所以挑一个好名字,描述出场景和代码的预期结果。好名字还有助于我们定位测试里的Bug。

  ● 评审:为了增加测试成功通过的机会,编写第一个测试时我们应该和同事结对。两个人都能从实践中学习,而且我们还能立即评审测试。最好对所测的内容、测试的名称达成共识,因为这会成为团队其他人员的基本模板。

  ● AAA:现代测试的结构符合AAA模式——Arrange(测试设置)、Act(调用测试里的代码)、Assert(测试通过的标准)。如果我们使用测试驱动开发(TDD),我们要先编写完整的测试,然后再添加代码。对遗留代码来说,我们可能需要换一种方式。一旦我们有一个场景和名称需要测试,那先编写Act和Assert部分。我们要不停构建Arrange部分,因为对需要准备或仿造的依赖关系,我们知道的要更多一些。然后继续这么做,直到有一个测试能够通过。

  ● 重构:一旦准备好了测试,我们就可以重构代码了。重构和测试都是后天获得的技能。我们不仅要重构被测试代码,也要重构测试本身。但DRY(不要重复自己)原则不适用于测试。测试失败时,我们希望尽快修复问题,所有的测试代码最好在一个地方,而不是分散在不同的文件里。

  ● 可读性:测试应该是可读的,最好是人类可读。和搭档评审测试代码,看他能否理解测试的目的。评审其他测试,看看它们的名称和内容怎样与相邻的测试区分开来。一旦测试失败,就需要修复它们,最好还是在运行失败之前评审它们。

  ● 组织:一旦我们有了更多的测试,组织就有了用武之地。测试可以在很多方面有所不同,但最明显的一个就是如何快速运行。有些测试可能在毫秒内运行完,而有些则需要数秒或好几分钟。和工作一样,我们都希望得到最快的反馈。这就是前面谈到的怎么按一定的节奏去进行。要做到这一点,你应该把测试划分一下,把快的测试和慢的测试分开运行。这能手工(努力)去做,但在.NET领域,Typemock Isolator有一个运行器,能自动按运行速度分离。

  总结

  迈出单元测试的第一步是很有挑战的。体验依赖的东西很多——语言、工具、现有代码、依赖关系和技能。只要稍稍思考,进行大量训练和实践,你就能渐入测试的佳境。













posted @ 2012-07-30 09:59 顺其自然EVO 阅读(195) | 评论 (0)编辑 收藏

未雨绸缪:从软件测试到质量保证

 【摘要】我们都遇到过这样的情况:每次系统上线,几十人,甚至几百人的测试和开发团队都要提心吊胆的经过若干个不眠之夜。从高层领导到技术人员、测试人员不停的想象着各种可能遇到的情况…

  2005年11月1日,日本东京证券交易所股票交易系统发生大规模系统故障,导致所有股票交易全面告停,短短2个小时造成了上千亿的损失。经查明,故障的“元凶”是当年10月为增强系统处理能力而更新的交易程序存在缺陷。

  设想一下,当一名大银行老总,正在焦头烂额地组织本行的IT系统建设工作,突然看到这样的一条消息,会有什么样的感觉?当然首先会想到,如果自己新上线的系统也出现类似的故障,后果同样是不堪设想的。所以,一个很自然的想法就会冒出来:对即将上线或已经在运营中的IT系统进行一次全面体检,保证系统健康上岗!

  质量危机

  现实中,因IT系统质量存在问题而导致的这样或那样的事故,在很多大型的金融、电信企业中时有发生。

  我们都遇到过这样的情况:每次系统上线,几十人,甚至几百人的测试和开发团队都要提心吊胆的经过若干个不眠之夜。从高层领导到技术人员、测试人员不停的想象着各种可能遇到的情况:服务能否正常运转;功能会不会存在问题;速度能否满足用户要求;移植过来的数据正确性如何,是否会影响业务导致客户投诉……总算熬到安全上线,ATM机系统故障、Pose消费终端没有响应、核心业务系统故障致使业务暂停等等一系列问题又会不时出现,造成巨大的经济损失和恶劣的社会影响。质量问题已经成为企业IT系统主管心中难言的痛。

  在激烈的市场竞争中,如果能在竞争对手前推出新的业务,就能在竞争中争取有利的位置。兵贵神速,新业务的推出速度越快越好。但同时,如果新的业务没有一个稳定可靠的系统支撑的话,那么,轻则面临大量的直接经济损失,包括对客户的损失的赔偿以及修正系统错误的开销,重则损失大量的开展新业务,占领市场高度的时机,直至声誉下降,大量的客户流失,一败涂地。

  避免IT系统质量问题带来的风险,降低故障成本已经刻不容缓。然而,中国质量测试行业才刚刚起步,很多企业采用的测试方法和技术简单而低效,如:组织大批的业务员,把以前做过的业务拿出来,在新的系统上重新跑一遍,发现错误和隐患后,再和开发部门联系进行整改;当有系统变动就再组织大规模人力重复上面的工作,如此反复。然而,这样的方法并不能解决实质性问题,只能头痛医头,脚痛医脚,而且受很多因素限制,系统的质量风险很难控制。一旦遇到测试人员业务不熟;人员长期反复工作产生疲劳倦怠情绪;或是系统有了较大变动,而第二天又要保证上线等等诸多状况时,IT系统的质量风险会陷入不可控的境地。同时,大型金融,电信企业的IT系统又是错综复杂的。以下面的建设银行总行IT系统为例。

  建行已投产运营的项目有十几个,包括银行渠道平台、网上银行、综合产品管理、客户关系管理、信息总线项目等等;后续建设的项目,如企业资源计划(ERP)、数据仓库、信贷业务系统等约十多个。这些项目大都采用了国际国内最先进的技术,技术构成复杂而多样性;而且很多项目在业务、技术架构、物理部署和数据上都有很强的关联,构成了一个庞大的、复杂的IT系统群集。未投产的项目需要进行跨系统的集成测试和非功能性测试,并组织实施投产上线;已投产的项目要进行系统调优和未来的系统发展分析预测;同时,项目还涉及到与大约20个总行级系统的联调测试。这样规模的IT系统质量已经不是上述的简单测试方法能够保证的。

  这就需要专业的质量测试团队来协助企业进行IT系统全面的质量保证和测试工作,从而降低质量风险,使IT系统更好的为业务提供支撑服务。

  专业服务

  要解决质量问题,就必须把IT系统的质量测试工作摆到重要位置。那么采用何种方式保证质量?

  如果客户自己来做测评,虽然也能发现一些问题,但局限于测评方面的专业知识和行业经验,不利于问题在开发方面的追踪,协助开发人员进行修正。如果开发人员自己来做的话,不仅缺乏丰富的测试经验,更重要的是,由于开发工作通常划分比较细致,各部门各司其职,不利于从大局上对软件的质量进行把握。而且,如果在开发的问题上双方出现分歧的话,开发部门自己的质量测试报告的效力就会打折扣。因此,对于大型IT项目而言,最好的办法就是引入专业的第三方质量测试机构,来保证过程和结果的客观性和公正性。而且从测试技术和解决方案上,专业的质量测试机构也更先进和全面,可以提供更为可靠的质量保证。

  在中国,专业的软件测试服务目前尚处于起步阶段,能提供大型项目质量测试服务的机构更是少之又少。专业化的质量测试服务机构,必须具备下面三个条件:1、有先进的、完整的软件质量测试管理理念;2、结合先进的测试技术和工具,有一套完整的实用的质量测试解决方案;3、拥有一批行业经验丰富,测试水平高超,项目管理能力很强的咨询实施团队。

  具备这三个条件的神州数码质量测试事业部,敏锐地看到了这个市场商机。事业部前身是神州数码ITS项目管理中心。多年的项目监理、质量保障和测试管理经验,让其具备了深厚的专业功底,并建立了基于IT系统全生命周期的质量测试解决方案。顺应市场的呼唤,2004年初,事业部正式成立开始走入质量测试领域,为大型应用系统提供来自第三方专业的咨询实施服务。

  建设银行总行,十分注重自身的IT系统质量,其信息化水平在业内也属于领先地位。他们采用的策略是针对重点系统进行性能测试,验证各种系统在不同使用条件和压力下的性能表现,跟据性能测试进行系统性能优化,包括对用户行为、硬件和软件参数配置、数据库和代码的优化。对软件体系结构方面的性能基准测试和咨询。从而确保系统在上线前后都无质量问题。此外,在项目前期通过实施事业部提供的设备选型方案和技术架构验证方案,采用科学化的技术手段和客观的数字分析,来采购最适合的设备和最适宜业务特点的架构,避免了资金的浪费和后期的开发风险。

  事实证明,质量测试是企业IT系统建设健康运转的必备手段。它需要由独立在客户与开发人员之外的专业机构,严格按照客户的质量需求,对IT系统的质量进行全生命周期的监控。

  如何判断IT系统质量是否存在问题?一般的评判标准包含以下几个方面:1、功能,软件的规范和满足用户需求的程度;2、性能,即软件的运行速度和消耗的资源;3、可靠性和安全性,在规定的时间和条件下,软件所能维持其性能水平的程度;4、友好度,软件的学习、理解和使用的方便程度;5、可维护性,当运行条件或者软件本身发生故障的时候,对其进行修正的困难程度。

  系统能不能用,是用户关心首要问题。这就需要功能测试,原则就是不能出错。系统是一个有机的整体,动一指而牵全身。所以,一个细微功能的改变都有可能对系统的其它部分造成重大影响。比如,银行最常见的业务是存、取款,如果因为新的功能加入,造成存、取款业务出现错误,甚至无法完成的话,那么就需要对新加入的功能模块进行修正。针对大量的重复性功能测试,可以采用自动化回归测试方案,每天设定程序自动执行,从而减低人力成本,提供测试效率。

  解决了系统是否能用问题,好不好用就提到了重要位置。也就是性能测试。如果系统不能在规定的时间内做出正确响应的话,就是根本无法投入使用的,再强的功能也只能是摆设。比如,春节时电话和短信的数据量会有一个爆炸性的增长。如果系统性能不过关的话,就会因为不堪重负宣布罢工,这是电信供应商和消费者都不能接受的。性能测试,就是要找出对系统性能起着瓶颈式影响的各种因素并对其进行优化。

  功能再强,性能再好,但如果系统三天两头出故障,同样也是不能接受的,所以需要进行可靠性和安全性方面的测评。

  而友好度和可维护性,都可以通过功能测试和针对性地专项测试来实现。

  总之,IT系统质量的几个因素相互关联。比如,功能的提升,可能会带来可靠性和性能方面的问题。所以,质量测试工作必须从全局的高度出发,平衡各因素的影响,从而系统质量能够满足用户需求。

  针对这点,神州数码质量测试事业部与世界上著名的测试工具供应商,美国Mercury公司在建立白金级战略合作伙伴关系。双方建立了研发级实验室,由Mercury公司提供培训,事业部也依靠强大的研发能力为测试工具开发更为实用的功能插件。同时,作为微软在国内的四个战略合作伙伴之一,在测试外包、行业应用测试、微软平台的开发等领域广泛合作。致力于吸取国外先进质量测试理念和技术,更好的为行业客户质量保证工作尽自己的一份力量。

  从被动测试到主动管理

  然而,测试终究是被动的查漏补缺,没能从根本上解决质量问题,实现标本兼治。如果从IT系统生命周期的源头做起,从过程上做起必然能大大提高软件开发与应用的效率,这就是质量管理。即是从客户的需求开始,主动对IT系统生命周期的产生过程进行质量控制。

  根据业界著名的“V”字型模型,每一项测试工作都与开发的经过是一一对应的。所以需要从需求开始,结合软件质量5个方面的层次需求,按照需求、设计、详设、开发、测试的流程,对软件的质量进行全生命周期的质量管理,这样,才可能把隐患减小到比较低的程度。比如需求,神码质量测试事业部总经理单军说“其实,很多时候,像金融、电信类的大型企业,他们自己困惑,为什么有的测试没有效果?原因是,他们对自己的需求没有明确。由于质量测试的依据是客户的业务和技术需求。需求不准确的话,测试肯定会出问题。所以,我们提出了一个测试需求的概念。”

  建设银行总行,在质量测试事业部的助力下,建立起一套有效的测试体系和管理流程,整合业界最先进的测试管理工具,从测试需求的管理、测试分析设计、测试案例的设计、测试执行、缺陷的管理和报告,确保使每一个需求,都保障得到有效的测试,每一次变更,都保障得到测试的覆盖。对于自身大型IT项目,采用了事业部的测试管理、质量保证方案;创新性地应用了项目群架构关联密集型的测试管理思路,制定了多主线并发测试管理流程,以及目标系统驱动的管理模式,在实际运作中取得了明显成效,有效的控制了项目质量风险,使项目开发更加有的放矢,成果显著。

  所以,将质量管理的理念渗透到IT系统的整个生命周期,是确保系统开发高效、质量可靠的有效保证。

  光明的蓝海

  经过严格的质量管理,苛刻的测试,拿到像神码质量测试事业部这样专业机构的质量测试报告后,也就意味着IT系统在很大程度上是健康的。也许有的人会觉得事业部有今天的成就已经很不错,但事业部这支年轻团队的目标更长远、更靠近客户“金融、电信等高端行业的质量测试业务个性很强,满足客户个性化的质量测试需求,提供更完善的、满足整个IT系统生命周期的质量测试服务,才是我们的目标。”总经理单军说,“我们还要不断努力,用更先进解决方案和技术,更贴心的服务为客户创造最大化的价值,共同开创一片光明的蓝海!”

  “中国的软件开发工作,在测试和质量管理的方面,投入是很低的,这个数据,在国外是30%—50%,要害部门的投入甚至达到了开发费用3—5倍。我们要通过专业化的服务,不断的提升中国企业质量测试意识,真正的为更多的客户提供帮助。”

  路漫漫其修远兮,吾将上下而求索!



posted @ 2012-07-30 09:45 顺其自然EVO 阅读(277) | 评论 (0)编辑 收藏

我的软件测试之旅:(2)转变——作为专职测试人员

  后来我被直接派驻客户(诺基亚网络杭州3G研发中心,现诺基亚西门子网络杭州研发中心)现场,再后来被直接买下,成为了诺基亚的员工。也正是从派驻诺基亚那时起,我开始了自己作为专职测试人员的旅程。但编程这个活动一直都伴随着我,直到现在,这也是我从来都不认为开发、测试有着很清晰的界限的原因,欲知详情请继续往下看。

  当时我们两家公司合作已经有一段时间,已经有数十位工程师在诺基亚干活,我们这一批人是专门为研发中心某个产品线的测试部门补充人力的。团队管理非常简单,我们自己公司的事务由自己的外包经理或者叫协作者经理(Collaboration Manager)管理,当然,在我们这批人和经理之间还有小组长(Team Leader)。而从做事情做项目的角度呢,我们则直接由诺基亚的项目经理来负责管理,也即由他们来分配任务、确定时间表等各种事务。

  该产品线的结构应该属于比较常见的一种,分为几个开发部门和一个测试部门,支持型的部门还有质量管理部和产品管理部、项目集群(Program)管理部等等。使用的是自己独特的开发模式,类似于瀑布模型,也即分阶段、基于文档的开发模式。一个产品的开发会被分割为多个项目集群,而后项目集群再分作多个项目,每一个项目又分割为多个子项目。通常一个子项目也即是某个或某些模块的开发任务,或者测试任务,测试和开发是独立分开进行的子项目。测试项目要等待整体的开发完成之后才开始。

  刚到诺基亚时,我颇为感慨,果然是大公司啊,真是有风范,的确很有人文关怀的感觉,我们所担心的事情都有人考虑到。当时,诺基亚的新员工都要先参加总长度两个月的入职培训,包括从诺基亚介绍、价值观等人事的部分,也包括对产品线产品的介绍,以及开发模式的介绍,以及开发、测试具体流程的介绍,总之,非常的全面,凡是未来会用到的全都有涉及到。只要保留好课堂的材料和自己的笔记,回头上手干活基本上没有任何问题。

  机缘巧合,我还在参加培训就被小组长抽调过去先参与到测试项目的工作中去了,也许是因为我看着比较顺眼吧……当时的我心中非常忐忑,不知道该如何干活,所幸有诺基亚的导师(Tutor)制度在,小组长给我安排了一位导师(在此要非常感谢她的辅导,帮助我顺利地融入诺基亚的氛围,真的非常感谢!),她教给我作为一个测试人员所要做的各种事情,给我很多的相关资料可以自我学习,也手把手地指导我执行以及分析和写测试报告等等很多很多。总之,和她配合,我受益颇多,测试项目开始不久,我就差不多已经可以独立工作了。

  我加入时导师已经在开始执行测试的阶段,于是我主要是要去理解测试计划、理解测试用例,熟悉测试工作和被测产品,掌握测试执行的各种操作命令。测试部门的知识传承做得相当不错,所有的文档都有模板和介绍,很容易就上手,知道各个部分写的是什么东西,以及如何使用。而且在测试用例中,不止包含测试步骤,通常也包括要执行的命令,和每个步骤的预期结果,以及最终的预期测试结果。测试报告也有模板,只要按照模板的要求,将测试时的环境,被测对象的各种版本信息,执行的命令和返回的输出等等各种信息都记录下来就行。

  当我渐渐地熟悉如何执行测试后,就开始对周遭事物有着各种好奇,成天都缠着导师问各种问题。一开始主要是在测试失败,或者得到一些不完全符合预期的输出时,不知道该算是通过还是失败,就要去找导师请教。慢慢地就开始问很多关于,为什么要这么设计这个用例啊,到底要测试的是什么功能,之类的问题,而导师的回答总会附上一句,“多看看功能需求说明书吧”。于是我就开始看功能需求说明书(Functional Requirement Specification),从中去理解我所测的对象所应该实现的功能。功能需求说明书也是有模板的,不过依然会出现不清楚或者难以理解的地方,这也是让测试人员很头疼的地方,因为无法确定测试的对策。最好的解决办法就是去问文档的作者,只不过这份文档的作者通常就是其开发人员(或者开发人员所在领域的专家),而他们通常都比较忙,忙着进行后续版本的开发(针对同一版本,测试总在开发完成后开始,所以测试开始时,开发人员都已经在做新功能的开发了)。

  而我的幸运则在于,当时开发那个功能模块的开发人员人都很好,是公认的牛人,而且很健谈,很愿意和测试人员交流(基于开发项目的进度压力,这一点还是比较难得的)。而且他的特点在于,除了开发自己负责的模块,他会花很多时间,多数是自己的业余时间,阅读其他模块的代码,而后是其他领域(Domain,技术领域)。他后来的发展也非常快,因为他阅读的代码很多,所以开发起来也就速度很快,了解的多分析问题也就很快、对整体架构把握也好。而我则是从他身上了解到很多该模块设计的原理,以及所要实现的功能,和服务的对象(其他模块),对我理解被测对象从而更好地有针对性地进行测试帮助非常大。

  这一个模块的测试还有一个比较特殊的地方,它其实是支持型模块,为系统内其他模块提供调试、日志相关的服务,所以测试中很必然地要针对各种情况下的记录、显示灯功能进行验证。如果直接借用现有模块来测试,会有一定的困难:首先是处于稳定性的考虑,其他模块一般都是要等到我们测试完成了才会开始使用;其次,就算有一些模块在使用,也不大会专门为了测试而频繁地修改它的代码,编译,然后提供给我们用于测试,除开开发人员工作繁忙,也还有编译和版本管理实践很花时间的原因。因此,我必须要自己开发一些测试应用程序(Test Application),这个程序里面,使用被测对象所提供的服务,并且要知道如何修改产品的启动列表,从而可以使这个测试应用程序可以在设定的时间点其中以及打印相关的信息。

我们当时所使用的测试工具也是诺基亚内部的工具部门自己开发的,说实话,相当好用。由于我们的产品具有自己的一套人机交互界面,所以只能用自己的工具来操作测试。这个测试工具自带的就有提供一个类C的脚本语言,可以很方便的写测试脚本,语言本身也很简单,上手不难,而且会写一点脚本对于测试 工作的辅助作用也很大。因而,从这个角度出发来看的话,我们并不存在完全手工的测试。

  做测试不可避免地肯定会发现软件的缺陷(Bug),发现缺陷之后需要将相关的信息记录下来,录入到缺陷追踪系统中去,开发人员会相应地收到通知。看到这里大家脑海里恐怕会浮现出一幅景象:测试人员提交缺陷报告后,过了好久开发人员终于回复过来“缺乏信息,需要得到某某模块的输出”,测试人员又吭哧吭哧地重现场景,再填好信息发过去,结果开发人员又要求别的信息,通常都要来回好几趟,才最后可能定位出问题根源,然后开发人员开始修改。当时我们的流程中对于开发人员最后的回复有一些要求的,定位出问题根源后,需要给出描述,以及计划在哪一个版本中进行修复,有一个例外,就是如果这个问题是“正常的”,不用改,那么通常会标识为“无需修订”(CNN,Correction Not Needed),打回给测试人员,结束当前的缺陷追踪流程。如果测试人员对此有异议,就好玩了,就开始打嘴仗,最后再和开发、测试的资深工程师(一般是相关技术领域的技术专家和测试专家)一起讨论定夺。缺陷修复的速度主要受到测试开发双方人员沟通效率的影响,从发现缺陷并记录下来,到定位出问题根源制定修复计划,通常以天数计算,而修复的过程,一般来说都是以小时计算,个别疑难问题稍微多花一些时间。

  有一次,我发现了一个错误,然后把现象记录下来,提交到缺陷追踪系统中,结果开发人员的回复是无法重现。于是我在测试环境中又再执行了好几次,发现问题都能够很稳定的重现,于是就再通过系统把这个信息返回回去。幸得开发人员也是态度很积极的工程师,估摸着心里很好奇,就直接来找我,于是我就在座位上给他重现,结果,居然没有重现成功!让人百思不得其解。长话短说,后来发现原因在于我之前执行的时候,都是用跑脚本的方式执行,而我们现场调试是手工执行的方式,但这两种方式的差别在哪里呢?经过仔细地分析,我们发现和测试用例的步骤有关。测试用例是要在一个会话(Session)上监听消息(产生特定消息是模块的功能之一),所以我们会先打开一个会话开启监听,然后再打开一个会话,再里面进行一些操作,然后回到之前的会话里去查看相应的消息是否有出现。而手工和脚本的差别在于,手工的情况下,我们人眼看到操作结束,就返回到第一个会话去停止监听,而后检查监听到的消息。在脚本中,为了确保操作是成功的,通常会等待一点时间,然后再切换到第一个会话执行后续的动作。但最大的区别在于,手工操作时,我们可以在测试工具中打开两个小窗口,监听和操作的会话都是处于活动状态(Active)的,而在脚本中,则只有当前会话处于活动状态。

  通过多次地现场协同重现缺陷场景,开发人员确定该问题不是被测的模块所引起的,还给了我一些建议,建议我找会话管理这一块的人来看看。后来发现这正是问题所在,通过分析之前执行的测试日志记录,包括我们现场重现的情况,对方很快就确认原因是会话超时(Timeout),为了节约资源避免浪费,每一个会话都有超时时间,超过这一时间没有任何动作的话,会话就会被关闭。而我的测试中,恰好离开第一个会话再回来,中间的间隔就超过了这个超时时长,导致会话关闭,第一个会话中的监听无法得到要监听的内容,测试结果分析的时候得不到预期的结果,测试也就无法通过了。修复非常的简单,对于会话超时处理的地方修改几行代码即可,但这个问题解决(Troubleshooting)的过程才是最艰难的地方,需要我们细心检查,发现任何可能的蛛丝马迹,甚至还要发挥想象力,将不同线索联系起来,最终才定位出缺陷的根源。

  正由于上述提到的缺陷管理时间中的沟通成本,我们一直在思索如何能够改进。一是从缺陷管理工具入手,加强它的功能,提高它的速度;二是从缺陷管理流程的角度出发,尽量简化,提高它的可操作性;三则是从组织架构方面出发,思考是否可以改变现有开发模式,拉近开发、测试人员之间的距离,使得沟通无需依赖工具也可以进行。

相关链接:

我的软件测试之旅:(1)起点——作为软件开发人员



posted @ 2012-07-30 09:41 顺其自然EVO 阅读(227) | 评论 (0)编辑 收藏

单体测试指南

 1、单体测试应该小并且快

  理想情况下在每次代码签入之前都要执行下测试套件。测试快就可以降低开发周转时间。

  2、单体测试必须完全自动化,不需要交互

  测试套件通常经常执行,必须完全自动化才有用。如果结果需要人工检查,该测试就不是真正的单体测试。

  3、单体测试应便于运行

  开发环境应该配置成通过一个单独的命令或者一个按钮点击就可以运行单独的测试和测试套件。

  4、评估测试

  对测试的运行进行覆盖分析从而得到执行覆盖并调查代码的哪些部分执行,哪些部分没有执行。

  5、立刻修复失败测试

  每个开发者都应该确保在签入后新的测试以及所有既有的测试都可以成功运行。

  如果在日常测试执行中有一个测试失败了,整个团队必须停下手头的工作来保证问题得到解决。

  6、保持测试在单体层

  单体测试和类的测试相关。每个普通类都要有一个测试类,类的行为应该在隔离的条件下测试。应该避免使用单体测试框架测试整个工作流程,因为这样的测试会很慢并很难维护。会有需要流程测试的地方,但不应该作为单体测试的一部分,它必须独立地设置和执行。

  7、从简单开始

  一个简单的测试要比根本没有测试好。一个简单的测试类可以建立起目标类的测试框架并可以验证编译环境、单体测试环境、执行环境和覆盖分析工具是否具备以及是否正确,从而可以证明目标类是否是程序集的一部分以及是否可以访问。

  单体测试的入门程序可能像这样:

void testDefaultConstruction()
{
    Foo foo = new Foo();
    assertNotNull(foo);
}

  8、保存测试相互独立

  为了确保测试健壮并简化维护,测试不能依赖其它测试以及测试执行的先后顺序。

  9、测试类和被测试类尽量近

  如果被测试类是Foo,那么测试类就应该命名为FooTest(而不是TestFoo)并同Foo放在同一个包里面。将测试类放在单独的目录下会使其难于访问和维护。

  确保编译环境的配置可以使得测试类不会进入生产库或执行文件中。

  10、合理命名测试

  确保每个测试方法测试一个明显的类功能并据此命名测试方法。典型的命名规则是test[what],比如testSaveAs(), testAddListener(), testDeleteProperty()等。

  11、测试公开API

   单体测试被定义为通过公开API测试类。有些测试工具可以实现类的私有方法的测试,但由于这会使得测试太过繁琐并更难于维护因此需要避免。如果有一些类 的私有方法需要显示地进行测试,考虑将其重构成工具类的公开方法。要这样做就应该要改进总体设计,而不是仅仅为了帮助测试。

  12、以黑盒考虑

  作为第三方的类使用者来测试该类是否满足需求。尝试着让它失效。

13、以白盒测试考虑

  毕竟,开发者写测试的同时也写了被测试类,需要特别注意测试复杂逻辑。

  14、微不足道的类也要测试

  有人会推荐测试所有主要的情况,而可以忽略诸如简单的类似setter和getter等微不足道方法。 然而,应该测试微不足道方法情况有几个原因:

  ● 很难定义微不足道。对不同的人可能有不同的含义。

  ● 从黑盒测试的角度看无法知道代码的哪部分是微不足道的。

  ● 由于拷贝-粘贴操作,微不足道的代码也可能包含错误。

private double weight_;
private double x_, y_;
public void setWeight(int weight)
{
   weight = weight_;    // 错误
}
public double getX()
{
   return x_;
}
public double getY()
{
   return x_;    // 错误
}

  建议就是测试所有代码,毕竟微不足道的代码很容易测试。

  15、首先关注执行覆盖率

  执行覆盖不同于实际代码覆盖。一个测试的最初目标应该保证高的执行覆盖。这可以确保代码在某些参数下真正执行。有了这个,就可以去改善测试覆盖了。注意实际代码覆盖很难确定(通常都很接近0%)。

  考虑下面这个公开方法:

void setLength(double length);

  通过调用setLength(1.0) 你就可能得到100% 的执行覆盖率。为了达到真正100%的实际测试覆盖,必须使用所有可能的double值来调用该方法以确认它们的正确行为。这显然是不可能的。

  16、覆盖边界情况

  确保覆盖参数边界的情况。对于数,测试负数、0、正数、最小、最大、NaN、无穷等情况。对于字符串,考虑空字符串、单个字母的字符串、非 ASCII的字符串、多字节的字符串等情况。对于集合,测试空集合、单个元素集合、第一个、最后一个等。对于日期,考虑1月1日、2月29日、12月31 日等。被测类会提示各个具体情况下的边界情况。由于这些都可能是错误的根源,因此要尽可能多地测试这些情况。

  17、提供随机数生成器

  在覆盖了边界情况后,进一步提高覆盖率的一个简单方法就是产生随机数以使得每次测试都可以使用不同的输入执行。

  为了实现这个目标,可以提供一个生成double、integer、 string和dates等类型随机数的实用类。生成器必须可以从各个类型的全范围内生成值。

  如果测试很快,可以考虑在一个循环内运行尽可能多的组合。下面的例子就是验证通过一次大端和一次小端转化是否可以得到原值。由于测试很快,每次可以根据不同的值执行100万次。

void testByteSwapper()
{
    for (int i = 0; i < 1000000; i++)
    {
          double v0 = Random.getDouble();
          double v1 = ByteSwapper.swap(v0);
          double v2 = ByteSwapper.swap(v1);
          assertEquals(v0, v2);
    }
}
 18、每次测一个功能

  在测试模式下,很容易去尝试对每个测试中的每件事都断言。这必须避免因为它使得维护更难。仅测试该测试方法的名字表明的功能。

  对于一般代码应该将测试代码尽可能少作为一个目标。

  19、使用显式断言

  在assertEquals(a, b)和assertTrue(a == b) (之类的)之间优先选择前者,因为它可以在测试失败的时候给出关于失败原因的更多有用的信息。 这对于上述提到的随机参数组合时输入值无法预先知道的情况尤为重要。

  20、提供负面测试

  负面测试是通过故意用错代码以验证稳健性和适当的错误处理。

  考虑下面这个如果传入负数就会抛出异常的方法:

void setLength(double length) throws IllegalArgumentException;

  可以这样来测试该特殊情况的正确行为:

try
{
     setLength(-1.0);
     fail();    // If we get here, something went wrong
}
catch (IllegalArgumentException exception)
{
     // If we get here, all is fine
}

  21、设计代码是考虑测试

  编写和维护单体测试的代价很高,使公开API最小化并降低代码的循环复杂度是降低成本并使得高覆盖率的测试代码更快编写和更易于维护的方式。

  一些建议:

  ● 通过构造时候确定状态来使得成员类不可变。这会减少对setter方法的需求。

  ● 限制过渡使用继承和虚的公开方法。

  ● 减少利用了友元类(C++)或包范围(Java)的公开API。

  ● 避免不必要的分支。

  ● 在分支内的代码尽可能少。

  ● 尽可能使用异常和断言来验证分别在公开和私有API中的参数。

  ● 限制使用帮助方法。从一个黑盒测试的角度每个方法都必须一样地测试。考虑如下这个小例子:

public void scale(double x0,double y0,double scaleFactor)
{
      // scaling logic
}
 
public void scale(double x0, double y0)
 
      scale(x0, y0, 1.0);
}

  省去后面的就可以简化测试,但代价是客户端代码会有额外的工作。

 22、不要关联到预定义的外部资源

  编写测试文件的时候应该不能利用将要执行环境的上下文信息以使得他们可以在任何时间任何地方运行。为了给测试提供所需的资源,这些资源应该通过测试自身提供。

  现在考虑解析某种类型文件的类的情况。应该将文件的内容放在测试内,在测试开始前将其写入一个临时文件并在测试完成后删除掉文件,而不是从预定义的路径选择一个示例文件。

  23、了解测试成本

  不写单体测试代价很高,写单体测试代价也很高。这是两者之间的平衡,从执行覆盖率考虑一般的行业标准是大约是80%。

  通常比较困难达到完全覆盖的区域是处理外部资源的错误或异常。在一个交易中模拟数据库崩溃是完全有可能的,但较之作为替代方法的深度代码检查通常代价过高。

  24、测试优先级排序

  单体测试通常是一个至底而上的流程,如果没有测试系统所有部分所需的足够资源就应该优先考虑最底层。

  25、考虑到测试代码失败

  考虑下这个简单的实例:

Handle handle = manager.getHandle();
assertNotNull(handle);

String handleName = handle.getName();
assertEquals(handleName, "handle-01");

  如果第一个断言是假的,接下来的语句就会崩溃,余下的测试也就不会被执行了。所以应该考虑单个测试代码失效不会使得这个测试套件无法执行。通常可以改写成这样:

Handle handle = manager.getHandle();
assertNotNull(handle);
if (handle == null) return;

String handleName = handle.getName();
assertEquals(handleName, "handle-01");

  26、编写测试来重现缺陷

  如果报告了一个缺陷,就应该写一个测试来重现该缺陷(比如一个失败的测试)并使用该测试作为是否成功修复代码的标准。

  27、认识局限性

  单体测试永远不能证明代码的正确性!

  一个失败的测试意味着代码含有错误,而一个成功的测试不能证明任何东西。

  单体测试的最普遍的应用就是验证和记录底层的需求以及回归测试:验证代码在变迁和重构的过程中一直保持稳定。

  因此,单体测试永远无法替代前期设计和健全的开发流程。单体测试可以作为既有开发方法的一个宝贵补充。

  后记:

  对于第9点”测试类和被测试类尽量近”和第14点”微不足道的类也要测试”,我不是很赞同,实践的时候也没有完全遵守。但为了忠实于原文没有做 擅自修改。大家在学习和实践的时候可能也会接触一些相悖的观点和理论,不要担心,选择最适合你尝试下就知道了。同时,欢迎说出你的故事!

posted @ 2012-07-26 09:46 顺其自然EVO 阅读(645) | 评论 (0)编辑 收藏

Oracle数据库查询高效分页

  由于网页渲染速度的影响,在C/S程序中那种一个Grid包含几千、上万行的数据基本上在网页是无法展现的,因此一般采用分页的形式显示(也可能采用Visual Srolling方式加载的,企业应用系统的不是很常见),ASP.NET 的数据控件一般带有分页功能,3.5以后还提供了单独的分页控件,也有用过AspNetPager这个第三方的组件。

  分页的控件实在很方便,以前的处理方式就是数据都拿出来,然后由控件进行处理,一般数据量不大的时候应该说感觉不出来优劣,但由于每次从数据库取的时候都是取所有的数据,肯定会增加数据库的压力,传输的数据库多了对网络带宽也会产生压力的。很有可能查出来1万条数据,最后显示只用到启用50条,翻页的时候又重新去查1万条数据,显示之后的的又50条。

  以下的分页SQL比较常见的,在SQL Server也有对应的使用TOP关键字的版本,记得刚学Oralce的时候就想着怎么不能rownum between minValue and maxValue的用法。与最初的疑惑的原理一样,rownum是在查询过程中生成的,因此以下的SQL其实是查出来5300行,然后扔掉了前面5000行,返回后面的300行。当然这种已经进了一大步的,由数据库返回的数据变少的,只是当查询的页数比较大的时候,查询还是存在一定的浪费。

  1. select * 
  2.   from (select a.*, rownum as rnum 
  3.           from (select * from yz_bingrenyz) a 
  4.          where rownum <=5300) 
  5.  where rnum >= 5000

  Linq提供了Skip和Take的API可以用于分页,由于使用的是Entity Framework,在好奇的驱使下用EFProfiler查看生成的SQL,才知道这样以下分页更好。 主要就是使用了row_numer()over()这样的分析函数,可以直接找到那第5000行开始的地方,然后在取出30行就行了。

  1. select * 
  2.   from (select * 
  3.           from (select t.*, 
  4.                        row_number() OVER(ORDER BY nullAS "row_number" 
  5.                   from yz_bingrenyz t) p 
  6.          where p."row_number" > 5000 
  7.         ) q 
  8.  where rownum <= 30

  比较分析:

  本机测试前者耗时1.3s,后者仅0.25s,从以下的执行计划也能看出差异来。

  实际应用

  如果每次查询都要写这种SQL那肯定比较麻烦,可以采用存储过程进行封装,但由于要动态执行SQL,效率肯定又要打折扣,所以在ASP.NET中用C#封装函数比较好,对于没有使用实体框架的而用ADO.NET的,传入表名 、主键名、页数、要取的行数作为参数,用DBCommand进行执行返回结果即可。

posted @ 2012-07-25 10:04 顺其自然EVO 阅读(858) | 评论 (0)编辑 收藏

敏捷项目管理实战之质量管理

简介:本文以笔者的项目管理实践为基础,介绍基于经验过程控制(Empirical Process Control)模型、缺陷预防以及敏捷价值观的敏捷质量管理思想及其实践。希望通过本文为广大项目管理人员提供质量管理的一些思路和经验分享。

  经验过程控制

  经验过程控制是一种问题驱动的轻型过程控制模型。在进一步介绍经验过程控制之前,我们先看一个日常生活中应用经验过程控制的一个例子:在菜肴的烹饪过程中,人们往往先观察菜肴的颜色,或者用筷子检查其软硬度来判断菜肴是否已经煮熟。若不够熟,则继续煮。待到菜肴快熟时,我们开始放盐、味精之类的调料。然后尝尝菜肴的咸淡是否适中,若太淡了则继续加盐,直到我们满意为止。经过这样一个过程,烹饪者满意的一道菜肴才能完成。

  上述例子正好体现了经验过程控制的三大支柱——透明性(Transparency)、检查(Inspection)、适应(Adaption)。透明性指影响最终产出结果的因素对于过程控制者来说可观察或者使其可观察。“透明性”在上述例子中表现为:菜肴煮熟程度是影响菜肴质量的一个因素,而这个因素可以通过菜肴的颜色或其硬度反映出来。检查指对影响最终产出的因素进行观察和评价的动作。上述例子中提到的观察菜肴的颜色、尝尝菜肴的咸淡就是“检查”。适应指检查过程中发现不可接受的结果、偏差时所采取的矫正动作。上述例子提及的在发现菜肴味道偏淡的情况下采取的继续加盐的动作就是“适应”。

  从经验过程控制的三大支柱我们可以看到其问题驱动的性质。问题驱动是指在过程实施时所进行的活动是基于有哪些因素影响了最终产出的结果,而不是像一些传统的过程控制实施者是从一些预定义的活动集合中“剪裁”一些活动。从一个活动集合中剪裁出一些活动,这本身就要求剪裁者对这个活动集合中的每个活动足够了解,从而能够选择适合自己的活动。这个剪裁的过程使得这些传统的过程控制实施起来相对困难,而经验过程控制因为省却了“剪裁”的过程而使得其实施相对容易。

  基于经验过程控制的质量管理其实施的基本思路是先通过经验或者对质量问题进行根因分析(Root Cause Analysis)发现影响质量的因素,再采取措施使这些因素成为可观察的因素(对应经验过程的“透明性”)。然后,在项目实施过程中对这些因素进行检查(对应经验过程控制的“检查”)。检查过程中发现不可接受的结果或者偏差时及时采取措施进行矫正以防止缺陷的引入或者缺陷流入下一道工序中(对应经验过程控制的“适应”),从而保证了最终产出的质量。

  缺陷预防

  《孙子兵法·谋攻》中提到“百战百胜非善之善者,不战而屈人兵,善之善者”。每次打仗都取胜不是战争的最高境界,战争的最高境界是不费兵卒而取得胜利。同样,在软件开发过程中,找出所有缺陷并将其一一去除不是质量管理的最高境界。质量管理的最高境界是将缺陷扼杀在摇篮之中——缺陷预防。经验过程控制三大支柱所体现的其问题驱动的特性说明了它可以帮助我们去实施缺陷预防。基于经验过程控制的缺陷预防是通过使缺陷来源成为可观察的因素,然后在软件开发过程中对这些因素进行检查,发现不可接受的偏差时及时采取措施进行矫正,从而避免了缺陷的引入。比如,当我们发现开发人员对需求理解的错误、不全面是缺陷的一个重要来源时,我们就可以应用经验过程控制的思想,先采取措施使开发人员对需求的理解成为可观察的因素。然后对其进行检查,若发现有需求理解上的偏差,则进行矫正,从而避免了因需求理解偏差而引入缺陷。

  诚然,软件测试的目的是发现缺陷。也正因此大多数公司和个人也就把测试人员定位成缺陷的发现者。然而,测试毕竟是一种事后控制型的质量管理手段,这不是上上策。能否往测试人员这个角色的职责的定义中增加一个缺陷预防的职能呢?笔者曾经在所带团队中引导测试人员往缺陷预防方面发展,在这方面多做贡献,而不是仅仅把自己定位为缺陷的发现者。在开发测试一体化团队中,测试人员同开发人员一起参与需求分析、评审。项目经理可以通过一些奖励措施鼓励测试人员多去发现需求本身的错误以及开发人员对需求理解的偏差,从而避免了需求相关的缺陷。另一方面,测试人员往往习惯于从发现缺陷中获得成就感。在引导测试人员在缺陷预防上多做贡献的过程中,项目经理需要引导测试人员使其认识到预防缺陷比发现缺陷更加能够体现一个人的能力和价值。

  需求澄清

  需求规格说明书本身的错误、不明确是软件缺陷的一个重要来源。因此,消除需求本身的问题是缺陷预防的一个重要内容。笔者在所带的项目中是通过开展需求澄清活动来消除需求本身的问题的。在开发团队内部进行需求规格说明书评审之后,评审意见被汇总成一个列表,这个列表可以是一个 Excel 表格,我们称之为需求问题确认列表。然后,我们邀请客户过来和开发团队一起对问题列表中的每个问题进行讨论。团队成员负责提出和解释问题确认列表中的问题,客户代表则负责解答和澄清团队成员提出的问题。客户对于问题的回复我们会记录到问题确认列表的“回复”一栏。需求澄清活动往往是以头脑风暴会议的形式展开的,而不仅仅是一个一问一答的过程。对于客户当场给的问题回复,团队成员可能因为通过自己的分析认为客户的回复是错误或者不合理的而当场对客户代表的回复提出质疑。客户代表往往也因此对其回复进行重新思考从而给出与会人员一致认同的回复。

  《敏捷宣言》中提到“客户协作胜过合同谈判”,需求澄清活动的基本前提就是客户代表的参与。因此它是符合敏捷开发的价值观的。

表 1. 需求澄清活动

  需求宣讲

  团队成员对需求理解的偏差也是软件缺陷的一个重要来源。我们可以应用经验过程控制的思想对这种因需求理解偏差而引入的缺陷进行预防。其基本思路是先使团队成员对需求的理解成为可观察的因素,然后对这个因素进行检查。检查过程中发现不可接受的偏差时及时采取措施进行纠正,从而避免了缺陷的引入。笔者通过在团队内开展需求宣讲活动来具体实施这个缺陷预防。

  需求宣讲是在开发人员开始编码、测试人员开始设计测试用例前,由全体团队成员参与的一个头脑风暴会议。在这个会议上,开发人员随机选取一个 Story,然后口头表述其对所选择的 Story 的理解。通过这个讲解,开发人员对需求理解就成为了一个可以观察的因素。当其他与会人从需求讲解人的讲解中发现其对需求理解上的偏差时,可以及时指出进行纠正。其他与会人员也可对其讲解提出疑问和质疑。当讲解人的回复无法得到团队成员的一致认同时,则进行讨论,最终达到对需求理解的一致。而对于讨论无法达成一致认识的问题,可以记录入需求问题确认列表会后再进行确认。

  当然,当开发人员被要求讲述其对需求的理解时,可能会说他其实已经理解了需求只是不知道如何表述。且不论这句话是否属实,项目经理应当引导团队成员意识到:在敏捷开发团队中,个人对需求是如何理解的,理解的对与错,深与浅不是其一个人的事情,而是整个团队的事情,因为它影响了这个团队最终交付的软件的质量!从另外一个角度来讲,当一个人能清晰得表述一件事物时,才说明其对这件事物是真正理解的。

  虽然需求评审和需求澄清这两个活动也能一定程度上反映活动参与者对需求的理解,但是它们更多的是用于发现需求本身的问题。而需求宣讲则是专门用于检验活动参与者对需求的理解正确性和全面性。

表 2. 需求宣讲活动


设计会话(Design Session)与简单设计(Simple Design)

  设计阶段所引入的缺陷不仅包括设计本身的缺陷还包括了因编码人员对设计方案理解的错误和偏差而引入的缺陷。极限编程所强调的是简单设计虽然一定程度上降低了设计本身缺陷的概率,并且也有助于降低设计方案理解偏差而引入缺陷的可能性。但是,从经验过程控制和缺陷预防的角度来看,我们仍然需要将编码人员对设计方案的理解这一影响质量的因素成为可观察的因素,并对其进行检查。

  笔者在所带的项目中开展设计会话活动。在设计会话中,通常由设计人员借助白板讲解设计方案,其他人员对讲解的内容有疑问和异议时可以提出集体讨论。主讲的设计人员也可以针对其讲解提出一些问题让其他参与人回答,以确定参与人是否真正理解设计方案。设计会话结束后,白板上的内容可以先保留一段时间,以方便事后再查看。有条件的团队也可将其拍照存档。设计会话中所讨论的设计方案可以事后由编码人员写入 Story 文档。由于相关人员事先都参与过设计会话,在 Story 文档评审时对其中的设计部分多少也许自己的认识和意见,这有助于发现对设计方案理解的偏差。

  设计会话体现了《敏捷宣言》中提到的“个人与交互胜过过程与工具”这一价值观,避免了仅仅通过设计规格说明沟通设计方案导致的沟通效率低下、设计方案理解偏差的问题,充分发挥了人与人直接沟通的优势。

表 3. 设计会话

  单元测试评审

  单元测试是软件开发中被普遍接受的优秀实践,也是影响软件质量的一个重要方面。有效的、充分的单元测试能够提高代码质量,从而有效避免了返工。但是如何保证单元测试得到有效的执行呢?按照经验过程控制的思想,我们可以先使单元测试成为一个可观察的因素,然后对其进行检查。检查过程中发现偏差时及时进行纠正从而保证单元测试得到有效的执行。

  定义单元测试的产出物可以使单元测试活动成为可观察的因素。对单元测试产出物进行评审可以发现单元测试所覆盖的测试用例是否真正执行通过以及测试用例覆盖是否充分。若单元测试评审过程中发现有测试用例未通过的或者遗漏的,则及时反馈给开发人员进行纠正,从而避免了缺陷进入下一道工序——Story 测试。

  笔者曾经在一个基于 SOA(Service Oriented Architecture)的项目中将单元测试过程中系统所产生的接口日志文件定义为单元测试产出物。在这个项目中,开发人员会将单元测试过程中每个测试用例执行时系统所产生的接口日志文件按所覆盖的测试用例的名称进行命名提交到配置库上,然后知会其他项目组成员进行评审。由于这个单元测试产出物能够反映系统所要实现的功能,评审人员可以通过分析产出物判断每个测试用例是否真正执通过以及测试用例是否覆盖充分。评审者把评审过程中发现的测试用例未通过或者未覆盖等问题会整理成评审意见提交到配置库上,并知会开发人员进行处理。

表 4. 单元测试评审活动



  面对面代码复审

  在比较常见的轻型代码复审过程中,开发人员提交代码到配置库上,然后代码复审人员从配置库上获取相应代码并借助一些代码复审工具将复审结果形成意见提交给代码作者进行处理,并跟踪复审意见的处理结果。代码复审人员往往只在复审过程中有疑问的情况下才找代码作者进行确认。这种轻型的代码复审复审表面上执行起来比较容易,成本也比较低。但是它和《敏捷宣言》中提到的“个人与交互胜过过程与工具”这一价值观是相违背的。因为它缺乏有效的人与人间的交互。这种缺乏人员间交互的方式也导致了评审结果最终呈现给代码作者的往往是问题。这一方面使得代码作者只是被动得发现问题和解决问题。被动得发现和解决问题往往导致当事人对问题及其解决方法印象不深刻从而极易导致相同或者类似问题重复得出现。虽然我们可以将复审过程中典型的问题形成检查表由开发人员在代码提交前对检查表中的项目进行自检,但是这个检查表往往也是在重复的问题被重复得发现后才形成的。另一方面,这种代码复审往往给代码作者一种“挑刺”的感觉,而作者自认为代码中比较优雅的部分往往也被人忽略了,因为那不是问题因此复审人员也不会将其指出。这容易导致开发人员对代码复审的本能性排斥心理,因为人总是倾向于被他人肯定,而不是总是被人指出问题。

  笔者在所带的项目中开展面对面代码复审。面对面代码复审活动中,代码作者通过电脑显示器或者投影仪向其他参与人展示其代码并逐行对其代码进行讲解。其他参与人则对其讲解进行分析判断,并将其分析判断的结果提出同其他复审人员进行讨论。复审人员发现比较优雅的代码时可以及时指出来,并对代码作者给予肯定。因此,面对面代码复审某种程度上也是编程经验和优秀实践的一个交流形式。另外,对于经过讨论后确认的问题则记入代码复审意见表由复审人员跟踪其处理结果。代码作者对其代码讲解的过程某种程度上说也是其本人对其代码进行回顾和再思考的过程。因此,代码讲解过程中,讲解人往往会自己发现代码中的问题,从而对发现的问题有深刻的印象,这有助于避免同样或者类似的问题再次产生。另一方面,由于代码中的问题会当众暴露出来,对代码往往有种敝帚自珍心理的开发人员在代码复审前会小小谨慎地去检查代码,从而避免“当众出丑”。因此,面对面的代码复审某种程度上也是一种缺陷预防的措施。

表 5. 面对面代码复审活动

  Story演示与转测试控制

  《左传·庄公十年》提到“夫战,勇气也!一鼓作气,再而衰,叁而竭”。返工不仅增加了成本,阻碍了进度,还影响了士气降低了质量。返工往往是由于某道工序缺乏它的入口条件控制。比如,Story 转测试这道工序如果没有控制其入口条件,则很容易由于事先未评估被转测的 Story 质量导致在测试时仍然有大量的缺陷存在。这就意味着在第一次转测试后,开发人员需要修复大量的缺陷,并且开发人员在修复缺陷的过程中往往又引入了新的缺陷,进而导致了对于同一个 Story 需要进行多次修复缺陷和多次转测试的工序才能使这个 Story 满足质量要求。

  因此,对 Story 转测试这道工序进行入口控制可以有效避免返工现象。任何一个 Story 在其转测试前,我们要首先评估其质量是否满足一定的要求才决定其能否转测试。

  笔者在所带项目中通常以 Story 演示作为 Story 的转测试控制。Story 演示要求开发人员在 Story 转测试前召集该 Story 的测试人员及其他相关人员对该 Story 的各个验收测试用例的执行情况进行展示。其他参与演示的人员则根据展示的结果分析各个验收测试用例是否真正通过,进而评价所演示的 Story 的质量水平并决定所演示的 Story 能否转测。

  Story 演示过程发现的问题以及疑问可以记录入 Story 演示记录。Story 演示记录样例见表 6。

表 6. Story 演示活动

表 7. Story 演示记录样例

  结论

  经验过程控制模型为敏捷质量管理提供了一个简单易行的理论指导。缺陷预防是质量管理的一个重要思想,而经验过程控制模型可以帮助我们具体实施缺陷预防。另外,敏捷宣言所体现的敏捷价值观也为质量管理提供了思想指导。




posted @ 2012-07-25 09:54 顺其自然EVO 阅读(473) | 评论 (0)编辑 收藏

关于系统性能测试的步骤总结和分析

关于系统性能测试的步骤总结和分析

  近期接触的项目,进行了比较多的性能测试,就性能测试的步骤做一下总结和分析,也希望对以后的工作有益。

  性能测试,是一种“正常”的测试,主要是测试正常使用时,系统及时性(响应时间、吞吐率)是否满足要求,同时可能为了保留系统的扩展空间进行一些稍稍超出“正常”范围的测试。

  常用软件:HP  LoadRunner

  系统性能测试中的几大步骤:

  1、明确测试目标;了解性能测试需求;

  2、编写性能测试计划;

  3、分析性能测试需求;

  4、编写性能测试方案、设计测试场景;

  5、相关资源准备(硬件资源、软件资源);

  6、执行性能测试并收集测试结果;

  7、分析结果;

  8、系统调优及再测试;

  关于步骤的解析:

  1、明确测试目标;了解性能测试需求;

  性能测试启动阶段要确定测试的负责人和组织结构。明确测试的总体目标和范围,确认资源情况。获取性能测试需求:业务列表、性能指标、测试环境、数据量等详细需求。为策划规划做准备。

  性能调优是是无止境的,所以在测试之前应确定一个明确性能调优目标,作为基准。

  2、编写性能测试计划;

  性能测试计划中包含测试目的和测试目标的相关信息,还确定了实施和执行测试时使用的策略,方法;同时还要确定测试工具、所需资源、日程表计划等。

  3、分析性能测试需求;

  性能测试需求分析主要目的是要找出可能造成系统瓶颈的因素,为后面的测试场景设计提供依据。影响系统性能有很多种原因,在此应关注如下几个关键点:

  A 环境配置性能需求:

  应用配置需求:例如应用整体框架、涉及到哪些第三方的组件、应用层与数据库层的接口、使用了什么数据库等;

  B 系统配置需求:例如用户客户端配置、客户端与服务器端的网络配置、应用服务器或数据库服务器操作系统等等;

  C 服务器性能指标要求:

  预期的在上线系统中服务器资源使用情况、吞吐量、软件运行情况等等。

  D 系统设计需求:

  系统架构、系统的技术实现、与其它系统接口关系及其技术实现、本系统测试数据及其与相关系统测试数据关系等等。

  E 工作负载需求:

  用户使用情况需求:例如用户分布情况;哪些模块用户使用比较频繁;在用户操作的数据有哪些特点等等;这些需求需要具体定位到系统的哪些功能模块、功能点;

  F 客户端性能指标要求:

  请求响应时间分布;请求的准确率等等。

  4、编写性能测试方案、设计测试场景;

  明确测试目的和测试的范围以及项目功能需求,分析测试环境中可能出现瓶颈的位置,据此来编写性能测试方案。在设计测试场景时,尽可能把测试按照类型划分,每个类型下又设计N个场景。一般来说测试中会使用的一些场景:

  预期性能指标测试、单一功能加压测试、复杂场景测试、压力测试、负载测试、大数据量测试、配置测试等。根据对业务数据的分析,设计与真实情况类似的场景,来测试系统的整体性能。

  5、相关资源准备(硬件资源、软件资源);

  硬件资源包括被测应用的主机和应用环境的部署,压力发生环境的准备和网络环境的部署以及监控系统环境的部署等。

  软件资源包括测试程序的开发,挡板的开发,测试脚本的编写、测试数据的准备和参数化数据在各测试用例中的调整、数据分析准备等。

  6、执行性能测试并收集测试结果;

  在测试执行前,需要确认用例和场景、测试环境、测试数据、测试脚本、测试工具监控工具的正常。

  在测试过程中,每个场景的执行和使用的用例都要做记录,并且做好结果的搜集,关键数据要做截图。

  在测试完成后,注意数据的恢复和备份、环境的清理、结果的整理和相关文档的生成。

  7、分析结果;

  测试结果的分析其目的主要是根据测试获取到的数据去判断造成系统出现瓶颈的位置,挖掘造成系统瓶颈的原因。当然这个过程是技术含量最高的一环。

  8、系统调优及再测试

  根据测试的分析结果,有针对性的去进行优化。比如:针对缓存上的问题,可以设置多级缓存;针对数据传输的问题,可以把大数据块分块传输,减小网络传输;如果是硬件资源的问题,可以增加更多的硬件资源;如果是服务器的应用访问压力问题,还可以做服务器应用的负载均衡水平扩展。在系统调优后,还可以再行测试以便达到更好的效果和切中指标。

  总之,性能测试是个繁琐和细致的工作过程,测试工具在测试中也只是一个辅助性的作用,而对测试得到的数据进行分析进而准确的定位问题和系统瓶颈才是关键。


posted @ 2012-07-24 09:46 顺其自然EVO 阅读(365) | 评论 (0)编辑 收藏

仅列出标题
共394页: First 上一页 304 305 306 307 308 309 310 311 312 下一页 Last 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜