2013年5月30日星期四

开发和测试的六道轮回

 2012年是移动互联网年,我学习了Object C的开发,开发了较多的功能和内容,对于开发的过程和开发后的质量,以及开发自测有了新的认识。此前一直站在测试的角度去思考开发如何做测试,如何自测,如何共同保证测试。当时觉得不是很有难度,应该可以这样做,应该可以做到什么程度。现在对这个问题有了一些新的看法,作为个人的体会和感受,希望与各位讨论。

  若隐若现

  记得毕业后,我和隔壁班同学一起分到了HW公司的某产品部门,我在测试部门,他在开发部门。刚开始的半年,我学习了业务、数据库操作系统、测试工具、测试流程和管理。半年后,我继续学习测试相关的资料,感到了一些迷茫,在HW是封闭式的环境,接触不到外面的世界,我觉得测试学得差不多了,看到同学每天写代码到很晚才下班,貌似学到了很多东西,成就感明显大于我。

  于是,我开始偷偷地拿出来自己带的C++教科书,慢慢学习C++代码,当时我没有自己的电脑,使用公司的电脑学习C++,为的是不让自己忘记C/C++的语法和基本代码,没有完整的学习规划,再加上HW公司的确工作忙,只能慢慢地学习,效果非常不好,基本上自学的代码量不超过百行。开发能力和刚毕业时有了较大的下降,但是也没有太多的危机意识,觉得自己学到了很多测试方面和OS和DB的知识,在外面能有用武之地。

  顺藤摸瓜

  在HW工作一年后,我去了A公司。相对来说,A公司的工作压力要小很多,也接触到了外面的世界,除了学习更多测试相关的知识以外,仍然没有放弃学习和编写代码。由于接触的产品是C#编写的,需要重新学习C#的语法和基础代码。由于时间较充裕,加上和开发人员关系和谐,自己可以动手编写测试工具和相关的工具。清楚的记得自己为了锻炼编写C#的代码,写一个计算器程序,代码量上千行,对于自己开发的计算器程序有种莫名其妙的成就感,体会到了一些编写代码的乐趣;后来乘胜追击编写了一个简单的写代码的Edit工具,有点类似于UltraEdit。

  也就是那个时候,发现自己编写的代码越多,隐藏的bug越多;发现修复了一个bug外,还产生了好几个bug。也许是自己的编写代码能力有限,清楚地理解了编程不是那么简单的事情。做出来的工具得到了开发以及开发主管的认可,感觉自己有编程方面的潜力,感觉不错,有些许的成就感,也曾想转岗做开发吧,但是一直没有下定决心。

  我的开发能力得到了展现,希望尽量应用到测试工作上,当时我在SE Team,专门为产品上线后提供后续服务,对于技术支持人员报告的bug,我负责重现和 验证,时间上较宽松。在重现bug后,我都要调试代码,查看问题出现在哪里,有时候找到出现错误的原因,并给出简单的修改建议,开发人员在修复bug时,大致了解我对于该bug修复的注释。

  随着时间和实践的增多,后来我不仅通过调试代码找到引起bug的根本原因,还会给出详细的修改缺陷的解决办法或变通方法,给出详细的原代码和新代码,同样也会验证结果。得到了开发的极大认可,我的成就感有了很大的提高,但是仍感觉和开发人员相比比较,我调试代码的能力较弱,投入调试的时间有限。从结果上来看,自己不仅仅保持了一定的代码编程能力,还可以将开发和测试的关系以及应用过程了解得更深入,相应地持续提高编码能力。当时也编写了基本的自动化测试代码,由于测试框架封装的较好,测试代码基本上没有太多含金量,这些工作不仅仅是了解这个代码规范,还详细了解了测试框架的架构以及基本实现方式,为后续接触不同的测试框架打下了基础。

  东山再起

  来到淘宝,我对测试能力保持充分信心。当时淘宝还是页面自动化的初始阶段,我结合以前对测试框架的架构的理解进行内部交流,为淘宝的测试框架的改进带来了一些新的架构思路,比如Page Model和DB Model。此时的编程语言变成了Ruby,只好尽快学习Ruby编写自动化测试代码,接着为了编写接口测试代码,马上学习Java,2010上半年我的开发能力还停留在自动化测试代码阶段。后来部门实施技术产品化的策略,将测试技术转换到产品中来,必须学会开发产品,所以当时参与了Web应用开发,开发公共用例中心(CTC),从而了解到了更多开发方面的知识。中间件、Spring、iBatis等等,在Java开发方面有了更多的进步,但个人认为还是皮毛阶段。

  2011部门开始提倡测试具有定位bug的能力,在几个项目测试过程中,在时间充裕的情况下也会调试代码,从而找到引起bug的根本原因。但这个要求在互联网的项目流程中实施起来较难,因为测试阶段本身的时间非常有限,还要花费较多时间调试代码,有些得不偿失。开发人员和项目经理(PM)也未必真正认可,因为在测试阶段会给项目带来进度上的风险。但是这个过程,对于测试人员提高前端开发和Java开发方面的技术知识有较大的帮助。

  我的个人体会是,测试人员不是一直处在编写代码的时间轴上,测试人员的开发能力随着时间的推移,下降很快,重新捡起来,需要花费较长时间。当时我在编写前端代码和Web service的Java代码时,投入了很多精力,咨询了很多同事,总算搞定了。但是3个月后(期间未做任何开发相关的工作),重新开发类似的工具或功能,还是需要花费较多的精力,感觉非常痛苦,真想转做开发岗位了。

  知己知彼

  2012年,部门开始强调开发自测,很多部门开始进行直接的开发测试比的考核和价值考察。我对这种做法一直持保守态度,可能和个人的经历有关,也可能和被测产品有关。对于互联网产品来说,需要做很多测试工作,完善被测产品的质量和用户体验。

  刚开始我的策略较为简单,将测试设计共享和传承到开发人员,开发人员能接受多少,就可以一定程度上避免某些bug,从而在进度和提交测试质量上保持良好的平衡。开发人员还是比较喜欢这种方式的,但是开发人员很少真正将异常测试场景自测下去。经过几个项目的试点,发现效果较差,原因肯定有多个,大家也会猜到一些。

  接下来强化单元测试,一方面开发人员提高单元测试的覆盖率,另一方面测试协助单元测试,但是这其中有很多瓜葛,特别对于上层Web应用来说,开发人员的压力较大,提测(开发人员完成开发和自测后,进行提交给测试团队的时间点)压力也较大,从而一定程度上影响单元测试的覆盖率和持续集成,再加上测试人员的Java理解代码能力不高,短时间内也无法做到较好的单元测试。只能测试人员慢慢地提高Java代码理解能力,导致测试进度缓慢,很多事情开发和测试都是心有余而力不足。当然,开发自测还有很多其他的策略和方式,不是本文讨论的重点。

  2012年,开始无线移动开发和测试,我希望把握工作机会,开始了iOS开发之旅,重新学习Object C语言,重新学习新的开发方式,坚持了一段时间后,自己对于iOS开发有了一些感觉。总体上来说,iOS开发比其他的开发更有成就感,因为开发出来的APP看得见摸得着,容易看到成果。刚开始加入产品的开发团队时,将测试设计的大部分时间用来开发产品的某个功能,感觉比较痛苦,我花了3天才开发出来的功能页面,一个刚毕业不久的开发人员只花了一天就搞定了。我当时的痛苦只能自我感受,必须持续坚持下去。为了尽快熟悉iOS开发技术,我多此请教开发人员。后来开发了tBug,从使用Storyboard到丢弃它,写了更多的代码,看着自己开发的APP,成就感真的比发现bug要强烈多了。

  通过在iOS上积累开发经验,这让我更多地理解了开发人员,更多亲自感受开发人员的心态和对于测试的态度,大致包括几个方面。

  (1)使用快速迭代时,对于某个功能需求,开发人员编写代码时绝大部分考虑正常流程,较少考虑到异常流程,很多精力是放在如何实现功能,而不是思考用户会在多种场景下,如何使用这个功能(此任务需要测试人员投入很多时间思考)。

  (2)开发人员在修复一个bug后,存在一定的思维惯性,只能验证这个bug是否修复,没有较多的时间测试相关的功能流程,而测试人员会发现该bug修复后引出的新的bug。我针对Bug调试代码后,很快找到引起bug的原因,很快的修改了bug,较少思考修复的方案是否会带来新的bug。在修复一个bug时,开发人员往往有多种方案去解决这个bug,但是不同的方案会带来不同的结果,有些方案会引发一些新的bug,有些不会。所以我也经常建议测试人员不仅仅要验证bug,更要思考bug的解决方案,思考这个方案会带来什么影响,从而探索式的使用更多的测试场景去测试它。

  (3)开发过程中,考虑如何去测试它,难度不小。有人会说,使用"测试驱动开发(TDD)"方式,开发之前,先把测试用例写好。这个方式的确很好,但是对于测试经验较多的人而言,可以这么去做,但是开发人员还是需要耗费较多时间思考如何实现,而不是如何测试它(这就是测试人员与开啊人员思维的差别)。所以测试人员强迫自己写完代码后,多去测试它以及周围相关的功能。真正体会持续集成的作用,虽然没有发现bug,但是对产品的质量提供了充分的信心。

  (4)开发人员可以发现很多测试人员都发现不了的bug,然后"悄悄地"修复bug。2011年我经常和开发人员沟通,开发人员说他们发现了好多个bug,已经修复了,测试人员是不会发现的。我当时无法理解这个事情,现在我总算能明白一些了,开发人员在修复bug时或编写相关功能的代码时,会发现某些问题,然后修复掉,而测试人员完全不知道,很多时候也不会去测试这些场景。举个例子,APP登陆分为第一次登陆和后续登陆的逻辑区分和判断(包括读写cache和客户端数据库),假设第一次登陆出现错误的结果,测试人员报告bug。开发人员修复bug时修改了相关的代码,从而引发该业务逻辑的错误,测试人员的大部分测试都不是第一次登陆看到的结果,测试人员很难想象第一次初始化会出现问题。假设测试人员想到这个场景,需要重新登陆、甚至需要重新安装APP、重新初始化,这些过程都是很麻烦的过程,测试人员不一定有坚定的信念完成这些操作。如果他知道如何实现功能的代码,调试相关if else代码,进行逻辑的修改,从而可以在白盒层面测试到自己需要测试的部分。

  (5)开发人员需要了解的知识面远大于测试人员。完成一个任务,开发需要实现这个功能,需要付出很多精力。对于测试来说,完善的测试设计和测试执行,可能需要了解业务逻辑层面,而不是技术层面(如果在白盒层面进行更多的测试,情况会不一样)。总体时间是固定的,开发人员将在实现功能上耗费更多精力,响应减弱在自测上的投入。而测试人员刚好相反,测试人员会投入更多的精力去分析功能的异常逻辑是什么、用户的正常使用路径和异常使用路径是什么、用户体验上是否有改善的地方、开发会如何设计这个功能、会存在什么样的风险和问题等等。希望开发也会用一些时间思考测试人员如何测试程序,这样或许能帮助提高自测的质量。

  六道轮回

  上面讨论了个人做开发期间的一些感受,希望真正的站在开发的角度去理解测试,从而更好的从测试角度去测试产品、提高开发的质量。我需要解释这篇文章标题的含义了。我在2009年问过一位在微软总部工作的测试开发工程师,微软的测试最大的核心价值观是什么。他毫不犹豫的告诉我:开发就是测试、测试就是开发。

  对此观点,我现在明白了一些了,表面上不同的岗位,不同的职责,大家的目的和目标是一致的。开发的过程中,开发人员思考如何测试产品,就是更好的开发产品。测试人员更好的思考如何开发产品,也就是更好的测试产品。开发久了,不得不思考测试的重要性,不得不提高代码的质量(其实你就是在做测试)。测试久了,不得不思考开发的重要性,不得不去发现更多更好的bug、不得不设法提高代码的质量,从而提高整个项目的流程和进度,同样也是减轻自己的痛苦(其实你就是在做开发)。

  开发和测试,都有脱离不掉的责任和目标,为此,开发和测试人员都需要换位思考自己、思考对方。我相信未来开发和测试会有更好的机制理解对方、制约对方、依赖对方、完善对方、改变对方。开发人员不再看不起测试人烟、测试人员不再自我感到彷徨,大家在六道中享受轮回带来的乐趣和成长。



工具类App困局:变现之路崎岖

  从2012年开始,移动互联网就进入了"降温"通道。这种"降温",其实并非是玩家退出盘子缩小,而是产业格局的整体变化。在资本力量的引导与推动 下,优势资源开始朝着有明确商业前途的应用汇集,而未能在这个窗口期寻求到明确商业模式的应用,如果没有足够投资可供延续,则会黯然退场。

  显然,游戏、电商应用(包括O2O类应用)、儿童应用和垄断性质的重应用App都有明确的商业模式。而在这四个群体之外,还存在着大量的大众工具类应用。粗略划分,这些工具类应用大体上可归为网络与终端工具、生活信息、生活记录、社交与多媒体等类别。它们显然具有用户价值,但在商业化的道路上往往被其他应用甩在后面。

  对于这些起步并不算晚的工具App来说,时至2013年仍然存在的它们显然可能面临着相同的困境——比如盈利时间尚不可测;却也会迎来不同的机遇——比如相同定位的新竞争者出现的概率已经很小。工具类应用正处在一个十字路口。

  然而,这究竟是长跑的最后一公里,还是永无止境的不归路?通过对这些应用的观察与分析,也许能够彰显出移动互联网更本质的一些东西。

  门槛

  工具类App应用所面临的共同局面是:开发门槛相对较低和竞争对手众多两个不利局面。然而,这些应用能够留存到现在,已经说明了其具备可观的用户价值。

  以Camera360应用为例,这款2010年6月诞生的App,是比Instagram还要早的拍照类app 之一,并且在2012年初就拥有了3000万用户。Camera360的用户数量在很长时间内都与Instagram的用户数量相当。截止到2012年上半年,Camera360已经拿到了三轮融资,这在当时拿到第二轮融资都屈指可数的中国开发者团队里面,的确是凤毛麟角。

  然而,Instagram在去年被Facebook收购,可谓是给了Camera360以及同类App一个有喜有忧的暗示。喜的是 Instagram的被收购价格在一定程度上证明了自己的价值;忧的是Instagram放弃了独立探索盈利之路,这对它们这些曾经目标远大、现在用户仍旧可观的拍照App无疑是一种与理想渐行渐远的暗示。

  3G门户总裁张向东对《商业价值》表示,在他看来,一款大众工具类App若想实现商业模式,必须经历几个门槛:第一道是拥有大量用户;第二道是拥有良好的产品体验;第三道是满足用户个性化需求;第四道是能使用户长时间停留。

  按照这个逻辑,显然,Camera360已经迈过了前两道槛,第三道也基本迈过,但在第四道前面被卡住了——拍照类应用没有长时间留住用户的基因。

  在这方面,似乎3G门户的Go桌面系列比Camera360更前进了一步。Go桌面App一直是3G门户在海外广受好评的产品,2009年将Go桌面剥离出产品群独立运营,并于去年12月在Google Play上线了价格为15.99美元的高端3D桌面App——Next Launcher系列。仅用两周,Next Launcher就登上Google Play应用商店个性化分类"创收最高"榜首位置,销售收入突破100万元人民币。这应该说是Go桌面应用商业化的里程碑。

  对于Go桌面为何能跨越最后一道门槛,张向东的解释是,桌面应用是相对比较底层的应用,容易长时间吸引住用户。

  然而,像Next Launcher这样能够直接下载收费的app必然是少数,并且收费前提还是在海外市场。对于大部分大众工具App来说,不能直接迈过第四个门槛,靠流量变现的模式探索盈利可能仍是一个必选动作。

  出路

  流量变现这条路按照PC互联网的视角,看上去很美,然而却充满艰辛。众所周知,在移动互联网爆发之后,移动广告却没有跟上整个行业的步伐。流量变现这一种原本应该是互联网最基本的商业模式,竟然在移动互联网上失灵了。

  于是,从充满期待到失望悲观,诸多开发者都在等待PC上面那些挥金似土的广告主的给养,以摆脱仅靠手游广告和巨头应用广告惨淡经营的局面。这就必然要求这些大众工具类app在保证迈过前三个门槛的同时,还要等待姗姗来迟的广告主。

  在塞班时代就开始创业的墨迹天气,是国内创业最早也是最知名的天气类App。其目前已经拥有了1.2亿用户,日活跃用户在千万级别。2012年 年末,墨迹天气开始试水品牌广告。比如其专门设置了紫外线指数,并给出该指数下的饮料推荐;又在iOS 2.8版本中由身着品牌服装的姚晨、阮经天等明星给出用户穿衣提示。

 虽然已经取得了些商业收入,但墨迹天气的创始人金犁对《商业价值》表示,要想继续生存下去,在产品在驻留时间方面有短板的前提下,必须通过社交功能加强用户粘性,进而曲线实现张向东说的长时间停留。比如,墨迹天气正在通过"时景拍照功能"打造摄影师社区,并且与微信对接,增加了朋友圈分享功能。

  既然没有盈利,金犁并没有允许墨迹天气在市场推广方面进行大量支出,而是吸收了1月份登陆湖南卫视《天天向上》后用户激增的经验,采取品牌化推广的路子。其在不久前刚刚与青海电视台合拍了一个公益节目。

  与墨迹天气一同登陆《天天向上》的还有Camera360应用。实际上,Camera360的境遇与墨迹天气十分相像。两者采取的都是通过加强社交功能曲线延长用户驻留时间的办法,也都打算通过品牌运作减少渠道推广的支出。

  与Camera360、墨迹天气和Go桌面都不同,知名记账App随手记采取的是另外一套生存策略。随手记上线也很早,但拥有5000多万用户的它同样因商业模式问题苦苦探索了好一阵子。

  2012年,随手网旗下的第二款产品——卡牛上线,这款信用卡消费实时通知App,与随手记形成了搭配关系,并且可以整合双方数据来记账。随手 网创始人谷风向《商业价值》介绍,由于记账类应用无法社交化,那么随手记等产品只能选择面向企业去运作,以增加黏性。例如,成为银行理财产品的推荐渠道或 者与银行联合发卡。这是随手记系列产品今后的基本商业模式。当然,随后记也没有放弃改善产品体验,例如随手记9中就开辟了旅游、装修与结婚事宜垂直记账表 格。

  2011年随手记的市场推广费用只用了18万元,现在则因找到了商业模式,每个月的推广费用都超过了这个数。

  值得一提的是,这些拥有大量用户的大众工具类App ,绝不会被归零。像Instagram被收购那样实现与巨头的耦合价值成为了它们保底的选择。实际上Camera360、美图秀秀、陌陌等知名大众工具App都已经与巨头联姻。

  总之,由于门槛低却想象空间大,加之流量变现有待时日,致使大众工具类App仍旧处在一个前途不太清晰的探索阶段。

  但因为它们有着巨大的用户价值,所以各开发者已经有了比较明确的产品定位和方法论。只不过,它们各自的成长道路却往往相差很大。

  谷风认为,现在很像PC互联网的2002年,每一款大众App的最终市场饱和量就是2~3家,这是一致的。而且即使最后被收购,那也是一种成功。

  "MSN最后也被QQ干掉了,谁能挺过恶性竞争谁就是赢家。这就是互联网。"谷风说。



为什么测试在敏捷项目中重要


前段时间发布了《QA部门将会消亡》一文。

  本文是一位测试专家对该文做出的回应。

  就如同已经灭亡的皇室(国王已经消逝了,但是皇后却将永存),我们的软件开发正传递着类似的呼声:"测试已死,我们再也不需要测试人员了!"但随之你会发现,哎呀,客户不满意,最后又回到"测试万岁",但这次是更好,更完整,更有效的测试。就如同历史上众多的复辟王朝(我最喜欢皇后伊丽莎白1世)一样,测试将强有力地帮助重新定义事物完成的方式以及它们的工作原理。

  我打赌你现在正在想这不过是自我吹嘘而已,但是,事情是这样发生的:

  让我们讨论一下测试的概念:什么是测试?测试就是考虑什么是"对的"的一个流程,定义方法以判断所测试的事物是否是"对的",确定度量以明确"对的"是什么样子,理解"对的"的等级对团队其他人的任务和活动意味着什么,还有协助团队根据有用的信息做出好决策从而满足"对的"所必须的等级。

  测试远不止随机敲击键盘以期找出问题这么简单;测试需要真正地理解所要求的解决方案,参与交付产品所采用的方法计划,了解交付方法所含的风险,同时还要尽早发现这些风险以便采取合适的补救措施。测试还需要驱动项目往成功的方向发展,并且帮助每个人理解成功所要求的合适水平。

  为什么我们还需要关注测试呢,敏捷团队中的每个人不都在做测试吗?事实上并非如此。

  所有的争议都是从质量的概念开始的。可能你会对自己说:"这简单。"如果你确实是这么想的,那就把它推到下一步…定义它。让你的开发团队、客户、产品所有者、项目经理以及组织中的首席信息官和首席执行官定义质量,要好好地定义,定义到足够好的程度。他们会同意吗?如果不同意,那这就是你的第一个问题。测试的任务就是帮助团队定义和理解质量所带来的影响。

  "质量的影响??这是什么?"这是你的下一个问题。事实上:质量是需要成本的!更糟糕的是:真正的高质量需要更高的成本!想真正建立质量,我们首先必须定义它,然后需要找到它。如果没有将质量建立到流程和技术中,没有将完整的各个级别的测试构建到我们的工作中,就不可能实现质量解决方案。

  "啊,总算逮住你了"开发人员说道,"我们在敏捷中通过定义"完成"来明确质量"。"垃圾!"是我的答复。在我从事IT的所有时间里我听过最让人兴奋的概念就是定义"完成"—所有的组件,集中所有的知识,传递所有的信息……将解决方案的复杂性预先定义,所有的团队(开发和客户团队)都知晓所需要完成的任务以达到"完成"。定义"完成"让我想起了测试相关的一切。但是坏消息是我们并没有这么做!是的,我们没有这么做!就像我们不定义质量一样……我们只是假装我们定义了而已。哇~, 是否刺到你的痛处了?

  为什么我这么说呢?首先,定义"完成"就如同定义质量一样,非常难。因为质量就像"美丽"一样,它是一个仁者见仁,智者见智的问题。测试的内容包括接受培训从而关注质量的定义,紧接着是对质量的探索(或者是质量缺陷),还有就是沟通在项目过程中依据进程、风险和剩余工作明确质量等级意味着什么。对于"完成"的定义也是如此,对于每个"执行者"(非旁观者)而言"完成"是不一样的,这允许我们理解"完成"的多个层次……我的完成,我们的完成,故事的完成,迭代的完成,特性的完成,发布的完成,产品的完成,项目的完成。

  "这个没有关系,我们可以在其完成时再定义。"这是你对这个问题的机智回答。现在真正的挑战来了!定义"完成"与定义"很好地完成"是完全不一样的。"很好地完成"中的"很好"不仅仅是要完成目前产品中所要求的工作,还要明确我们如何知晓它达到了被要求的标准。每个层次的"完成"都有不同的完成标准,以及一个非常不同的"很好"的质量标准。团队中就有一群人不仅非常适合于协助定义"很好地完成",同时还可以协助定义用于寻找"干得好"等级的流程和技术。

  步骤一,定义"完成"…嗯,这看起来很简单嘛——保证执行者按照"完成"的等级完成所有需要交付的组件。好吧,目前为止听起来还不错。但是紧接着难点就来了…如果客户不满意,那么任何事情都不算"完成"。这就是敏捷宣言的基本属性之一。我引用了"可工作的软件胜过面面俱到的文档"这句话。因为一些不为人知的原因,人们往往会混淆"可工作"的定义与"完成"的定义,同时还会混淆"面面俱到的文档"这一概念与"良好测试"的定义。然后这就违背了原则"我们的最高目标是通过尽早持续地交付有价值的软件使客户满意"。那么是什么使软件具有价值呢?是不是交付产品?当然不是!而是该软件能很好地完成它所要完成的工作!!那么这算是我的"完成",我们的"完成",还是什么的"完成"呢……?

  我们该如何去做呢?首先,我们需要认识到测试不仅仅是考虑开发和用户所关注的功能。功能要实现什么是非常简单的部分(简直就是轻而易举——我发誓)。功能很容易定义、构建和评估。功能倾向于二进制,类似"完成"与否的!"完成"有两个等级……"完成"和"未完成"……没有什么"几乎完成"这类说法。功能类似于煮食物……只有能与不能工作之说……二进制!但接着我们就进入了"完成"和随后的"很好地完成"领域,甚至更进一步的"为谁很好地完成?"。

  测试关注于理解什么能使一个解决方案或方法对于使用它的人有价值。价值是上下文独立的,并且必须在项目和客户的上下文内定义。使用类似ISO9126之类的标准,根据它的6个质量特征(功能性,可靠性,实用性,有效性,可维护性和便携性)及其子特性,可以激发测试人员针对什么是好的、恰当的、有价值的这些问题进行讨论。但是更好的是我们需要真正的测试来找出这些价值。这类测试同样也需要时间和计划来很好地执行,如果想做得更好地的话,就需要更长的时间。

 一个解决方案中的所有非功能特性都是设计层特性,并且通常不能在迭代中演变。需要预先对其进行讨论,而且需要在解决方案确定时尽快讨论,是的……在解决方案设计确定时尽快讨论。如果这些特性在最开始没有被正确嵌入的话,那么它们最终永远都不会在测试中被找到。单元测试能做这些吗?当然不能!

  "噢~~~,这就是为什么我们做验收测试驱动开发啊!"你说。我同意,但是我们往往并没有将ATDD做好,我们只关注客户所知道和所问的内容,而没有关注前期需要考虑和捕获的内容。

  "那我们就只关注功能吧。"这是我经常听到的一句话,往往让我感到厌烦……这意味着很难想到其他的事情,我们只好继续前行,并祈祷它是对的。你是否"曾经"听过"忽略"敏捷呢?敏捷就是要从一开始就把事情做对。

  测试通过静态测试从一开始就协助建立正确的解决方案。静态测试是"不通过执行代码来测试解决方案"。静态测试之美在于它可以在任何时间和任何地点执行。静态测试应该在解决方案的第一个想法产生时执行。理想情况下,应该有个测试人员提出这样的问题:"这是功能不错……但你是如何确定它是有价值的呢?"通过问题,图表和该解决方案的计划来测试该概念以查看它是否真正交付了所需要的解决方案,这是产品生命中至关重要的一部分。

  我们还可以测试交付计划,关注风险、时间以及各组件间的依赖,以及如何利用不同等级的"完成"来证明我们正在往正确的解决方案行进。往"很好地完成"的方向上定义"完成"需要正确的人在工作初期就参与进来,而不是在编码已经开始之后。测试计划是至关重要的——是否定义了正确的环境、团队、资源和方法来交付价值?这是一个问题,但往往并没有在编码前得到回答。这个奇妙的新测试制度的存在引发了这个问题,并且所有人都在前往下一步之前就把它回答了。

  测试计划的完成可以通过使用测试设计技术预先定义接受标准。你可能会喊道:"什么???已经开始测试了???"是的,完全正确。如果不提前执行的话,那测试人员获取的那些培训和证书又有什么意义呢?你看到测试人员所做的大部分测试执行活动都是他们基于风险和测试设计技术规范而形成的测试设计活动的结果。概念、特性、长篇故事和用户实例其实都只是规范在不同名字下的转译。更好地,在理想的敏捷世界里,测试人员会参与到需求定义中,这样他们就能够静态测试它们,然后可以在任何人试图实现一行代码前对其应用动态技术。

  接下来,我们开始真正的工作(轻笑……任何人如果觉得编码前的工作不是工作的话,那他并没有理解工作的概念),我们开始编码,做单元测试,改进代码,做集成测试,将代码发布到测试环境(咚,咚,咚……鼓声响起)……我们开始尽全力寻找紧急行为!

  紧急行为——这是测试人员在敏捷队伍中的真正价值:关注模块、代码和用户故事如何结合在一起从而交付所需要的功能。但是我们都知道这些地方往往是那些重要bug的藏身之处。bug只有在我们开始多方位查看解决方案时才会露出端倪。测试人员的技能就是在系统中根据客户需求和路径风险设计这些路径,利用测试技术定位需要关注的重要区域。这里是决策表和有限状态模型(比如:N-1切换覆盖)真正发挥作用的地方。那些在单元测试或集成测试时没被发现的缺陷,会让验收测试立即崩溃。

  在系统测试过程中,设计测试发掘具有风险的紧急行为,提供具有实践经验的证明来评估覆盖率、遗留风险、缺陷密度、开发进度等其它质量属性也是测试人员应该具有的技能。当然我并不是说开发人员或BA不能做这些,只是他们太过忙于自己的工作,往往没有时间或精力去想这些。同样我建议测试理念和技巧在计划、执行和报告这些问题上是最有效和高效的。

  这把我们带到了确认和验证的讨论。它们的不同点到底在哪里?验证是确保所建立的东西是正确的——符合标准,遵循模式,在正确的时间做正确的事情。确认在另一方面是定义正确的事情是什么!确认和验证这两个部分都必须完成,测试给了我们完成这两部分的技术和技能,同时也允许我们将这两部分覆盖到系统需要的各种属性上(例如质量)。

  下一个问题是"那我们还需要测试人员吗?"恕我直言,--需要!!!为什么?因为测试实践人员所想的与团队里的任何人都不一样。测试人员是"专业的悲观主义者"(ISTQB基础教学大纲)。好的测试人员会花费时间关注潜在的问题,而非潜在的解决方案。从一开始我们就考虑坏的消息——到底哪里会发生严重的问题,如何快速定位问题,甚至如何去阻止问题发生。这和敏捷概念中的"快速失败"和尽早理解风险这两点完美切合。我们需要这样的思想观念尽早地参与到项目和解决方案设计中,从而让我们能够尽快并尽可能多地发现潜在障碍。

  真正拥有足够多的测试知识,能够准确计划测试工作的人并不多,而敏捷团队中需要关注的哪里和何时需要测试的东西又太多。在用户故事等级测试,迭代等级测试和特性等级测试之间应该有个明确的界限;还记得之前讨论过的"完成"的等级吗?由谁,在哪里,何时完成哪一部分测试都需要明确地确定出来,以保证所有的环境、工具、技术、数据和人员在执行时的有效性。测试(就像大部分事情一样)在好的团队中并不是偶然发生的……好的测试会做优秀的计划。优秀的测试需要杰出的计划。在该计划中,需要紧密地考虑测试人员和测试以保证所有相应的安排都建立到位。

  你是否会问:"那测试人员如何做到这些呢?"大部分人认为测试只是测试执行,但是在现实世界中,你所看到的那小部分测试是测试中最简单的。执行测试用例花费了总体测试工作大约25%的时间。大部分测试是在思想和文档中完成的。"天哪!"……你被震惊了……敏捷不是说了吗:"可工作的软件胜过面面俱到的文档"!没错!但是测试可以在任何或全部文档中发生(故事实例、白板设计、验收标准等)。第一个也是最大的一个障碍是,人们或整个团队不愿意定义什么是"很好地、价值、完成",或者由于太难而不愿将它们细化。

  多样的团队允许我们掌握每个方面最好的那一部分。特意排除某组技能或某组知识是幼稚的,非常不成熟的行为,且不能提高解决方案或方法的长期性。一个完整的并且拥有能够在最好的可能时间以最优惠的可能价格交付最好的可能解决方案所需要的所有技能的团队,才是完全聪明的、优秀的业务团队。认识到团队中其他人的技能,并将它们最大化发挥出来也是聪明的举动。

  那测试人员需要有自己特有的团队吗?不需要……敏捷项目中的任何人都可以成为测试人员,事实上,敏捷项目中的所有人都是测试执行者。主要问题是,团队中的所有人都需要遵守纪律,为了完成必须的所有测试活动(不单单是测试执行)他们需要在日常工作中时刻做到"测试先行"。如果团队没有在他们的工作产品、方法和解决方案中花费时间或精力计划、设计并应用测试,那团队将无法知晓他们的进程以及他们所面临的问题。

  因此我能留下的建议是:

  确保整个团队对每个层次"完成"的定义有个明确且一致的理解——自己的任务、用户故事、迭代、发布、项目和产品

  确保整个团队对这个产品的"质量"概念有个明确且一致的理解——是什么构成了"可工作的软件"

  测试并不只是敲击键盘以期找到缺陷,也不仅仅是执行单元测试

  测试是整个团队的责任,应该从第一个概念的讨论开始,并涵盖敏捷项目中的所有方面

  尽早测试,并且经常测试——等到所有工作完成之后才开始想到测试是错误的

  静态测试(检查每一块工作以确保其达到质量要求)比执行测试用例更有价值

  设计好的测试是个专业活动,敏捷团队中任何人都可以做到,但是需要一个正确的理念

  测试在敏捷中是否灭绝了呢?是的,但那是传统的,过时的,生命周期测试末期的测试。新的,完整的,预先的,积极参与的,挑战思想模式的,挑战现状的,并允许团队交付…交付价值,交付 "可工作的软件",交付客户真正想要的解决方案的测试将会永存。



五大敏捷原则——可以应用到每一种类型的开发过程

  一些专业顾问可能不希望你知道的东西:

  你并不需要在你的开发过程中作出重大改变就可以从敏捷原则得到很多好处

  如果你花时间去真正了解敏捷(而并不只是在网络上重复的徘徊于支持和反对中),你就会认识到事实上敏捷开发并不是一种方法论,而是一种可以应用于每个软件开发的方法。当然,像SCRUM(Scrum 是一种迭代式增量软件开发过程,通常用于敏捷软件开发)和 XP(Extreme Programming 极限编程)的方法都旨在制定敏捷原则的具体使用,但这并不意味着你可以通过这些工作方式来获得的敏捷开发的全部或大部分好处。

  一些工作中使用到了敏捷可能你没有注意到

  几个月前我们在与客户交谈的过程中,客户告诉我们,想要在工作中使用敏捷方法,但是在他们的团队中没有足够的时间实施SCRUM。该团队的经理提及曾经与一个SCRUM 顾问谈及敏捷开发的的实施,但是在进一步的考虑之后,他决定最好等待,直到当前产品发布,要在接下来6 到9 个月的时间实现所有必要过程的变动。

  顾问的建议给经理留下了非常深刻印象,他要求团队做出小的变化同时开始实施的一些顾问建议的想法。因此,每天早晨在喝咖啡和吃点心之后开15 到20 分钟小会议以及他们开始组织2或3人的程序员团队并使其尽可能在短周期内完成任务,而不是让每个程序员单独完成这样可能需要长达6 到8 周的时间才能完成的任务。

  他们所做的另一件事是让测试人员更早的介入工作,更紧密地与开发人员合作,在编码阶段开始,测试人员将对尚未完成的产品执行初步测试,也告诉程序员一些他们如何改善单元测试和集成测试的想法。作为这个过程的一部分,程序员也学到如何在提交修改之前自己进行部分的手工测试作为内部健全检查的一部分。

  最后,经理要求整个团队在每个月的月底与产品营销人员安排一个正式的会议,并将演示相关特性功能的开发进展。在这些营销会议提供的反馈仍然可以实现当前版本发布而不延迟版本发布。经理告诉我们,自从他们开始用这种方式工作,大大提高了团队的生产力和工作气氛,他真的很期待他们的团队实现SCRUM。

  他不理解的是,他们的工作方式并没有做任何革命性的改变,他们就已经实施了部分的敏捷开发并且从中体验到敏捷的好处。

  小的变化和改进之路

  这个经理的故事是一个很好的例子。如何在你的整个工程中使用小的改变来实现敏捷就能实现很多你想获得的结果并不需要开展一场彻底的革命。

  以下是一些想法,可以从上面的故事得到证明,我们相信,无论你的团队目前正在使用哪种开发方法都可以快速实现敏捷。

  (1)小/更小块的工作

  把工作分解成更小的,更易于管理的块,而不是少量的非常大的需求或任务,可以在更短的时间间隔内(数天或数周)完成。通过这种方式确保任务不比你原先分配的占用更多的资源(因为如果你的计划设想开始在工作中出错,你会在2周内而不是2-3个月才发现它),最重要的是,你会更快地交付功能给测试人员和产品营销人员,并得到及时反馈,进行必要的修正和调整,而不会影响你的发布日期。

  (2)增加程序员和测试人员之间的协作和沟通

  如果这个想法是为了使开发人员尽快得到功能的反馈,那么最好的办法是更早开始测试,很多时候,即使是在平行开发时也是如此。

  你可以通过多种方式实现这一目标,例如通过一准备好部分功能就邀请测试人员直接在开发环境运行其测试,(而不是等到所有部分都完成的时候)。

  另一种方法是测试人员与开发人员合作来计划和写单元和集成测试的方式,这将有助于测试人员更迅速地捕捉到更多的错误。最后,如何能让我们开始教程序员怎样运行少部分的由测试人员编写的手动和自动测试程序,作为他们在提交代码之前的健全性测试的一部分?我们看到很多的团队,在开发人员提交代码的主要分支之前他们需要运行开发自己的测试集进行测试。

  (3)有更多的自动化测试以及更多经常运行它们

  这是应用敏捷的团队的首要原则之一,事实上,也是符合每一种类型的项目逻辑。作出承诺,有意识地投资自动化。

  首先,指导你的开发人员为每一个新功能或重要的错误修复,创建单元测试和集成测试。

  你也可以让你的测试团队创建自动测试,以覆盖尽可能多的产品,并指导你的开发人员使用这个功能的自动化更简单,更强大(例如,通过使用GUI 元素中正确的仪器)编码方法。

  但是,创造你的测试是远远不够的。你需要有一个框架,尽可能多地运行这些测试,并在测试发现缺陷时即时反馈给程序员。

  现在,有很多很好的持续集成框架(如 Jenkins1,Bamboo2 或TeamCity3),所有这些都可以利用我们强大的API 集成到实践测试中。最后,你也将确保你的程序员遵守"你把它弄坏了,立刻你修复它!"的黄金规则。

 (4)寻求快速反馈和持续改进

  改善最大的敌人是人类行为:没有人喜欢被批评,我们指的就是没有任何一个!

  这就是为什么每当我们在做某件事,我们不愿意展示给别人,除非我们认为它已经完成了,我们的观众能够"完全"理解我们所做的。

  但正如你可能已经明白,这是反作用于编程的,因为如果我们等太久才得到反馈,我们不可能实现任何变更而不错过我们的交付目标。

  那么,你能做些什么呢?

  基本上,克服害怕被批评的心理,作为一种政策要求,在工作中每个人展示给其他团队成员以及产品行销人员他的工作过程。

  营造一种企业文化让人都知道如何给予和接受反馈。你通过确保反馈针对的是工作,而不是人,同时让人反馈产品的好和坏的方面(而不是只集中在需要修复的部分)来可以实现这一目标。

  起初,这可能不是一件简单的事,但它会随着时间的推移会变得容易,从中获得的价值简直是不可思议的。

  (5)拥抱变化和有序工作

  这可能是敏捷实现的基石,无论你如何努力工作规划你的项目,无论你有多擅长,最终事物会改变,你需要调整你的计划。

  但是,除去口号,你该怎么拥抱变化呢?

  首先,计划要少,不要深入但是要有,减少长期的,因为你无法准确地预见现实到底是几个月。

  寻求反馈宜早不宜迟,确保,如果你不得不改变功能和计划,你在2.4周时知道,而不是6至9个月。

  为改变做计划,并确保你的团队知道,变化确实会来,而且它会被接受,这使得他们当他们面临着这一现实和需要时,更容易应付它。

  小的变化应该是你工作方法的一部分

  你可以从敏捷的理解中获取最好的原则之一,正如产品和需求是不断变化的,所以你的工作流程应该是动态的,自适应。

  能接受被提问关于你是否工作在最好的和最有效的方式,或者是是否你能在过程有或大或小的改进?

  能接受反馈,寻求它,甚至奖励给出反馈的人。一旦你能够引入接受反馈的企业文化,你将看到如何真正开始改善,甚至是他们自身。

  注:

  1、Jenkins,之前叫做Hudson,是基于Java 开发的一种持续集成工具,用于监控秩序重复的工作,包括:

  I、持续的软件版本发布/测试项目。

  II、监控外部调用执行的工作。

  2、Atlassian Bamboo是一款持续集成构建服务器软件(Build Server)(非开源软件)。Bamboo 的特点: 简单的用户界面容易安装-顺利的话,5 分钟内就可以让运行起来!自动检测你的设置 - 如果你的Server 上使用了Maven,Ant 或者Java 设置, Bamboo 会自动检测他们; 连续的日志 - 监测你的build 的colour coded 日志;容易显示所有项目。

  3、TeamCity是一款功能强大的持续集成(Continue Integration)工具,包括服务器端和客户端,目前支持Java,.NET项目开发。

  TeamCity 提供一系列特性可以让团队快速实现持续继承:IDE 工具集成、各种消息通知、各种报表、项目的管理、分布式的编译等等,所有的这些,都是让你的团队快速享有持续集成带来的效率提升、高质量的软件保障。

  使用 TeamCity,你能够在几分钟之内为你的项目配置一个构建服务器,它内建了持续单元测试,代码质量分析和早期的构建问题分析报告,你甚至可以在IDE 进行。

  TeamCity提供平滑的学习曲线,你可以逐步的学习经它的高级特性和功能,你很快就能加强你发布管理实践。本次发布,在可用性作了大量的改进,更新的IDE 插件支持 CVS 和SVN,另外还包括一些之前版本不具备的企业级的特性。



产品的性能测试

 项目的情况简介:

  项目属于客户端/服务端模式产品,要求每个服务端能支持连接500个客户端

  测试环境简介:

  服务端支持三级连接模式,每个服务端能支持连接500个客户端,总要求支持大约5000个客户端。

  测试的过程描述:

  在测试实验室中,只能搭建10个客户端的环境以及三级连接的环境。服务端初次连接客户端后,客户端会保留服务端的IP地址。下次客户端机器启动时,会自己连接服务端。每次连接属于短连接。在产生事件时,客户端会自己上报给服务端。

  测试过程遇到的问题:

  在实验室中测试系统稳定可用,但在用户那里遇到服务端异常退出。

  问题分析:

  客户端同时大量上报事件时,服务端处理出问题,导致系统异常退出。

  希望寻求的帮助:

  如何模拟多客户端问题?如何进行产品的性能测试?如何保证产品的稳定性?

  分析一:

  作者:多瑙河

  分析内容:

  很简单,这种情况,用loadrunner最合适了,用loadrunner这种压力测试工具,模拟多用户环境,不知道你们是用什么语言开发,如果是java的甚至可以利用loadrunner的Tunning组件,达到代码级的调优。如果是C#.net,那很要等啦,Mercury同意支持C#.net,但支持版本还没有出来。我在给你个建议,找个系统整合专家,看看是不是他们的网络有问题,或者是服务器没有调试好。有时候,机子CPU多,没有调试好,可能大量的CPU资源用于频繁的调度,而造成系统异常。有时候,还要改进算法。这种系统调试最麻烦了!

  分析二:

  作者:关河

  分析内容:

  个人意见:对这个问题的分析应该考虑两个层次:

  1、解决现有问题的层次;

  2、探讨测试不充分问题产生的根源并从根源上避免此类问题的发生。 这个问题本身是比较好解决的,在现场出现问题后,我们要做的是利用实验室的环境(或者现场的环境)确定问题产生的原因,从例子的描述来看,应该是在客户端大量建立连接时服务端无法支持,产生异常退出。对该问题的定位可以用LR等性能测试工具(或是自己编写的工具)模拟进行大并发量的突发连接测试,并据此给出改进的方法。

  其次我们还应该探讨测试不充分问题产生的根源。在这个例子中,由于设备不足够,可能根本就没有进行压力和负载测试,这本身就留下了隐患。其次,作为测试负责人,对这种项目的经验不足,一般来说,基于短连接方式的C/S结构应用最大的可能出问题的地方就是大量用户同时进行连接操作,即使没有环境在实验室中进行测试,也必须把这个作为一个大的项目风险列出,要求在交付最终用户使用前进行这类测试。

 分析三:

  本案中,作者的描述有些歧义:

  1、"三级连接模式",不知道是不是有服务器,有端站,有客户端的模式,还是采用了服务器集群,多台服务器分三级级连

  2、"每个服务端能支持连接500个客户端,总要求支持大约5000个客户端。"

  3、"服务端初次连接客户端,"这个不知道是不是应该是"客户端初次连接服务端",而书写的当时,思维太快了,手没跟上,请教开发工程师都说"一般都是客户端去连接服务端的"拉"模式,而极少服务端向客户端"推"的模式。"

  4、"在产生事件时,客户端会自己上报给服务端",不知道是不是以发送日志文件的形式上报。

  5、"在实验室中测试系统稳定可用",实验室中测试是不是只有10个端站的情况下,而并没有采用任何的测试工具来做模拟端站和用户,已达到实际需要的量级。

  6、"下次客户端机器启动时,会自己连接服务端。"这个连接,是指自动登录还是会同步数据或者仅是网络连接?

  所以,对于本案编者只能按照性能测试的一般做法做一个介绍,不能详细的分析本案为什么会出现了不稳定运行的状况了,希望能对本案作者及遇到相同问题,或者准备做性能测试的同行们有所启发。

  首先,我们为什么做性能测试呢?

  性能测试的目的:

  一、评估系统的能力,测试中得到的负荷和响应时间数据可以被用于验证所计划的模型的数据处理能力,并帮助作出决策。

  二、识别体系中的弱点:受控的负荷可以被增加到一个极端的水平,并突破它,从而修复体系的瓶颈或薄弱的地方。

  三、系统调优:重复运行测试,验证调整系统的活动得到了预期的结果,从而改进性能。检测软件中的问题:长时间的测试执行可导致程序发生由于内存泄露引起的失败,揭示程序中的隐含的问题或冲突。

  四、验证稳定性(resilience)可靠性(reliability):在一个生产负荷下执行测试一定的时间是评估系统稳定性和可靠性是否满足要求的唯一方法。

  性能测试类型包括:

  负载测试:负载测试是一种性能测试指数据在超负荷环境中运行,程序是否能够承担。

  强度测试: 强度测试是一种性能测试,他在系统资源特别低的情况下软件系统运行情况。

  容量测试:确定系统可处理同时在线的最大用户数

  性能测试观察指标:

  性能测试主要是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。负载测试和压力测试都属于性能测试,两者可以结合进行。通过负载测试,确定在各种工作负载下系统的性能,目标是测试当负载逐渐增加时,系统各项性能指标的变化情况。压力测试是通过确定一个系统的瓶颈或者不能接收的性能点,来获得系统能提供的最大服务级别的测试。

  在实际中作中我们经常会对两种类型软件进行测试:bs和cs,这两方面的性能指标一般需要哪些内容呢?Bs结构程序一般会关注的通用指标如下(简):

  Web服务器指标指标:

  1、Avg Rps: 平均每秒钟响应次数=总请求时间 / 秒数;

  2、Avg time to last byte per terstion (mstes):平均每秒业务角本的迭代次数 ,有人会把这两者混淆;

  3、Successful Rounds:成功的请求;

  4、Failed Rounds:失败的请求;

  5、Successful Hits:成功的点击次数;

  6、Failed Hits:失败的点击次数;

7、Hits Per Second:每秒点击次数;

  8、Successful Hits Per Second:每秒成功的点击次数;

  9、Failed Hits Per Second:每秒失败的点击次数;

  10、Attempted Connections:尝试链接数;

  11、CS结构程序,由于一般软件后台通常为数据库,所以我们更注重数据库的测试指标:

  12、User 0 Connections:用户连接数,也就是数据库的连接数量;

  13、Number of deadlocks:数据库死锁;

  14、Butter Cache hit:数据库Cache的命中情况

  当然,在实际中我们还会察看多用户测试情况下的内存,CPU,系统资源调用情况。这些指标其实是引申出来性能测试中的一种:竞争测试。什么是竞争测试,软件竞争使用各种资源(数据纪录,内存等),看他与其他相关系统对资源的争夺能力。性能测试的流程步骤和做其他的测试没有什么区别,做性能测试也要如下步骤来做:

  1、测试需求分析

  2、测试设计

  3、测试脚本开发

  4、测试实施

  5、测试结果分析

  测试需求分析,性能测试(或者其他的测试)做的好与坏完全取决于测试分析做得好不好。软件最终始要被应用的,要在应用的实践中考验,所以,任何类型的测试分析都要以实际业务的要求为依据。那么,性能测试的测试需求分析都需要分析哪些内容呢?

  1、性能测试的需求来源。客户需求和期望,实际业务需求,系统需求。

  2、业务数据量级,要根据实际业务分析可能出现数据吞吐瓶颈的地方,比如本案中作者提到的要求每个服务端连接500个客户端,总要求连接5000个客户端。分析到这个程度还不够,还要进一步分析业务操作集中的点,时间段和量。如,本案中客户端开启会自动连接服务端,那么在每天开始上班的时候客户端的开启就会出现峰值,可能会持续20分钟,服务端需要响应客户端的连接请求,请求还可能并发至少 5000/120次每秒,同时短时间内集中请求的频率也是有阈值限制的。

  3、系统架构,在每种不同的系统架构的实施中,开发人员可能选择不同的实现方式,造成实际情况纷繁复杂。我们不可能对每种技术都详细解说,这里只是介绍一种方法提供给你如何选择测试策略,从而帮助分析软件不同部分的性能指标,进而分析出整体架构的性能指标和性能瓶颈。

  4、测试策略和评估标准,任何测试的目的都是确保软件符合预先规定的目标和要求。性能测试也不例外。所以必须制定一套标准。通常性能测试有四种模型技术可用于评估:

  * 线性投射:用大量的过去的,扩展的或者将来可能发生的数据组成散布图,利用这个图表不断和系统的当前状况对比。

  * 分析模型:用排队论公式和算法预测响应时间,利用描述工作量的数据和系统本质关联起来

  * 模仿:模仿实际用户的使用方法测试你的系统

  * 基准:定义测试和你最初的测试作为标准,利用它和所有后来进行的测试结果进行对比

  测试设计,测试设计是在了解软件业务流程的基础上。设计测试用例的原则是受最小的影响提供最多的测试信息,设计测试用例的目标是一次尽可能的包含多个测试要素。这些测试用例必须是测试工具可以实现的,不同的测试场景将测试不同的功能。因为性能测试不同于平时的测试用例,尽可能把性能测试用例设计的复杂,才有可能发现软件的性能瓶颈。

  测试脚本开发,性能测试是通过工具,模拟大量用户操作,对系统增加负载。所以需要掌握一定的工具知识才能进行性能测试。大家都知道性能测试工具一般通过winsock,http等协议纪录用户操作。而协议选择是基于软件的系统架构实现(web一般选择http协议,cs选择winsock协议),不同的性能测试工具,脚本语言也不同,比如rational robot中vu脚本用类c语言实现。

  开展性能测试需要对各种性能测试工具进行评估,因为每一种性能测试工具都有自身的特点,只有经过工具评估,才能选择符合现有软件架构的性能测试工具。

  测试结果分析,运行测试用例后,收集相关信息,进行数据统计分析,找到性能瓶颈。通过排除误差和其他因素,让测试结果体现接近真实情况。不同的体系结构分析测试结果的方法也不同,bs结构我们会分析网络带宽,流量对用户操作响应的影响,而cs结构我们可能更关心会系统整体配置对用户操作的影响。



2013年5月14日星期二

Session对性能测试的影响

Session介绍

  Cookie是Web产品测试过程中不可缺少的一部分,我们需要通过Cookie信息辨别用户,得到属于自己的结果数据,例如DWR接口测试过程中,需要在请求头信息中传入测试用户的cookie信息,才可以得到该用户学习的课程,发表的博客,或者关注的用户等。Cookie信息通过模拟登陆操作就可以获得。但是,你有没有注意到你获得的Cookie是由什么组成的?是否包含NTES_SESS信息,是否包含SessionID信息?

  NTES_SESS是URS返回的Cookie信息,NTESSTUDYSI是云课堂返回的Session信息,NTESSTUDYSI存储SessionID信息,不同的产品会配置不同的变量名。这个信息对于接口测试来说并不是必须的,但是却会在性能测试过程中起到很关键的作用。Cookie和Session有什么区别,为什么性能测试过程中必须需要Session信息?下面,我们一一阐述:

  Cookie是什么:

  cookie是小甜饼、小型文本文件,因为HTTP协议是无状态的,浏览器无法区分这次请求来自于哪个浏览器,因此产生了随着HTTP请求一起被传递给服务器的Cookie信息。Cookie是保存在客户端的,存在内存中的cookie,浏览器关闭后就消失了,存在时间是短暂的;存在硬盘中的Cookie,但存储时间长度超过过期时间或者用户手动清除时,cookie信息会消失。

  Session是什么:

  Session是会话,当用户第一次对网站服务器发生请求时,服务器会创建Session信息,生成SessionID用来唯一标识用户,并会把该SessionID返回给客户端浏览器(只存在内存,并不存在硬盘中),在会话结束之前的每次请求,浏览器会自动将该SessionID附加在请求头信息中,服务端接受请求时,检测是否存在SessionID(不存在或者Session过期都会重新生成Session),并通过该SessionID以键值对的方式查询用户信息。服务端的Session使用类似散列表的结构存储用户信息。

  Session的常见实现形式是会话Cookie(Session Cookie),即未设置过期时间的Cookie,这个Cookie的默认生命周期为浏览器会话期间,只要关闭浏览器窗口,Cookie就消失了,这种形式的Session是和Cookie绑定在一起的。而平常所说的Cookie主要指的是另一类Cookie——持久Cookie(Persistent Cookies)。持久Cookie是指存放于客户端硬盘中的Cookie信息(设置了一定的有效期限)。持久Cookie一般会保存用户的用户ID,该信息在用户注册或第一次登录的时候由服务器生成包含域名及相关信息的Cookie发送并存放到客户端的硬盘文件上,并设置Cookie的过期时间,以便于实现用户的自动登录和网站内容自定义。

  我们在执行接口测试之前,首先会通过URS得到用户Cookie信息,这份Cookie信息中至少会得到NTES_SESS字段对应的Values值,如果在获取Cookie时,我们同时跳转到产品页面,向该产品服务器发送请求(例如云课堂),那么在我们得到的Cookie信息中同样存在NTESSTUDYSI字段,该字段就是该产品的Tomcat服务器产生的32位的SessionID +jvmRoute设置的后缀名。在做接口测试时,如果请求头中没有传入SessionID信息,那么每次执行时,Tomcat都会重新生成一份Session;即便你传入该SessionID信息,如果SessionID过了超时时间设置,Tomcat还是会重新生成一份,Tomcat默认的Session过期时间为30Min。

  性能影响

  虽然只是一个小小的SessionID,却会对性能测试的产生很大的影响:

  1、Session缺失:

  在做Lofter产品的性能测试时,测试getHomePage接口,发现响应时间比较慢,JVM内存在测试过程中一直增长,Young GC收集不过来,Old区内存不断增长,最终会导致频繁Full GC,使用Jmap定位到堆内存中java.util.concurrent.ConcurrentHashMap$Segment对象不断增加,但是并不知道这个对象时谁在什么时候产生的。我们Dump出来此时的堆内存,使用MAT (Memory Analyzer Tool)工具进一步分析,到底是什么操作产生了大量的ConcurrentHashMap$Segment。

  由上图可以看到这个对象是由org.apache.catalina.session.StandardManager产生的,session.StandardManager就是存储Session的容器。


 通过了解Session的原理得知,我们在测试过程中,只是传入了Cookie信息,在Cookie中没有包含SessionID信息,所以每次请求时,Tomcat都会检查是否存在该标识信息,如果没有则会创建。如果我们测试过程中有几十万次请求,那么Tomcat会创建几十万个Session信息,假设一条Session需要2K的数据,那几十万的Session可能会使得Session容器占用上百兆的空间。同时需要注意,因为我们每个请求都会创建Session,这个Session是创建了以后不会被使用的(下次请求中依然没有携带SessionID),即垃圾Session,但是垃圾Session在过期之前是会一直存在内存中的,默认的Session保存时间是30Min,这样的垃圾Session会在内存中保存至少30Min,如果在这30Min中内我们不停的发送请求,Session容器占用的内容空间会 不断扩大,最终会影响我们的测试结果。

  2、Session过期

  即便我们在请求中加入了SessionID,但是还可能会产生不停的创建Session问题,这是为什么?因为Session是存在过期时间的,默认的Tomcat中web.xml中设置的session过期时间为30Min,如果我们得到的SessionID在30Min后使用,依据Tomcat的Session机制,首先会检查是否存在SessionID,如果有的话,检测是否过期,如果传入的SessionID已经过期,Tomcat还是会每次都自动生成Session信息。

  Mark,Session的过期时间有三种设置方式:一种是Tomcat的配置文件web.xml中设置,一种是webroot项目代码中的配置文件web.xml中设置,一种是代码中设置session.setMaxInactiveInterval(15*60),所以我们在测试中要记得检测和确认这三个地方。

  3、SessionID后缀不匹配

  在测试云课堂项目中,我明明已经修改了每个地方的Session过期时间,请求中传入了没有过期的SessionID,可是为什么还是会不停的创建Session?

  一般我们的产品架构是Nginx+Tomcat方式,静态请求走Nginx,动态请求通过Nginx访问到Tomcat。Nginx处理Session采用了session sticky方案,需用到第三方模块jvm_route,需要在Nginx的配置文件中upstream.conf中设置:

upstream study {
server 10.120.36.68:8010 srun_id=qa18-8010;
server 10.120.36.97:8010 srun_id=qa19-8010;
jvm_route $cookie_NTESSTUDYSI reverse;
keepalive 100;
}

  该配置文件中配置了一个Nginx连接两个Tomcat,当请求过来时,会依据SessionID中的后缀来查找请求发送到哪个Tomcat,例如NTESSTUDYSI=1816E5ECBC052F6ABA420FEE7B06DA86.qa18-8010;就会把带这个SessionID的请求发送到 10.120.36.68(qa18)这台机器上去。

  在qa18这台机器的Tomcat配置文件server.xml中,会设置jvmRoute="qa18-8010",这样保证生成的SessionID的后缀是qa18-8010,如果这个两个后缀不一致的话,同样会出现问题。

  例如如果Nginx配置文件中upstream.conf中设置的srun_id=qa18-8010,而tomcat配置文件中设置的jvmRoute="qatest18-8010",那么获取Cookie得到的SessionID后缀则为qatest18-8010,当发送请求到Nginx时,检测到SessionID的后缀和设置的server服务器无法匹配,则会丢失session,使得发送到Tomcat的动态请求依旧是没有Session信息的请求,造成session丢失,测试过程中还会有session不断的创建。



建立软件测试管理与评判体系的六大过程

  软件测试过程模型或软件测试生命周期模型为我们提供了软件测试的流程和方法,为测试过程管理提供了依据。由于测试过程管理牵涉的范围非常广泛,包括过程定义、人力资源管理、风险管理等,我们仅从前面介绍的软件测试过程模型来介绍软件测试过程管理的思想。

  现代软件测试过程管理不是仅锁定在测试阶段,软件测试过程管理在各个阶段的具体内容是不同的,但在每个阶段,测试任务的最终完成都要经过从计划、设计、执行到结果分析、总结等一系列相同步骤,这构成软件测试的一个基本过程。通过软件测试过程管理我们要尽量达到测试成本最小化、测试流程和测试内容完备化、测试手段可行化和测试结果实用化的理想目标。

  软件测试是软件工程中的一个子过程,为使软件测试工作系统化、工程化,必须合理地进行测试过程管理,包括签订第三方独立测试合同、制订测试计划、组织项目人员、建立项目环境、监控项目进展等等。软件测试过程管理主要集中在软件测试项目启动、测试计划制定、测试用例设计、测试执行、测试结果审查和分析,以及如何开发或使用测试过程管理工具。概括起来包括如下基本内容:

  (1) 测试项目启动

  首先要确定项目组长,只有把项目组长确定下来,就可以组建整个测试小组,并可以和开发等部门开展工作。接着参加有关项目计划、分析和设计的会议,获得必要的需求分析、系统设计文档,以及相关产品/技术知识的培训和转移。

  (2) 制定测试计划

  确定测试范围、测试策略和测试方法,以及对风险、日程表、资源等进行分析和估计。

  (3) 测试设计和测试开发

  制订测试的技术方案、设计测试用例、选择测试工具、写测试脚本等。测试用例设计要事先做好各项准备,才开始进行,最后还要让其他部门审查测试用例。

  (4) 测试实施和执行

  建立或设置相关的测试环境,准备测试数据,执行测试用例,对发现的软件缺陷进行报告、分析、跟踪等。测试执行没有很高的技术性,但是测试的基础,直接关系到测试的可靠性、客观性和准确性。

  (5) 测试结果的审查和分析

  当测试执行结束后,对测试结果要进行整体或综合分析,以确定软件产品质量的当前状态,为产品的改进或发布提供数据和依据。从管理来讲,要做好测试结果的审查和分析会议,以及做好测试报告或质量报告写作、审查。



如何打造一个理想的测试团队!

一、确认好团队的目标(即该团队未来2-3年或者更长时间内期望发展成什么样)
    测试团队的核心任务应该就是保证自己负责项目的质量,并且通过不断的改进来缩短项目的周期吧!
我们可以先想象下2-3年后,期望整个团队的测试模式是怎样的?
比如:一个新的版本开始后(这里指增量版本),我们确认该版本的测试模式是
1、新增模块在版本前期就开始研究测试方法(比如:单元测试接口测试自动化测试等),并且能够让开发配合提供一些支持。通过这种方式能够覆盖到70%以上的测试点。然后再通过对该模块以及对整个系统的把握,准确的分析出那些可能还是有风险的,并且进行探索性测试和整体场景的测试
2、关联模块的测试点分析出来后能够很快的实现自动化
3、老模块已经全部实现自动化了
4、测试人员发现的问题基本上都能够自己定位,甚至能够指导研发进行修改。研发修改后能够准确的分析出可能有影响的地方,并补充测试

达到这样的程度(或者达到这样程度的80%以上),相信对于版本的快速迭代以及质量都是很有帮助的,而且对于测试团队以及测试人员的成长来说,也是比较好的。
那么,怎样才能够达到这样的程度呢?
1、整个团队自动化的程度非常高,只要是老模块全部实现自动化了
2、整个团队对于产品内部业务逻辑非常清楚,甚至达到研发的程度(不用到代码的每行),能够对研发的设计提出有效的意见,并能够指导研发进行设计
3、整个团队成员的质量意识非常高,会有应该是自己发现的bug结果没有发现感到羞愧的思想
4、整个团队具备前期测试和缺陷预防的能力,能够更开发一起配合在前期就做好相关工作,比如:前期的缺陷预防,测试方法研究等等!

达到这样的程度后,整个团队至少有部分人应该具备如下技术能力
1、自动化开发能力:这样的人员越多越好(至少要有1/3以上),这样能够让自动化成为一种常用的改进技术,让自动化成为一种习惯
2、业务能力:对于产品的内部实现和整个业务逻辑都非常熟悉,能够有效的指导该模块的设计,并且发现该模块的问题能够自己定位。至少每个模块都找得到这样的人
3、单元测试和接口测试能力:能够在前期通过对代码或者借口进行测试,尽量在前期就能够保证质量(需要学习相关的开发语言)
4、对于产品的理解比较深,能够有效的指导产品后面的改进方向
5、项目管理能力,对于一个不大的团队来说有2-3个差不多了

二、挑选合适的人员
理想的测试人员应该具备如下几个特点:
1、有激情:这是杰克韦尔奇最认可的一点,笔者深有同感,相信对生活有激情的人,对工作也同样有激情
2、喜欢测试:有探索未知世界的好奇心,能够在测试中找到成就感。
3、热爱技术并且有一定的技术能力:老实说,测试入门是技术门槛相对比较浅的,但是真的要做到很好程度确实需要比较好的技术,比如:上面的几点,都是有一定的技术门槛的,只有热爱技术的人才会愿意去主动去深入学习技术
三、如何实现目标
1、团队的文化和制度:所谓无规矩不成方圆,如果一个团队要健康的发展,团队的文化和制度是非常重要的。当然,我们团队的文化和制度也是为了更好的实现我们的目标而服务的,比如:我们期望大家主动去学习模块的原理知识,那么我们就可以形成这样的文化和制度。并且有了制度后一定要坚决的去执行(但是可以更加的人性化),然后根据大家的意见去不断的完善制度和管理。没有制度的话很难保证团队的执行力,那样目标也很难实现,所以,这个非常重要,也是一个初入管理者很容易出现的问题
2、业务熟悉:对于早期来说,我们的直接学习对象肯定是开发,学习的资料大概就是需求文档和设计文档,这个时候可以让测试人员每个人负责一个模块,先去学习设计文档,并且要求测试人员自己能够画出该模块的整个业务逻辑图,并且跟研发确认是ok的(要求内部培训和讲解,并请研发过来旁听)。然后根据业务逻辑图分析可能存在问题的地方,并结合代码进行详细分析(这个时候可不要求测试人员具备单元测试或接口测试能力),后面测试的过程中发现问题后,自己能够尝试的定位问题,并且完成一份模块的定位问题经验文档(后面随着自己的深入学习来不断的完善)

3、自动化:自动化的起步确实是很难的,刚开始的成本很高,再加上项目的工作本身也比较紧,这样很容易让团队对自动化望而止步。但是,经验证明自动化的工作确实是越早开始研究越好。一个比较好的方法是团队负责人自己先花时间去分析下,目前哪个功能模块的测试是重复率最高的,并且实现难度稍微比较小的(模块的选择很重要),然后思考如何去实现自动化(多关注同类产品,看下别人是怎么做的)。确定好怎么做后,如果自己技术比较好的话就自己尝试去实现(推荐方式,当然也会花费自己的一些额外时间,但是肯定是值得的),如果团队里面有更适合的人的话,则可以自己去承担对方的工作(比如:测试任务),然后让对方投入时间去做这件事情(当然,这个人一定要选好)。等到有效果后(这部分的工作能够节省下来),这个时候就可以利用节省的这部分时间继续做这个工作了(相信上面看到效果后也会提供更多的支持),通过这种方式持续改进应该会比较好
   
4、接口和单元测试:对于整个模块的业务逻辑比较熟悉后,这里需要的另外一个能力就是我们对于开发使用的语言本身也比较熟悉,至少静态走读开发的代码没有太大问题(当然,可能一个团队这样的人不会很多,我们可以先培养这样的人)。并且随着我们的自动化工作已经有了很大效果后(这个时候大家的代码开发能力实际上也比较好了),就可以专门投入人员做这些事情了。当然,这个需要跟开发的配合,但是前面2者做好后,后面的改进其实就是水到渠成的事情了。而且也最好是先完成前面的2点,再开始第3点,毕竟步子迈大了容易扯着蛋

将以上几点的目标进行细化,具体要做到什么程度?怎么去一步一步去做?每一步的完成时间点是怎样的?如何评估是否达成该目标呢?将这些问题搞清楚后就可以开始做了,定期分析和总结,相信应该是能够达成上面的目标的



测试员心中的那个木鱼

每个测试人员的心中都有属于自己的木鱼,每个人的木鱼节奏都不一样,或快或慢、或轻或重。
     刚接触测试工作,就和刚进少林寺的和尚一样,还不能戒掉尘世间的烦恼、琐事,瞧着无节奏的木鱼。想着有没有前途、工资多少、升职机会等等。想东想西,不能静下心来,影响自己的工作。
    
     随着时间的推移,有的人不当和尚了,去还俗了,认为不适合当和尚,去做自己想做的事,也可能有一番成就。还有一部分人依然瞧着自己的木鱼。这时候敲木鱼有一定的节奏了。
     
     敲到最后的,都是行业的专家了,敲木鱼稳健、有节奏感,心静如水,是行业的佼佼者。
     要把自己放空,专心做自己的事情,世上无难事,只怕有心人。努力朝着自己的方向走,坚定不移,会有一番成就。生活有很多浮躁的事情打扰你,就看你怎样对待了。
     测试有时候很枯燥,很多重复,你要把心态放正,静下心来测试。只有心静下来了,才可以发现身边的变化,才能很好地去发现Bug
     在生活中发现问题,测试就如生活。每天发现一点点不同,生活就很精彩,不会枯燥。


软件测试计划和测试方案区别

  关于测试计划测试方案的区别,这里主要从编写目的、定义和层次、编写时间和依据、软件过程、文档内容这五方面来说明,具体内容如下:

  一、编写目的

  制定测试计划目的:按照所制定的测试计划可以有效的计划、执行、跟踪、组织和管理测试项目。具体从一下三方面来说:

  1、领导能够根据测试计划做宏观调控,进行相应资源配置等;

  2、测试人员能够了解整个项目测试情况及项目测试不同阶段所要进行的工作等;

  3、便于其他人员了解测试人员的工作内容,进行相关配合工作;

  设计测试方案目的:软件测试方案的作用非常类似于产品设计说明书(软件概要设计和软件详细设计),开发工程师根据产品功能需求和设计说明来编码实现功能,而测试工程师需要基于产品功能需求和测试方案来设计和执行测试用例。测试方案是从测试的角度去分析或者说分解需求,在方向上明确要怎么测,分析结果就是测试点和测试方法。

  二、定义和层次

  测试计划是组织管理层面的文件,从组织管理的角度对一次测试活动进行规划。它是对测试全过程的组织、资源、原则等进行规定和约束,并制订测试全过程各个阶段的任务以及时间进度安排,提出对各项任务的评估、风险分析和需求管理。测试计划要能从宏观上反映项目的测试任务、测试阶段、资源需求等,它只是测试的一个框架,所以不一定要太过详细。测试计划的内容会因项目的级别、项目的大小、测试级别的不同而不同,所以它可以是一本书那么多,也可以是几张纸那么少,但是一份测试计划应该包括项目简介、测试环境、测试策略、风险分析、人员安排、资源分配等内容。

  测试方案是技术层面的文档,从技术的角度对一次测试活动进行规划工具的设计、测试用例的设计、测试数据的设计。它是描述需要测试的特性、测试的方法、测试环境的规划、测试工具的设计和选择、测试用例的设计方法、测试代码的设计方案。

  三、编写时间和依据

  因为测试流程是按照测试计划阶段—>测试设计阶段—>测试实现阶段—>测试执行阶段来进行的,前一阶段的输出是后一阶段的输入,清楚了他们分别是哪个阶段的产物就知道他们主要的区别了。

  测试计划阶段:测试计划是测试阶段中的第一个阶段,首先将测试作为一个项目来看,应该有一个计划。测试小组组长或测试负责人或具有丰富经验的测试人员就要依据《项目计划》开始编写《测试计划》,其中包括人员,软件硬件资源,测试点,进度安排和风险识别等内容。原则上测试计划的有些内容在需求分析阶段就可以开始编写了,在需求分析形成的《需求规格说明书》通过评审形成基线后完成测试计划。但是对于开发过程不是很清晰和稳定的项目,测试计划也可以在系统设计完成后开始编写。《测试计划》编写完成后需要进行评审。

  测试设计阶段:《测试方案》一般由经验丰富的测试人员设计,测试方案依据《需求规格说明书》和《概要设计说明书》进行设计。其中包括需求点简介,测试思路和详细测试方法等内容。《测试方案》编写完成后也需要进行评审。

  四、软件过程

  测试计划软件过程:项目计划评审通过—>组建测试小组—>评估测试风险—>制定测试计划—>测试计划评审通过—>测试计划维护—>最后在测试结果的评审中,必须要严格验证计划和实际的执行是不是有偏差,体现在最终报告的内容是否和测试的计划保持一致。

  项目开始后,由于测试情况的变化,如需求更改导致测试进度的调整在两周或两周以上、测试资源需求的改变(人员、硬件、软件等)、新技术的引入、新风险的引入、开发过程的改变、交付时间的改变等,可能导致测试计划文档变化。如果发生变更,则由测试组长修改,项目组相关人员评审,评审通过后更新测试计划。

  测试方案软件过程:测试计划评审通过—>设计测试方案—>测试方案评审通过—>依据测试方案设计测试用例—>测试用例评审通过—>依据测试方案搭建测试环境。

  五、文档内容

  测试计划和测试方案的本质区别是内容不同。

  测试计划的核心内容:

  1、进行测试任务划分;

  2、进行测试工作量估计;

  3、人员资源和资源分配;

  4、明确任务的时间和进度安排;

  5、风险估计和应急计划;

  6、测试失败/通过的标准;

  测试方案的主要内容:

  1、测试策略选取,明确策略;测试策略就是如何用最少的资源满足测试质量的要求,既高效、低成本、较高质量的完成测试。

  2、测试子项细分,细化测试特性形成测试子项;将测试计划中描述的方法进行细化,包括要采用的具体测试技术。

  3、测试用例的规划;

  4、测试环境的规划;

  5、自动化测试框架的设计;

  6、测试工具的设计和选择;

  总而言之,测试方案需要在测试计划指导下进行,测试计划提出了"做什么",测试方案明确了"怎么做",方案是对计划的进一步细化和明确。两者既有联系又有区别,概念总归是概念,根据软件项目规格大小以及实际应用环境,测试人员应该具体问题具体分析。