qileilove

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

我的面试经历及思考

现在很多人都已经养成了一个习惯,就是面试前都在网上搜索一些对应公司的基本信息及面试内容,如果有笔试题,一定会第一时间内把那些题都做一遍,然后胸有成竹的去参加面试。我也不例外!既然我都已经查阅过别人的面经,处于礼尚往来考虑,我也需要提供些有用的信息给大家,说说我的这许多次面试经历~不过我已经不记得别人都问了我哪些问题,这也不是我这次分享的重点,我主要是想结合每家公司面试官的出题思路及与求职者互动过程中做的好的和不好的拿出来跟大家晒一晒,吐槽吐槽。
  阿里
  BAT在我心里是高大上的形象,不少求职者趋之若鹜,能进入这样的名企工作的确是很多人的梦想。这次求职经历,我也有过几次与阿里正面交锋。
  小微金服
  14年1月春节前时候,有猎头帮我推荐了阿里小微金服的高级测试工程师一职。其实当时对于自己的定位就是两个路线,一个是去BAT这种技术很强的公司做技术,深耕一下自己的技能,另外一个就是去技术不是很强的公司带团队。阿里在我眼里就是属于有很多技术大牛的公司,有一群的优秀且聪明的工程师在构筑着无比复杂的架构。到了那里,一个女同胞面试我,最开始她担心我最近2年都是在带团队,怕我介意高级测试工程师这个岗位,当然我诚心解释排除了她的顾虑,同时她还担心我以前多是做页面功能测试的,对于APP这样服务端测试比较多的工作不能应付过来,当然我也极力排解她的顾虑。接下来的面试多是问了一些实际测试工作中的场景及设计用例技能,还有就是一些linux命令,以及自动化过程中遇到的困难以及如何解决的,当然这些都是我工作中经常使用到的,自然不在话下,另外还问了一些JAVA的基础,如继承,重写,并当场设计一个student类。而我栽在了JAVA的考察上,细细说来主要原因就是太大意了,我只是直接说了继承就是类的extend,重写就是方法的override,并没有介绍详细的用法,对于student类只是大概设计了ID,name,class三个成员变量,和成员方法名及参数getId(), setId(int ID),getName(),setName(String name),方法体并没有写出来,构造方法也没有写,我觉得太简单没有必要再写了,我跟她讲可以直接考察下具体要实现什么样的student类,她回答我自己想就好。这类开放题目,让我倒是有些措手不及,毕竟工作中都是为了解决具体某个问题而写代码的。后来让我回去了,连二面机会都没有给,跟猎头再三询问结果,结论是JAVA基础太差。对于这次面试我的总结就是准备不充分导致了这个结果,如果想顺利过关就需要多方面准备才行,不管我们工作中能够解决多少的实际问题,面试官都只是关心这短短30~60分钟我们的表现,而且不能大意,要谦虚不能自傲。
  淘宝
  年后电话打过来聊了大概半个小时,问了很多我工作中的事情以及自动化测试性能测试相关的,并且让我介绍了很多我自认为是亮点的内容,自我感觉聊的还不错,但是最终结果还是未通过,再次与猎头沟通没通过的原因,说是HR系统里写的就是不合适,未详细标注,猎头提示很大可能参考了年前那次的结果,因为两次面试时间间隔很短,JAVA基础太差的备注害苦了我。这次面试我的想法是企业方应该多给求职者一点机会,多个角度也许才更能全面的考察一个人,对于一个较长时间没有面试过的人来说可能真的没有准备好,也许这次再问我JAVA的问题,我已经准备的不错了,即便是中间这段时间准备的,至少也能看出一个人善于总结之前的错误积极改进,也不失为一个优点,工作中何尝不是做很多类似的事,遇到不会的不懂的要善于通过学习实践来提高自己。
  中麦通信
  很多人应该都不了解这家公司,那我先简单介绍下,它是第一批拿到虚拟运营商的公司中其中一家巴士在线的全资子公司,成立于2013年,主要负责虚拟运营商相关业务,一家创业型公司。公司也是想找一个能帮他们带领好测试团队确保产品质量的测试经理,因为不是专业的测试人员面试我,而是开发总监跟我聊了很多一些工作中的场景如何来测试的问题,还聊到了一些他们单元测试中的一些难题,如果自动化测试的话如何解决等,还有大数据量如何构造数据及测试等,我的回答应该还如他意,整个面试过程还算比较轻松,然后是VP面试,我主要介绍了我过往的工作内容及业绩,对测试相关的问题问的不是很多,然后介绍了很多公司的规划,特别希望我能加入他们。这不是最让我印象深刻的,让我惊讶的是HR面试谈薪资时还问了很多测试相关的问题,比如自动化测试,性能测试相关的等等,顿时好生敬仰,从没有见过如此懂技术的HR,她居然还说她自己不懂这块的,我当场就说你对这些好了解啊~心想难道是创业型公司在招人时HR也需要先对候选人简单做个技术沟通?后来因为薪资没谈拢,没有去这家公司,不过我只能说给的待遇也还不错,应该比一般的创业公司丰厚些,只不过不符合我的预期。我也非常期望能见到他们的产品,没准以后买他们的SIM卡和服务呢。
  亚马逊
  也是一家高大上的外企,在网上看到他们能提供的薪酬就让人无比动心,正好也有一位猎头联系我,但是我实在对自己的口语没有信心,已经4年多没有讲过英语了,不过猎头说的一句话倒是又勾起了我的极大兴趣,只需要能简单的口语沟通即可,主要是能写和读懂英文邮件和资料,这个我当然还是没有问题的,好吧,欣然接受他的推荐。过了2天,他回复我说亚马逊那边的人嫌我们公司的人技术不达标,真心是还没有开始就被打回原形,也不知道是谁何年何月去面试给亚马逊留下了这么个印象,但是在我看来,最近两年我所在的部门人员技能都相对有极大的提高,对此我极力要求猎头再次与亚马逊那边沟通,应该用发展变化的眼光来看待,再者是针对不同的人应该有不同的考核结果,可惜无果。好吧!就算与它没缘,不过我仍然要讨伐一下亚马逊那边负责招聘的人,这的确是一个比较极端的做法,哪怕电话面试简单聊聊也多少对求职者有更客观的了解,也不至于一竿子打死。
  京东金融
  因为招聘的是这个事业部测试负责人,是测试总监/经理岗位,而帮我内推的也是这个岗位。所以面试官都是从别的事业部找来的,也就是说并不是我的直属上司。一面是个女的,自我介绍之后就问了很多技术上的问题,具体哪些问题我也记不太清楚了,但是唯一让我记忆深刻的一点,就是她在问我自动化实现上,也许是我并没有按照她的意思直接写出自动化代码,而是把如何设计这个自动化测试的框架说了一遍,然后在阐述过程中她也不停的打断我,来表达对我的不满意,说过不止两三次不管以前你干过什么有多么牛,主要看做现在这个岗位是否适合,我的确承认很多公司都很想找一个有同样经验的人不用多少培训就可以立马上手,我询问她们现在有没有使用什么自动化框架(即便是自己实现的)来辅助测试时,得到的答案竟然是自己写了两段代码来做自动化的并没有什么框架,我心里暗自想是否只有她一个人在做自动化,也只有她一个人能运行自动化呢?我觉得能写出几段代码并不能判定这个人适合做测试总监/经理,而更适合是对工程师的考察,对测试更宏观的方面的考察可能显得更重要。二面是个男的,也聊了大概一个小时,问了很多项目及管理中的问题,还针对某个项目整个测试流程都阐述了一遍,基本上算是把我工作中处理的很多事情都聊了一通,当然中间也夹杂一些技术上的考察,整体感觉还不错,面试官也非常nice,中途还问我是否需要休息下,他说毕竟面试是非常累的,不过的确我头都有些晕,这段时间精力是绝对集中。当时面试完时间是差不多5点多了,从第二个面试官透露出来的信息是还需要见一下事业部负责人,我也自己感觉虽然第一面不是很理解,但是二面应该可以扳回一局,就这样回去等通知了。可遗憾的是,居然面试没通过,原因是编程能力不行,好吧~我这次是真的无语了。公司我们部门整个自动化工作都是我来主导的,包括框架的设计实现及case的编写我都有参与,应该写过的代码行数不低于1万行吧~居然落得这个结果!都怪我没有直接在纸上把代码写出来,不过说实话,没有在eclipse这样的工具里而是在纸上直接写代码倒真的没有啥感觉不知道如何下手,平时也很少这么干。

 中体彩
  一家国企,我去面试其实也是想见识见识搞IT的国企特别是搞体育彩票的到底是个什么情况。工作环境很一般,办公地点装修的也比较普通,并没有想象中那么豪华大气,整个面试过程感觉里面的人还是比较不错的,因为当时猎头推荐的是高级测试工程师的岗位,面试前其实我也担心给不了我期望的薪酬,但是猎头说薪水应该是没有问题的,所以不妨一试。在跟HR沟通过程中了解到国企倒还真不错,有很多福利,过年过节礼品卡自然少不了,高温补贴啥的都有,只不过自习主席上台,福利也有所缩水,但相对于其他民营企业还是有优势的。他们那叫一部二部什么的,跟当时那个部的技术老大聊的时候也谈到离职原因,我说是职业发展瓶颈,他提到这里已经有一个测试经理,负责所有测试人员的管理,当然我也可以辅助他,但是如果他在这里的话,我还是没有机会的,然后我就说一个企业要收揽人才的话,事业/待遇/环境/感情几个方面都可以下功夫,我并不是特别在乎title什么的,如果待遇上能如我意,也是没有问题的。不过他提示应该达不到我的要求,然后让HR跟我谈,谈的时候我也说了自己最低可以接受的范围,然后让我回来2周后需要跟这个部负责人面试,当时这个人在出差不在,就回来等通知了,目前为止都没有消息,我想是因为待遇问题吧。
  京东广告
  招聘的也是事业部测试负责人,第一面倒是面试官不少,共3个,应该也是其他部门的测试负责人吧。在面试过程中,多是一个人在问,另外2个人问了两三个问题吧,多是功能测试方面的,自动化测试及其他技能涉及较少,与他们聊的也还挺开心,还有说有笑的,更像是在讨论。二面是技术总监,只问了3个问题,具体内容也不再说了,我想说的是三面。前两轮面完后也回来等HR再约三面,即与事业部VP面谈。在HR通知我说三面时还强调了下主要是面试管理方面的技能,让我准备一下,其实我下来还花了不少时间在总结最近2年来如何进行项目及人员管理的,还专门在纸上列出一个思维导图,从各个方面分析我是如何来做的,但是到了那里却没怎么用上。话说这位VP也是技术出身而且还获得过多项广告相关的技术专利,问了自动化框架,不过的确他先只是问的框架,然后工作中如何分工,还让我自己现场写代码设计一个hashtable的接口,我自己写了3个方法get,put,,containsKey,的确不太理想,自己之前工作中用过三五次hashtable,理解也不是特别深刻,不过好在没有留白。接下来回去后恶补了一下JAVA集合的知识,为接下来的小米面试做了下铺垫。幸运的是得到了京东广告的offer。所以,我想说的是,如果可以的话面试前最好通过各种途径充分了解下面试官,对于做技术出身的千万不能大意,没准就会考考技术水平。
  小米
  据说小米今年要扩大规模,从五千人扩到一万人左右,而我面试的是小米电视。从JD上看不出来职位具体职责,跟其他公司软件测试经理一样的要求和工作内容。在小米面试了好几个人,如果按轮次的话有五轮吧,2轮测试,1轮业务,1轮HR,1轮VP。一二面跟其他公司面试一样,各个方面都有考察,包括linux命令,JAVA基础,用例设计及功能测试等等,还现场让编写登录的用例,还好我从各个方面着手考虑的比较全面,并没有难倒我,但是聊到工作内容时倒是让我有一点顾虑,主要是招聘一个电视AppStore上App审核组leader,因为有大量第三方App提交给小米,需要人工审核他们的功能,类似于验收一样,但是人工工作量巨大想通过自动化方法来替代手工劳动,还比较奇怪的是这个组需要report给产品运营的人。接下来的3次面试都还不错,然后让回来等待,还需要跟VP面谈。与VP面试时其实更多在考察对于一个我从来没有做过的工作是否满怀信心,是否能接受挑战,能在较强负荷的工作压力下迎难而上,当然我结合现在工作的实例来说明我一直都在进行新的尝试和挑战,并且善于解决没有遇到过的问题,最终获得了他的肯定。最近两年小米的爆发式的发展速度的确让很多人刮目相看,这里没有KPI,没有title,进来的人都是工程师,大家都是干实事的,扁平化的管理和满怀激情的工作氛围的确是很多人来小米的原因,只可惜主要还是工作内容原因让我回绝了他们,如果是公司内纯软件产品的测试可能我能接受,毕竟这是我的职业方向。
  通过这段时间的面试经历,也有一些自己的想法:
  1. 并不是每个面试官都懂得如何进行成功的面试,也许面试经验丰富的人才懂得如何全方位的考察一个人,否则可能会误判,或许只招了会面试的人进来,而不是会工作懂得如何解决问题的人。毕竟还是‘千里马常有,而伯乐不常有’,做一个好伯乐本身就是一大挑战。所以对于比较高级资深的职位的话,企业真的需要选好面试官方能找到真正的人才。
  2. 在面试中凡是有女的面试我,都会挂,当然首先也有我自身的原因,除此之外,我要解释一下我遇到的女面试官的不足:1)她们更注重细节,可能稍不合她们意就会PASS掉;2)她们相对缺乏宏观管理和分析能力;3)更希望寻找一个来了就能干活的,对于潜力和学习能力等等不会太注重。当然,并不是所有的女面试官都这样,社会上同样有很多优秀的女性丝毫不比男性差,这点我毫不否认。
  3. 准备面试是一件非常不划算的事情,伤神费时费力,在工作中实践提高进步会非常的快,可能很多企业都没有培养一个人的耐心,但是如果一个人只会做做过的事情,对从来没有做过的事情缺乏分析和解决能力的话,也只能解决当务之急,不能委以重任。一个人的能力不是体现在能处理好以前做过的事情,而是更多的体现在能处理好以前从来没有遇到过的问题上。如果把面试当成考试一样来对待,我觉得是一大悲哀!

posted @ 2014-05-08 16:40 顺其自然EVO 阅读(369) | 评论 (0)编辑 收藏

敏捷方法是怎样优化设计验收测试

  正在缩小的世界中的测试软件  
        当“上市时间”从几个月缩短到几天(甚至几个小时)的时候,提供软件的整个方式就会受到影响,测试也同样会受影响。在采用了敏捷方法的项目中,传统功能测试链正被打乱。这对正在做持续部署的团队更具挑战。
  在敏捷项目中,迭代很短(通常介于1和4周间),带有小改进和持续集成。因此,每次迭代,我们都需要确保这些改进按照他们预期的方式进行,并执行一些回归测试。要达到敏捷性测试这个水平需要大量的自动化。项目将其测试100 %自动化并不罕见。谷歌每分钟做20+个代码变化,每天运行约50百万次测试!
  但测试执行只是硬币的一面。现在的问题是,如何以相同的速度和规模去设计和维护这些测试?换句话说,一个有许多小幅增长的迭代的项目如何能够在整个测试过程保持精简?


  早期测试设计

  如果一个项目团队必须非常快速地迭代,就很难维护和同步三个传统存储库:需求,代码和测试。我们过去用来管理他们的需求消失了!测试变得更加重要,流程(迭代或计划会议期间)中,很早就开始了测试设计。测试是“完成”的定义,同时确定需求及验收标准的方式。因此,所有利益相关者关于一个成功实施意味着什么达成了共识。这些验收测试也被用来驱动和聚焦代码编写 - 我应该先执行哪个测试?这些原则是验收测试驱动开发实践的基础。


  所以验收测试在生产前不再是开发过程的最后一步。反之 - 验收试验设计在项目早期就开始了。而且,到目前为止,它已被证明能够给质量和生产力带来巨大的好处。
  业务领域语言设计验收测试的需要
  为了按需求规定的速度和规模给早期测试设计提供有效支持并同时增强项目利益相关者之间的沟通,测试人员应该可以构建能被开发人员和业务专家理解的资产。自动化,甚至手工测试用例,通常过于复杂或过于详细而被错误理解。
  还有就是要保持与测试用例相关的文件,并且毫无疑问,这将引起矛盾。因此,要定义测试场景,测试人员应该使用一种业务领域语言,它:
  ▪可以被(定义业务术语的)业务专家理解
  ▪便于测试编写和维护(基于语义而不仅仅是文字)
  ▪可被自动转化用于测试执行
  这样一个业务领域的语言一点好处是:它使开发人员所谓的“重构”成为可能。测试不再是纯文本,它有了语义,只用一个动作就可以管理和修改大量测试。这意味着使用利于团队内部交流的业务语言时升级了一百或更多的测试步骤。因此,使用早期测试设计并通过创建一种业务领域语言所写的测试,你可以将整个项目组和验收标准的定义对其,并高速度、大规模地进行迭代。


  测试的执行也是要么用手动执行要么用自动化被简化了。因为验收测试基于一种业务领域语言,所以测试步骤是同类的且更容易理解和执行。对于那些想要做自动化的人,将业务领域语言转化为将被实现的关键字也很简单。有一些工具支持TADD且为设计测试提供一个特定领域语言(DSL)。

       举例:测试一个阅读应用 
  
     在这个例子中,我们将使用Zest平台及其语言来设计测试。我们将同时显示代码和编辑器。该编辑器是一种定义业务理念和场景的图形化方式。
  现在,让我们定义一个简单的场景:“买很多书”。首先,该场景将使用一个要么是“行动”要么是“结果”的步骤的传统观念。这是人们通常使用的方式。




编辑器中“买很多书”场景的视图

  该场景可以通过引入一个名为“选择书”的动作词进行重构。这个概念定义了一个业务动作/术语,确保了分解。就像一个功能,它提供了一个维护单一点,并且可以有一些参数。


所以,现在,该场景可以调用动作词了。

  现在,我们要把一个新场景添加到测试功能“取消购物车”中。首先,我们创建一个动作词来检查购物车中书的数量。这个动作在新方案中将被使用两次。

  然后,我们创建“可被取消的一选项”场景:

  在此,该平台已经注意到,下面的步骤序列被用在几个场景中,即:“买很多书”和“可被取消的一选项。”

  因此建议创建一个新的动作词并在2场景中重构以优化你的维护!当被执行(即行动词“登录”创建及场景重构)时, “可取消的一选项”场景就变成了:

编辑器中“可撤销的一选项”场景的视图

  这个例子中,我们已经看到了使用一种语言来设计测试的价值。使用动作词(类似于开发人员的功能)使得设计和维护更加容易,并提供了重构能力。它有助于定义不同项目利益相关者之间的业务术语。
  我们也看到了,这种业务术语的定义可以在设计,优化和重构场景时通过一个非常先进的方式实现。

posted @ 2014-05-08 16:37 顺其自然EVO 阅读(165) | 评论 (0)编辑 收藏

一大波平台来袭,可用性测试怎么破

 手机、PC、网页、平板……一个产品拥有多个终端/平台的情况已经非常普遍,面临大版本时更是所有平台要同期发布,并且各个平台之间的连贯体验也越来越重要,单平台的可用性测试已经渐渐不能满足当前的需求,这里就跟大家探讨下面对多平台的可用性测试需要注意的内容。
  (以下故事纯属为了奠定全文喜剧色彩和夸张手法,和真实产品没有半毛钱关系。)
  用户研究员老王最近遇到了一件烦心事,TA负责的某产品过俩月要发个大版本,瞅了眼项目经理发的周报,六个平台还要同步发!(领导再也不担心老王的工作不饱和了)看来各平台的可用性测试跑不掉了,老王掐指一算:
  我们这个狂霸酷拽的产品共有6个平台;
  这个新版本共有3个新特性和5个基本特性需要测试;
  各平台是分开研发的,所以每个特性完成的时间点不一样;
  那么项目进度表有可能是以下这样丧尽天良的:(以下表格纯属虚构)
  所以:
  等单一平台的所有特性开发完成后按平台测试是来不及的!
  等单一特性在所有平台开发完成后按特性测试也是不可能的!
  这可把老王愁坏了,硕果仅存的几缕头发也要被薅(hao一声)光了。
  老王不用怕!小天使偷偷告诉你一个秘诀——
 
  已经翻了白眼的稍安勿躁,这样放荡不羁的前提条件是:
  1. 平台多;
  2. 发布时间集中;
  3. 特性在不同平台同质性高。
  至于好处则是:
  1. 减少可用性测试的次数;
  2. 增加验证解决方案的轮数;
  3. 预测并避免同类问题在不同平台重复出现。
  那么具体执行与常规的可用性测试有什么不同呢:
  接需求前切记保持底线
  首先给大家讲个小故事:
  
  其实只是多问一句的事儿:
  
上面提到的这种情况也不是不可能发生,接需求前记得保持自己的底线:
  不能在当前版本落地的缓一缓(下个版本还是未知数,也许整个特性都会被干掉,那么这次的测试就是白费功夫)
  没有明显变化或改进的等一等(如果这个版本只是修复了上个版本的一些细节内容,而大的交互流程和图标体系没有变化,并且和上个版本测试出来的可用性问题无关,那么建议不要接,或者利用其他平台测试的资源顺便测试。)
  对界面完全没有影响的就算了(有时会和其他产品甚至是硬件合作,如果我们无法影响到其中的界面那么就算有问题也没法改,这种情况不如不做)
  保证一个主平台的基本特性不测漏,其他合理补充
  虽说这奥义是哪里做完测哪里,但是也不能胡来对吧。
  通常来说会放到可用性测试里去测试的特性有这么4种:
  
  在多平台的可用性测试中,首先要选定一个主平台,保证该平台所有的基本特性不测漏,对于其他平台,有全新特性做完的平台优先测,其次是有改进后特性的,但一次测试不要超过3个平台。这样是为了让新特性有更多的试错验证机会。
  重场景、轻任务,同平台放一起,跨平台看场景
  场景,是对角色如何使用基于软件的产品达到自己目标的简明描述。任务,在我看来更像是对特性的包装,而这些都需要在“场景”这个大剧本下才可执行。
  实际测试时我通常会让用户明白TA是谁(通常就是TA本人)现在在哪里(比如家里)要干什么(把手机里的照片存到电脑上),然后看TA如何操作就好。至于TA是不是按照理想的任务顺序来操作其实并不重要,重点是TA的目的(或者说是我们设定的目标)是否达到。如果没有达到目标,观察TA是在哪些环节出了问题导致失败即可。
  至于用户通过捷径跳过设定的任务直接达成目标(或者说没有测到需要测试的特性)的情况,可以在用户达到目标后再邀请TA通过其他方式尝试。
  另外值得注意的是,虽然让用户自然地操作很好,但是当平台较多的时候很可能出现手忙脚乱的情况,所以为了用户方便还是尽量要把同平台的任务编排到一起,需要跨平台的话(比如在电脑上下载了电子书传到手机上看)那就把它放在使用电脑的任务和使用手机的任务之间作为过渡,如下图示意。
  
  疯狂鞭笞小伙伴修改问题,反复验证解决方案
  测出了好多可用性问题怎么办?催着改啊!改完才能在下一轮验证解决方案对不对啊!iOS的特性A这轮出错了,下轮Android就能测改过以后的特性A啦!还有问题?那继续改啊!之后还有iPad那轮呐!(见下图)
  
  这里需要重申一下最前面提到的一个大前提——特性在不同平台同质性高。也就是说当特性A在iOS和Android的界面基本类似的情况下为了节约时间可以用另一个平台来验证这个平台的问题,当然最好还是能在原平台进行验证啦。
  把报告写给要看的人,及时跟踪落地结果
  报告出来以后要让同事能看懂并且立即消化对吧,所以给不同角色看报告大概是这样的:
  给老板看核心问题和主要结论;
  给产品经理看问题的严重性,提供需求优先级的参考;
  给设计师看具体问题发生的原因,这样设计师就可以去思考更好的解决方案,而不是粗暴地通过增加功能特性的方式来解决;
  给开发看哪些问题是属于bug,可以立即修复;
  另外,不同平台的负责人可能是不同的,所以最好把同一个平台的内容聚合到一起呈现。
  最后来说说自己维护一个可用性问题追踪表(如下图示意)的好:
  
  从跟踪情况看哪些问题是历史遗留并且还没有解决的,再发生类似问题就多跟相关同事聊一聊;
  从特性名称看哪些任务总是完成得很差,哪些是改了以后越来越差,嗯,还是要找同事聊一聊;
  从其中一个平台的问题也可以预估其他平台在做类似任务的时候可能出错的地方;
  方便统计自己的落地率,总结一下经验教训;
  最最好用的一点是——别人问起某平台某版本的问题时你可以瞬间把同版本不同平台/不同版本该平台的所有问题全截给TA看,如果顺便能把其他平台的同样问题或者该平台的历史遗留问题一并解决就太棒了。
  唔 说了这么多不知道对大家有用么~

posted @ 2014-05-08 16:36 顺其自然EVO 阅读(121) | 评论 (0)编辑 收藏

大话敏捷测试

 敏捷这个话题似乎热了好多年,随之也就自然地有了敏捷测试这个术语。
  说到敏捷,大家一定听过不少相关的演讲,看到不少相关的书籍,不过不管有什么新的技术,新的流程,归根结底都是遵循着敏捷宣言并以敏捷原则作为根本。就像Scrum开拓了一套敏捷项目管理的框架,XP指导着敏捷开发中的工程实践一样,敏捷测试也就是一组指引测试工作在敏捷团队中的一些最佳实践。
  首先,敏捷测试非常强调和多方的合作。在瀑布开发模式下,测试人员一般是根据需求文档和设计文档来设计测试用例,然后等功能开发完成,软件交付到测试人员手上才开始正式的测试工作,这样对于测试的所有输入就都是文档。而敏捷测试让测试人员在软件开发的最初就加入团队,为的就是使测试人员更加地靠近产品本身,对于产品经理的需求和开发人员的设计有深入的理解,甚至能和后续的部署和运维团队尽早地接触,了解到产品的全方位。
  再次,尽早地使产品可以测试起来,越早越好。测试工作不再是软件开发中的某一个环节,而是时时刻刻贯穿于软件开发中。实现这一点的基础就是软件的可测性,而可测性又包括至少两点
  有较为明确的需求指标(这里使用了“较为”两个字是因为有些非功能上的指标前期可能的确不太明了,但是随着产品开发的进行,最终还是会慢慢清晰的),这样才能对测试结果进行判定
  有适合测试的接口,这样才能方便的设计和执行测试用例,并能最大规模地发挥测试自动化的优势
  之后,使团队一起加入测试。千万不要孤军奋斗,软件测试是一件极其需要团队力量的过程,让策划/开发/运维甚至是产品经理一起加入。
  开发需要为自己的代码负责,单元测试是必不可少的
  编写用户验收测试用例的时候要邀请策划和产品经理,避免对于需求的理解错误
  请运维一起加入产品的部署测试,他们有着更多的生产环境的实际操作经验
  当然每个角色对于加入的方式可能会不太相同,但是重要的一点就是把所有的测试环节都对团队成员透明,让他们知道产品会进行哪些测试,已经进行了哪些测试,当前的测试结果怎么样。
  在测试可以跑起来之后,尽量频繁地测试。说到这个,测试自动化很自然地被提上了日程。注意,这里用的是“测试自动化”,而不是“自动化测试”。个人认为测试自动化不仅仅是把测试用例通过编写代码脚本化并通过机器运行起来,而是包含了一套对于测试过程的自动化,包括测试环境的自动部署,测试数据的自动生成,测试脚本的自动执行和测试结果的自动报告等等。好了,回到“频繁地测试”这个话题,我们需要多频繁呢?越频繁越好!
  每一次的代码(产品代码或是测试代码)提交或是每一次的配置更新都有潜在破坏软件的可能性,都是需要测试的
  产品在不同部署环境中的表现往往是不可预料的,尽可能多的对可能的部署环境进行验证
  即使部署环境和产品都没有变化,也需要重复测试。这个可能会有些疑问,既然什么都没变,已经跑过通过的测试还有必要重复执行吗?答案是“有必要”
  · 产品在刚启动时和运行了一段时间之后的表现是完全不同的,看似重复执行的测试其实已经是运行在不同状态下的
  · 测试的执行往往是按照一定顺序的,依据“杀虫剂”原理,系统是会有一定“抵抗力”的,这时可以不采取简单的重复测试,而是打乱测试顺序(虽然测试用例的设计在原则上是独立的,但是在实际中对于软件产品的内部状态变化是不可预知的)
  上面这些只是敏捷测试个人的一些理解,其中并没有涉及到具体技术层面的东西,更多的是一种思想层面对于软件测试的转变
  · 软件测试是软件开发的一部分
  · 软件测试是团队成员的职责
  · 软件测试需要尽早,自动,频繁的执行
  也正是因为有了这些需求,TDD/ATDD/CI才会被团队所接受,慢慢变成了一种标配

posted @ 2014-05-08 16:34 顺其自然EVO 阅读(156) | 评论 (0)编辑 收藏

如何攻破软件

 《How to break software》是James A.Whittaker 2000年的一篇有关如何组织带有明确目标的测试策略的文献。文章软件测试的过程比喻为“攻击”软件以发现bug的狩猎过程。目的在于使测试用例的设计变得有章可循,迅速提高软件测试效率。
  James A.Whittaker,测试界的权威人物,先后在IBMGoogle、Microsoft担任过顾问、工程总监、架构师等职位,在测试领域著有《How google test software》等著作。
  文章将“攻击”软件的策略分为三个大类:
    输入/输出攻击
    数据攻击
    运算攻击
  每个类型又分为多个小类型,导致特定的有趣的bug。然后以Microsoft Office系列产品为主要对象,以其中真实的
  bug为例,具体说明每一种攻击策略是怎样导致缺陷呈现的。
  输入/输出攻击
  所谓的“黑盒测试”,又可以分为以下具体的类型和施行策略。
  数据攻击
  首先要理解数据是如何、在何处建立是必要的。
  从本质上讲,数据的存储是通过读取输入,然后将其存储在内部或者存储一些内部计算的结果来实现的。因此,测试正是通过提供输入和执行计算来实现数据在应用程序中的传递。
  具体分为以下具体的类型和施行策略:
  
  运算攻击
  
  总的来说,找bug不外乎几种大概的思路:1.遍历一遍输入,把能出现的结果都覆盖到;2.通过构造错误的输出来设计输入并执行输入,验证是否bug;3.有相互作用的事务组合测试,包括相互作用的数据、功能等行为。
  另外,作者提出了两个更重要的测试思想:
  1.永远不要低估了测试时怀揣一个具体目标的作用。太多的测试人员把时间浪费在毫无目的地输入或者随机地调用API试图导致软件出错。实行测试意味着制定明确的目标——基于会出错的点——然后设计测试用例来实践该目标。这样,每个测试用例都有目的性并且进度可以被随时控制。
  2.测试应该是有趣的。

posted @ 2014-05-08 16:34 顺其自然EVO 阅读(192) | 评论 (0)编辑 收藏

软件测试的语境驱动方法

我们属于有时叫做软件测试语境驱动学派的一帮人。经过多年(断断续续),我们最后开发出一种原则描述,我们相信这种描述反映了这些松散地聚合在一起充当这一派思想领导的人们的共同观点。
  本书给出了语境驱动思维的大量例子,并解释了我们在团建开发中的体会。随着本书的出版,我们也创建了一个网站,即context-driven-testing.com,以进一步发展这个学派。
  如果读者阅读了以下给出的原则和说明,决定也亲自加入这个学派,可访问context-driven-testing.com并加入这个集体。
  语境驱动学派的七个基本原则
  1. 任何实践的价值都取决于其语境。
  2. 在特定语境下有好的实践,但是没有最佳实践。
  3. 在一起工作的人,是所有项目语境的最重要的组成部分。
  4. 项目以常常不能预测的方式逐渐展开。
  5. 产品是一种解决方案。如果产品不是解决方案,他就不能发挥作用。
  6. 好的软件测试是一种具有挑战性的智力过程。
  7. 只有通过判断和技能,在整个项目团队中始终进行协作,才能在合适的时间做合适的事,以有效地测试自己的产品。
  贯彻基本原则的说明
  ●成立测试小组是为了提供与测试有关的服务。测试小组并不开发项目,而是为项目提供服务。
  ●在为开发、质量管理、调试、调查或产品销售提供服务时,测试是代表项目相关人员实施的。完全不同的测试策略对于这些不同的目标是合适的。
  ●不同的测试小组有不同的任务是很正常的。服务一种任务的核心实践可能与另一种核心实践无关或生产率相反。
  ●采用无效的指标是危险的。
  ●任何测试用例的基本价值,在于它提供信息的能力(即减少不确定性的能力)。
  ●所有征兆都会有欺骗性。即使产品看起来通过了测试,但是也很有可能以测试员(或自动化测试程序)没有监视到的方式失效。
  ●自动化测试并不是自动化的手工测试,把自动化测试作为自动化的人工测试来讨论是没有意义的。
  ●不同类型的测试会暴露不同类型的缺陷——随着程序变得更稳定,测试应该更具进取性,或应该关注不同的风险。
  ●测试工作产品应该达到满足项目相关人员有关需求的程度。
  举例
  请考虑两个项目团队。一个团队开发用于飞机的控制软件。“正确行为”具有高度技术和数学含义,必须遵循FAA制定的规范。团队成员所做的一切或没有做的一切,都是从现在起20年时间内的法律诉讼证据。开发团队成员都遵循崇尚小心、准确、可重复性和反复检查每个人的工作的工程文化。
  另一个团队开发的是在Web上使用的字处理程序。“正确行为”就是把大量Microsoft Word用户吸引到自己的软件上。没有必要遵循的规范要求(只有控制公共栈的要求)。投放市场的时间很重要——从现在起20个月,到时候无论好坏必须拿出产品。开发团队成员肯定没有很好的工程文化,如果读者试图以第一种文化的普遍方式讨论问题,就会使他们认为那是”应该避免出现的损失。“
  适合第一个项目团队的测试时间会在第二个项目中失败。适合第二个项目团队的实践对第一个项目团队就是会受到起诉的失职。

 语境驱动学派的成员
  如果读者赞同这些原则,并想加入这个学派,可通过context@satisfice.com与我们联系。
  以下一些专著的作者,都赞同这些原则:
  Cem Kaner
  James Bach
  Bret Pettichord
  Anna S. W. Allison
  Stale Amland
  Bernie Berger
  Jaya R. Carl
  Ross Collard
  Christopher Denardis
  Marge Farrell
  Erick Griffin
  Sam Guckenheimer
  Elisabeth Hendrickson
  Kathy Iberle
  Bob Johnson
  Karen Johnson
  Mark Johnson
  Alan A. Jorgensen博士
  Brian Marick
  Patrica A. McQuaid博士
  Alan Myrvold
  Noel Nyman
  Pat McGee
  Johanna Rothman
  Jane Stepak
  Paul Szymkowiak
  Andy Tinkham
  Steve Tolman
  --------------------------------------------------------------------------------------------------------------------
  时势造英雄,环境的影响不可忽视。语境驱动测试,也是基于这样的思想。人不是一个线性的器件,不同的人组合在一起,会发生不同的化学反应。不同的团队,使用的方法也不会完全相同。

posted @ 2014-05-08 16:33 顺其自然EVO 阅读(175) | 评论 (0)编辑 收藏

易于测试的代码

软件IC是人们在讨论可复用性和基于组件的开发时最喜欢使用的比喻。意思是软件组件应该就像集成电路一样进行组合,这只有在你使用的组件已知是可靠地时候才能行之有效。
  芯片在设计时就考虑了测试——不只是在工厂,在安装时,而且也是在部署现场进行测试。更加复杂的芯片和系统可能还拥有完整的Built-In-SelfTest(BIST)特性,用于在内部运行某种基础级的诊断;或是拥有Test Access Mechanism(TAM),用以提供一种测试装备,允许外部环境提供激励,并收集来自芯片的响应。
  我们可以在软件中做同样的事情,与我们的硬件同事一样,我们也需要从一开始就把可测试性(testability)构建进软件中,并且在把各个部分连接在一起之前对每个部分进行彻底的测试。
  单元测试
  硬件的芯片级测试大致等价于软件中的单元测试(unit testing)——在隔离状态下对每个模块进行测试,目的是检验其行为。一旦我们在受控的(甚至是人为的)条件下对模块进行了彻底的测试,我们就能够更好地了解模块在广阔的世界上将怎样起反应。
  软件的单元测试时对模块进行演练的代码。在典型情况下,单元测试将建立某种人工环境,然后调用被测试模块中的例程。然后,它根据已知的值,或是同一测试先前返回的结果(回归测试),对返回的结果进行检查。
  随后,当我们把我们的“软件IC”装配进完整系统中时,我们将有信心,各个部分都能够如预期的那样工作,然后我们可以使用同样的单元测试设施把系统当做整体进行测试。
  但是,在我们走那么远之前,我们需要决定在单元级测试什么,在典型情况下,程序员会随便把一些数据扔给代码,就说已经测试过了,应用“按合约设计”后面的思想,我们可以做得好得多。
  针对合约进行测试
  我们喜欢把单元测试视为针对合约的测试。我们想要编写测试用例,确保给定的单元遵守其合约。这将告诉我们两件事情:代码是否符合合约,以及合约的含义是否与我们所认为的一样。我们想要通过广泛的测试用例与边界条件,测试模块是否实现了它允诺的功能。
  我们为什么要这么费事?最重要的是,我们不想制造“定时炸弹”——呆在周围不被人注意,却在项目最后的尴尬时刻爆炸的东西。通过强调针对合约进行测试,我们可以设法尽可能多的避免那些“下游的灾难”(downstream disaster)。
  提示
  Design to Test 为测试而设计
  当你设计模块,或是单个例程时,你应该既设计其合约,也设计测试改合约的代码。通过设计能够通过测试,并履行其合约的代码,你可以仔细地考虑边界条件和其他非如此不会发现的问题。没有什么修正错误的方法比一开始就避免发生错误更好。事实上,通过在你实现代码之前构建测试,你必须在你确定采用某个接口之前先对它就行试验。
  编写单元测试
  模块的单元测试不应被扔在源码树的某个遥远的角落里。他们须放置在方便的地方。对于小型项目,你可以把模块的单元测试嵌入在模块自身里。对于更大的项目,我们建议你把每个测试都放进一个子目录。不管是哪种方法,要记住,如果你不容易找到它,也就不会使用它。
  通过使测试代码易于找到,你是在给使用你代码的开发者提供两样 无价的资源:
  1. 一些例子,说明怎样使用你的模块的所有功能。
  2. 用以构建回归测试,以验证未来对代码的任何改动是否正确的一种手段。
  让各个类或模块包含自己的单元测试很方便(但却并非总是可行)。例如,在Java中,每个类都有自己的main,除了在应用的主类文件里,所有的main例程都可用于运行单元测试,当应用者自身运行时它将被忽略。这样做的好处是,你交付的代码仍然含有测试,可用于在现场对问题进行诊断。
  在C++中,通过使用#ifdef有选择的编译单元测试,你可以(在编译时)获得同样的效果。
  但是只提供单元测试还不够,你还必须运行它们,并且经常运行它们,如果类偶尔通过了测试,那也是有帮助的。
 使用测试设备
  因为我们通常会编写大量测试代码,并进行大量测试,我们要让自己的生活容易一点,为项目开发标准的测试设备(testing harness)。前一节给出的main函数是非常简单的测试装备,与之相比,我们通常需要更多的功能。
  测试装备可以处理一些常用操作,比如记录状态,分析输出是否符合预期的结果,以及选择和运行测试,装备可以由GUI驱动,可以用项目的其他部分所用的语言编写,也可以实现为makefile或Perl脚本的组合。
  在面向对象语言和环境中,你可以创建一个提供这些常用操作的基类。各个测试可以对其进行继承,并增加专用的测试代码。你可以使用Java中的标准名称约定和反射,动态的创建测试列表。这一技术是遵循DRY原则的好方法——你无需维护可用测试的列表。但是你出发前编写自己的装备前,你可以研究一下Kent Beck和Erich Gamma的xUnit。他们已经完成了这项艰苦的工作。
  不管你决定采用的技术是什么,测试装备都应该具有以下功能:
  ●用以指定设置与清理(setup and cleanup)的标准途径。
  ●用以选择个别或所有可用测试的方法。
  ●分析输出是否是预期(或意外)结果的手段。
  ●标准化的故障报告形式。
  测试应该是可以组合的,也就是说,测试可以由子组件的子测试组合到任意深度。通过这一特性,我们可以使用同样的工具,同样轻松地测试系统的选定部分或整个系统。
  构建测试窗口
  即使是最好的测试集也不大可能找出所有的bug;工作环境的潮湿、温暖的状况似乎能把它们从木制品中带出来。
  这就意味着,一旦某个软件部署之后,你常常需要对其进行测试——在现实世界的数据正流过它的血脉时。与电路板或芯片不同,在软件中我们没有测试管脚(test pin),但我们可以提供模块的内部状态的各种视图,而又不使用调试器(在产品应用中这可能不方便,或是不可能)。
  含有跟踪消息的 日志文件就是这样一种机制。日志消息的格式应该正规、一致,你也许想要自动解析它们,以推断程序所用的处理时间或逻辑路径。格式糟糕或不一致的诊断信息就像是一堆“呕吐物”——它们既难以阅读,也无法解析。
  了解运行中的代码内部状况的另一种机制是“ 热键”序列。按下特定的键组合,就会弹出一个诊断控制窗口,显示状态消息等信息。你通常不会想把这样的热键透露给最终用户,但这对于客户服务人员却非常方便。
  对于更大、更复杂的服务器代码,提供其操作的内部视图的一种漂亮技术是使用 内建的web服务器,任何人都可以让Web浏览器指向应用的HTTP端口(通常使用的是非标准端口号,比如8080),并看到内部状态、日志条目、甚至可能是某种调试控制面板,这听起来也许难以实现,其实并非如此。你可以找到各种现代语言编写,可自由获取、可嵌入的HTTP Web服务器。
  测试文化
  你编写的所有软件都将进行测试——如果不是由你和你们团队测试,那就要由最终用户测试——所以你最好计划好对其进行彻底的测试,一点预先的准备可以大大降低维护费用、减少客户服务电话。
  尽管有着黑客的名称,Perl社区对单元测试和回归测试非常认真,Perl的标准模块安装过程支持回归测试(%make test)。在这方面Perl自身并无任何神奇之处,Perl使得比较和分析测试结果都变得更为容易,以确保顺应性(compliance)——测试被放在指定的地方,并且有着某种预期的输出。测试是技术,但更是文化;不管所用语言是什么,我们都可以让这样的测试文化慢慢渗入项目中。

posted @ 2014-05-08 16:08 顺其自然EVO 阅读(257) | 评论 (0)编辑 收藏

Xcode 5 使用 XCTest 做单元测试

 什么是单元测试,请看 百度百科 单元测试
  一:在xcode5 之前,我们新建项目时,可以选择是否集成单元测试;如今在xcode5,我们新建立的项目默认就已经集成了单元测试和ARC;
  xcode5 之后集成的单元测试框架 XCTest.framework
  如图,我们用xcode5 新建立一个 名为 StudengManager 的空项目
  项目新增加框架 XCTest.framework
  项目新增加组 XXXX项目名Test
  新增加 xxxxxTest.m
  Test.m测试文件没有 .h文件,并且 继承 XCTestCase 类;
  项目新建立好之后,我可以用 快捷键 com + u (或是 导航条 --> product --> test) 来启动测试;
  如图:出错了,那是默认的,需要开发者 自己实现 相应的 - (void)test开关的方法;
  二:有兴趣的可以打开 XCTest.framework 先看一下该框架为我们提供的测试用的api;
  如下一些基本的api的使用;
  1:如图,我们在项目里添加一个Student类,里面包含 姓名,年龄、是否是男孩 三个属性
 2:把 Studen引入到 Test.m文件中使用;
- (void)testExample
{
//创建两个学生对象,并初始化一些属性;
Student *stu1 = [Student new];
Student *stu2 = [Student new];
stu1.name = @"Mike";
stu1.age = 18;
stu1.isBoy = YES;
stu2.name = @"Lisa";
stu2.age = 18;
stu2.isBoy = NO;
//测试 是否为 nil
Student *stu3 = [Student new];
stu3.isBoy = YES;
//当姓名为nil时,错误会提示,并显示后面的log
XCTAssertNotNil(stu3.name, @"学生3的姓名不应该为空");
}
  3:XCTAssertTrue和XCTAssertFalse
  4:XCTAssertEqual使用
  5:你可以建立自己的测试类 ,但要继承 XCTestCase; 并且里面测试方法要是 - (void)test 且以 test开头的;当没有错误 的时候,就会全部变成绿色;
  6:还有关于 TDD 测试驱动开发,请谷歌之!

posted @ 2014-05-08 16:08 顺其自然EVO 阅读(335) | 评论 (0)编辑 收藏

轻巧的线程堆栈查看工具Hot Threads

 定位性能问题,尤其是cpu使用率过高时,经常需要查找cpu消耗较高的线程,然后查看其堆栈,从而进入代码定位问题。
  该场景下, jstack+top是一种非常经典的方式。
  jstack+top
  jstack+top的一般套路:
  1、top -H 查看cpu占用较高的线程,记录十进制的线程id
  2、jstack  将线程信息dump到文件中,在文件中根据线程id查找该线程的堆栈。 注意,jstack输出中线程id是16进制的,这里要做一次进制转换。
  3、研究这个线程的堆栈
  jstack+top方法的不足:
  1、麻烦。由于top工具输出是实时变化的,一般需要抓多次,重复下来,上述过程更显繁琐。
  2、线程状态时刻变动,top -H时看到一个线程的cpu占用率较高,等到jstack 时可能已经处于sleep状态,因此上述操作需要较高的APM
  有什么办法能省却这些麻烦 —— 能在看到线程堆栈的时候,直接看到他们各自的cpu占用率呢? —— Hot Threads 可以!
  Hot Threads
  Hot Threads是一个小巧的开源工具,使用十分容易:
  1、下载jar包,扔到服务器上
  2、执行java -jar HotThread.jar [pid] 即可,pid是被测的进程号。使用中注意填对路径即可。
  Hot Threads的输出:
  执行完上述指令后,Hot Threads会在很短时间内,重复查询10次线程堆栈信息(调用sun.management.ThreadImpl.getThreadInfo方法),统计平均cpu占用最高的3个线程,打印线程堆栈,并显示cpu占用率。
106.3% CPU Usage by Thread 'Swing-Shell'
10/10 snapshots sharing following 10 elements
sun.awt.shell.Win32ShellFolder2.getAttributes0(Native Method)
sun.awt.shell.Win32ShellFolder2.access$600(Unknown Source)
sun.awt.shell.Win32ShellFolder2$6.call(Unknown Source)
sun.awt.shell.Win32ShellFolder2$6.call(Unknown Source)
java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
java.util.concurrent.FutureTask.run(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
sun.awt.shell.Win32ShellFolderManager2$ComInvoker$3.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
1.6% CPU Usage by Thread 'RMI TCP Connection(9)-172.30.41.210'
10/10 snapshots sharing following 32 elements
sun.management.ThreadImpl.getThreadInfo0(Native Method)
sun.management.ThreadImpl.getThreadInfo(Unknown Source)
sun.reflect.GeneratedMethodAccessor106.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
com.sun.jmx.mbeanserver.ConvertingMethod.invokeWithOpenReturn(Unknown Source)
com.sun.jmx.mbeanserver.MXBeanIntrospector.invokeM2(Unknown Source)
com.sun.jmx.mbeanserver.MXBeanIntrospector.invokeM2(Unknown Source)
com.sun.jmx.mbeanserver.MBeanIntrospector.invokeM(Unknown Source)
com.sun.jmx.mbeanserver.PerInterface.invoke(Unknown Source)
com.sun.jmx.mbeanserver.MBeanSupport.invoke(Unknown Source)
javax.management.StandardMBean.invoke(Unknown Source)
com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(Unknown Source)
com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(Unknown Source)
javax.management.remote.rmi.RMIConnectionImpl.doOperation(Unknown Source)
javax.management.remote.rmi.RMIConnectionImpl.access$200(Unknown Source)
javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(Unknown Source)
javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(Unknown Source)
javax.management.remote.rmi.RMIConnectionImpl.invoke(Unknown Source)
sun.reflect.GeneratedMethodAccessor21.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
sun.rmi.transport.Transport$1.run(Unknown Source)
java.security.AccessController.doPrivileged(Native Method)
sun.rmi.transport.Transport.serviceCall(Unknown Source)
sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
0.0% CPU Usage by Thread 'Reference Handler'
10/10 snapshots sharing following 3 elements
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
  上图中,每个线程的能看到 10/10 标记。 n / m 意味着m次统计中,有n次都是该排名。
  Hot Threads使用中的问题和解决方法:
  直接执行java -jar HotThread.jar [pid]可能会报错,此时可以换一种启动方式:
  java -classpath "/opt/jdk1.6/lib/tools.jar:HotThread.jar" hotthread.Main [pid]
  其中 /opt/jdk1.6/lib/tools.jar 是服务器上jdk tools包的完整路径,hotthread.Main 是Hot Threads程序的入口。
  Hot Threads的不足:
  使用中发现,Hot Threads自身的cpu开销比较高,有时候统计显示cpu使用率第一的线程,在执行的是获取线程信息的操作,该条堆栈对分析问题无效。
  2723.0% CPU Usage by Thread 'RMI TCP Connection(4)-192.168.164.87'
  6/10 snapshots sharing following 33 elements
  sun.management.ThreadImpl.getThreadInfo1(Native Method)
  sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:154)
  sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  总结:
  Hot Threads使用快速轻巧, 在需要使用jstack + top的场合,都可以尝试代替比较繁琐的jstack + top。

posted @ 2014-05-08 16:07 顺其自然EVO 阅读(1260) | 评论 (0)编辑 收藏

基于模型的测试用例设计(1)

介绍
  测试设计是测试过程中最重要的部分之一。一个好的测试用例不仅要为被测系统( SUT )提供一些输入,还要验证系统是否如预期进行。也就是说,它有助于确认利益相关者要求得以实现。但测试设计可以做的远不止这些。理想情况下,测试设计有助于沟通两方对这些需求的理解,验证他们能被正确实施,并引发对利益相关者可能增加的更大价值的讨论。
  基于模型的测试(MBT)(下文都简称为:基模测试)是一种技术,有时被标榜为“自动化测试设计”。虽然一定程度上这并没有错,但它或许会给人以错误的印象。基模测试工具从一个由用户指定的测试模型生成测试用例。没有测试模型,该工具就无法生成任何测试用例。没有好的测试模型,该工具就无法生成好的测试用例。因此,基模测试里,任务从测试设计变成了测试模型设计。不是设计单个测试集,我们设计了一个用于生成任何数量的测试用例的测试模型。
  例子
  为了给这个概念提供一个具体的理解,首先我们举一个简单的例子。这里所说的例子使用OSMO Tester MBT生成器的符号,它基于Java编程语言。这种情况下,测试模型是使用标准的Java编程语言结构编写的,但却被设计成被另一个称作测试生成器的程序以不同的方式执行,以生成测试用例。有时候,这种模型被称为模型程序。
  图1举了一个简化电信系统(其中多个移动终端被连接(注册)到潜在多个服务器之一上,彼此相互调用)的这种符号的例子。
  其他类似工具用于各种其他平台,比如Python (PyModel)和.NET (Spec Explorer, NModel)。其他基于Java的工具和符号,包括ModelJUnit和Conformiq Designer。许多工具也定义了自己的建模语言,并提供一种方法将模型以不同的方式进行可视化。
  根据用户的喜好,可以选择不同的工具提供一个熟悉的工作环境以及不同的算法和不同的特征等。
  [BINDER]中可找到一个MBT工具列表。 

图1.模型程序示例



  注意,图1中的试验模型被稍微简化以提供一个测试模型中的一些核心要素的例子。测试这样一个系统的真实模型将包含更多步骤,动作和检查,以及更多的规定。例如,我们需要来启动和终止调动的步骤,注销终端步骤,移动它们的网络的步骤,启动数据传输不同类型的步骤,等等更多。
  至于这种模型中的规定,我们应该保持终端列能有效调用,消息列可以发送和接收,并保证一切有效数据传输。并且应在测试先知中用类似于图1中检查注册终端的方式去再次坚持这项新规定。本文的其余部分将把示例模型引用为一个扩展版本。一个测试生成器可采取不同的方法从一个测试模型生成测试用例。对于OSMO Tester生成器及图1所示测试模型,该模型可能如[ ACM ]所述那样被最直观地描述为一系列规则和动作。该模型定义了一组可以在被测系统上进行的动作(在OSMO Tester标记中用作@TestStep的一部分)。当这些动作中的每一个都被允许时,一组规则(OSMO Tester标记中的@Guard)就定义了。规则允许的话,生成器就以不同的方式组合这些动作以生成测试用例。整个测试模型可以被视作用来描述大量的可能测试用例集。随后测试生成器从(使用一些由用户定义的覆盖准则的)这个模型去生成测试用例。可用标准的变化取决于所使用的工具,但一些例子包含了在模型中覆盖用户指定要求(手动标记的特定部分或路径),覆盖动作组合,并覆盖不同动作的各种数据值。(可能已被用来为我们的示例模型指导生成器的)覆盖准则的一些例子包括:注册终端的数量,调用终端的数量,注册却自由(不处于调用状态)的终端的数量,及动作结果配对。例如,它可以被定义为对将“零”,“一”和“多”类别都覆盖到终端类型数中的每一个很感兴趣。动作覆盖可以与这些数值中的一些进一步配对,以激励生成器来生成步骤,诸如注销一个调用终端和注销一个不同配置下的非调用终端。有了更严格/松散的覆盖目标,以及从自由度变为在测试用例中添加随机性,那么生成机就可以被用来生成一组更小/更大的测试用例。
  图2是一个(含有图1模型中的一个测试生成流程的四个不同点的)例子。在点一( 1 )中 ,模型程序被5个未注册终端初始化了。在点二(2 )中,生成由几个步骤推进,且三个终端已被注册。在点三( 3 )中 ,几个步骤再次被通过且两个注册终端有了有效调用(两者间的单独调用)。在点四( 4 )中,两个以前未注册的终端已经被注册了,前面调用的一部分已经退出,已用两个终端建了一个新的调用。

  

图2.测试生成流程示例


  它真正测试哪些东西呢?
  测试生成的一个常见问题是:它真正测试什么呢?如果我们只是无休止地生成测试数据或测试步骤却对结果的正确性一无所知,那还有什么意义呢?在基模测试中,测试模型也可以用来检查测试用例。图1中这是由模型中@Post注释的方法举例说明的。生成器在所有的测试步骤两两间(后)执行这个过程,以证明被测系统的情况与测试模型的情况一致。例如,在图2的点二( 2 )中,它会检查是否测试模型中被标记为注册的三个终端在被测系统中也都处于相同情况。它还要检查其他两个没有被注册,而且他们都没有正在进行有效调用。
  类似地,更具体的检查可以嵌入到任何可在其中获得一些具体结果的行动中去。
  如果需要的话,这些检查可以是不同粒度的,且可以在按量进行,因为不像手工脚本,他们不需要手工编写每个测试用例的每一步,却可以由测试生成器进行,时间间隔与时间长短都不限。
  当已经创建了一个测试模型,测试生成器就用来从这些模型生成测试用例。除了用指定的覆盖准则为指导从整体模型生成测试,很多MBT工具还提供了一种手段来指导生成器用各种形式的用户定义场景去关注特定部分。例如,有了(有调用等的)扩展示例模型,我们或许还想从某个角度专注分析管理终端注册的网络服务器。要做到这一点,用户可以创建一个场景,确保只有测试步骤与该场景(如注册和注销)相关联。
  工具的具体场景定义语言,可以用来建立这样的场景。要建一个特定测试配置,测试模式可用指定终端实例被参数化。
  图3说明了为我们只允许注册和注销步骤的示例模型建立一个场景,且每个步骤都必须在每个生成的测试用例中出现至少两次。
  更真实的例子会包括更多步骤,更多部分,并且可能还包括用以驱动SUT到场景起点的启动脚本。
  这样一个场景甚至可以用来定义一个特定动作序列,该序列将被用作一个启动脚本以生成一个类似于手工编写测试用例的纯手工特定测试用例,而不是当模型和其他生成的测试用例一样变化时将被更新。
  MBT的优点
  基模测试的优点很多。相对于手动设计(编写)单个测试用例,建立测试模型意味着有必要考虑和确定被测系统的整体行为。根据我们的经验,反之这促使了组织间的交流以便把要求建立这样一个模型的各方都汇集起来,既有利于协作又促进共同理解。
  当从一个单一的模型生成大量测试用例时,维护也被简化了,而且更新模型一次并重新运行生成器会可以立刻更新所有测试用例,而不要单独重新运行几百个测试用例。
  一个精心设计的测试模型表现出了作为一个整体的被测系统的被选方面。被允许和支持的测试值而不是单个测试值的范围应该在测试模型中被发现并表示。不利用测试(模型)设计师把开发人员和领域专家聚到一起是不可能。也许基模测试应用中通常观察到的最大的好处是:建设和共享对系统的限制和功能的明确理解,并把所有的假设都列到表格中。
  当这种理解被记录到一个测试模型中,某种程度上它就成了一个可执行的规范,因为它可以被用来生成测试用例以实施。然后,不断的测试用例将验证被记录的理解也与实施一致。如果不是这样,就有待达成一个新的共同的理解,细化的模型,或不变的实施。
  当然,该测试模型不能充分地描述该被测系统的所有可能的行为,或者它会变得和实现本身一样复杂甚至更复杂。因此,需要为建模内容选择一个合适的范围,为测试模型选择一个相当高的抽象级别。测试模型的设计需要把重点放在系统的核心部分,该核心部分被视为对严格的测试和验证最重要。这个变化要跨几个系统,例如,安全关键系统可能比不太重要的应用包含了更详细的内容。因为基模测试过程不仅提供了所生成的测试用例,而且还有对系统规范和功能的严格审查,这个审查被要求用来生成测试模型。我们发现这对一个高层次的系统概述和核心关键要素的详细研究特别有用。
  从测试生成的角度来看,基模测试的主要好处在于它的自动模型探索能力且在探索测试模型中不挑测试生成器。根据我们的经验,一个领域(测试)专家要查看系统并对它是如何工作的做出某些内在假设很简单,凸显一些东西,在手动设计测试用例中重复这些假设。手工操作也很昂贵,在各种不同的开发迭代中很少有时间资源来广泛测试一大组不同的选项,或者保证一个大堆测试得以审查和更新。
  使用测试模型为基础的测试生成器的限制较少。有一个好的测试模型,该工具就可以结合不同的模型覆盖准则探索不同场景并把随机模型覆盖融合进去,就避免了一些专业偏差还扩大了探索选项集合。自然,该工具无法避免模型内的偏差,但是当几位专家一起进行模型工作(甚至部分,如审查)时,模型具有巨大偏差的可能性就小了,工具将更加不知疲倦更彻底地探索模型。在现有计算能力和测试执行时间内,它可以生成并执行大量测试用例而不会厌倦,并在每次迭代中重复同样的过程,只需更新单个测试模型就行。
  许多关于使用基模测试的案例研究已经发表,也许这其中最广泛的就是微软协议文档工作[ ACM ] 。微软研究表明:把所有元素(包括学习曲线等)考虑在内时使用基模测试对比手工脚本有42%的利益。它还强调了许多我们所观察到的接下来将要讨论的问题。
  采用需求及潜在问题
  如果基模测试这么棒,为什么我们不一直用它呢?因为基模测试的初始成本较高,需要多样化的技能,它的利益却难以衡量。初始成本用于获取技能,学习测试建模的思维模式,并创建测试模型。无法证明自己的系统和域的好处的话,这样的初始成本很难被接受,如果所有人至今为止都一直手写测试,就很容易安于现状而不会为组织去尝试不同的和未知的事物。
  创建良好的测试模型需要良好的编程技巧(及一般的软件工程技能),测试专业知识,建模专业知识和领域专业知识。这是一个多样化的技能组合,很难靠单个专家获得。而当有这样的专家时,管理层往往快速将他们分配定位成为一个开发而不是测试。同样,管理层基本不会提供各种昂贵的资源(如领域专家,软件开发人员)用于和软件测试的筒仓相关的活动,即使他们需要成功的测试活动。从模型设计角度来看,测试模型也并不是一个传统的顺序计算机程序,而是指导测试生成器的一个规则和行动的集合,它本身与传统的顺序程序设计有点不同。
  一般情况下,当开始进行评估,(可能的话)采用基模测试方法的时候,或许最大的障碍就是需要采用一个完全不同类型的思维模式。有必要把重点放在考虑SUT的整体功能和目的或者它所选择的一部分上,而不要独自想着单用场景和单个测试用例。这需要与组织中的其他专家密切合作,这就可能需要对一般的工作实践稍作改变。
  这也强调了关于计算优点的问题。如果管理被用来测量如被写测试用例的数量之类的东西,他们要么就看不到测试用例(只有一个测试模型)要么就是一大堆测试用例(所有生成的)。 [ GRAHAM ]中已对该问题及其可能结果做了详细说明,[ GRAHAM ]中测试人员最初恶评如潮,后来因为已观察到的影响而被承认。还有,最初获得用该工具生成测试用例的启动成本会显得使用这种规格没有任何价值。然而,它可以是建立共同理解并将之记录在一个可执行的规范(测试模型)中的过程中最有用的部分。正如在任何自动化测试工作(或任何其他工作)中 ,管理支持,沟通和理解都是非常重要的。
  该方法和测试生成结果的有效性取决于设计的测试模型的质量。没有一个高质量的模型,就没有测试生成可以生产好测试。因此,投入足够精力去产生好模型并和其他专家一起检验它很重要。
  生成一大组测试用例也能生出一大组需要进行分析的结果。根据我们的经验,当考虑实施基模测试时,许多人通常认为这就是一个潜在的问题。然而,实践中,我们已经观察到:这问题不大,因为测试生成基本是使用某种形式的场景或(对系统具体部分分析关注的)专注模式指导的。然而,模型设计仍应仔细考虑诸如有趣元素有哪些以及它们从所有可能输入到测试的组合,所以测试生成的重点应放在最有用的方面。至于结果分析,积极地说,当更多的精力可以从手动复制测试脚本中被转移到分析结果时,这就可以使工作更有趣而不那么单调乏味。总之,测试自动化应该一层层往上建。
  有效实施基模测试需要将之建于一个好的基础的测试自动化平台之上。如果它无法写出可以自动化执行的测试脚本,那么继续进行基模测试去产生这样的脚本就毫无意义。建立基础的测试自动化需要良好的水平,这个水平上,基模测试过程可作为一个额外工具来提高总体质量。例如,如自动控制SUT的GUI进行测试一类的事,应该在测试一个基于GUI的应用程序时就得到解决。
  过程
  使用基模测试的过程可以用四个简单的步骤描述为一个迭代过程,图3所示。开始时,我们通常为系统所选的小一部分创建一个最初的测试模型。这使我们能够学习基本工具和框架,并看看他们是如何连接以形成整个测试环境并在该环境中定位基模测试工具。

  

图4.过程模型设计


  一旦拥有了测试模型的工作版本,我们就用它来生成并执行测试用例。生成的测试用例的执行可以在所谓的“在线基模测试”中与他们的生成进行交错,或在所谓的“离线基模测试”中的一个单独的阶段中完成。这就很快地给我们提供了对模型情况和对当前模型设计中被测系统的那些部分的反馈。
  当我们已经生成并执行测试用例时,我们分析出被测系统上及测试模型中错误的结果。
  在令人满意的水平上,我们开始一步步地扩展模型并添加更多功能。这意味着我们要从头重复这些步骤及这个过程,直到在我们觉得我们已得到了一个描述有趣元素的合适水平上的测试模型。
  一些测试模型可以用来设计系统的不同部分。测试场景被用来指导测试生成,或者它可以使用不同的模型和生成器配置去重点关注不同的区域和观点。
  我们采用的一种做法是帮助合作伙伴开始使用开源工具理解这个概念,看到好处,并学习技术。开源工具也有适应特定需求和环境的优点。一旦基本技术,及其实施和效益被更好的理解了,就可以选取不同的前进道路,包括转用(从广泛付费支持和大规模开发先进算法的资源获益的,如Spec Explorer和Conformiq Designer的)商业工具这个选择。然而,在许多情况下,我们早已经看到了开源选项提供的不错利益。
  可以运用基模测试的一个好地方是有很多变量和很多(需要进行测试的)交互的地方。一旦我们意识到把这个手动缩放到要求的复杂度和质量水平很昂贵的时候,基模测试就是一个值得考虑的好技术。另一个不错的地方是安全性软件,在这种软件中必须完全相信一个好的几乎无错的解决方案已被建成。
  结论
  基模测试可能听起来像一个很酷但却吓人的技术,很难上手。然而,经过一些初步学习之后,它并不比常规测试和测试自动化更复杂。我们一般采取的做法是建议一开始(最好是在熟悉这个概念的人的帮助下让对该方法及其潜力超振奋的人)把它用在一个较小的试点项目中。我们通常以现有的测试自动化和测试脚本为出发点,以这些为基础一次一小部分地开始建立测试模型。至于抽象层,一个好的起点可以是:(通过利用现有的SUT的API去定义可能采取的行动或关注可以观察到很多变化且很难测量手动测试的地方,在该系统复杂/易出故障的部分或在核心关键功能上,构建一个促进共同理解的高层次的总体模型中的)任何东西。
      作者介绍:
  TeemuKanstrén是一名资深科学家,目前在芬兰VTT技术研究中心工作,他还是多伦多大学的一名客座博士后。他的工作涉及:以改进行业现状,和生产实际有用的解决方案并帮助行业伙伴接受采纳它们为目的的自动化测试领域的研究和开发。他软件行业工作了好几年,已帮助众多合作伙伴开发和采用以基于模型的测试技术为基础的测试自动化解决方案。他是开源的基于模型的测试工具OSMO Tester的主要创造者。2010年他获得了芬兰大学测试自动化和基于模型的测试的博士学位。

posted @ 2014-05-08 16:02 顺其自然EVO 阅读(702) | 评论 (0)编辑 收藏

仅列出标题
共394页: First 上一页 116 117 118 119 120 121 122 123 124 下一页 Last 
<2025年4月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜