qileilove

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

软件测试工具设计中的协作

 做平台性的测试工具,通常涉及到各个角色,接触最多的就是测试工程师和开发工程师。

  和用户沟通

  普通用户抱怨质疑多,方案建议少;但是测试工具的大部分用户是测试工程师和开发工程师。

  他们一般都明白自己所需并具备清楚表达的能力,有明确的价值目标,有良好的方向感和情境感,有些自己本身就独立开发过优秀的工具,所以在整个工具开发的生命周期中,他们能承担更多角色,参与更多过程。

  测试人员提前介入需求,甚至担任某些模块的PD,参与到产品开发中来,对工具的顺利推广也很有帮助。毕竟,是自个儿亲生的。这批同学是工具最早的用户,他们的工作模式能影响和带动一批用户。

  对设计师的要求

  测试工具和一般互联网产品有所不同。

  传统页面以导航和内容为主,测试工具内容并不复杂,重功能和交互。

  区别于导航和内容的罗列, 作为管理和帮助性工具,一个页面通常会集中很多功能;工具所争取减少的每一步操作都是在节约工程师的时间,出于工作效率考虑,需要更丰富便捷的交互操作。

  在实际开发过程中,大部分前端问题也是在交互方面。从用户反馈来看,用户对功能性和交互性的要求远远远远高于界面样式。

  这就要求设计师必须对系统需求有所了解,包括业务流程、理解专业术语和每一步操作的目的,否则就是盲人摸象。

  不懂测试的设计师很难做出符合期望的界面设计。一般这类工具的设计师角色都是由测试或者开发本身承担。缺点就是产出的界面稍逊美观。不过根据我的经验,人民群众其实是不畏惧界面丑陋的,真正能使用的工具才能长久生存下来。

  和开发沟通

   关于工具交互,用户有很多优秀的建议和想法,不过最终落实还是到开发头上。可惜的是,好的交互一般开发起来都挺费事儿。大家知道,想把用户体验做到极 致,让用户轻松,开发就要“受罪”,要额外做很多在他们看来价值不大的细节工作。程序员有一个信念,这个世界上,没有代码实现不了的事情。如果他说无法实 现,一定是他不想。设计师对于开发工作所用到的知识有所涉猎,不用成为行家,但至少“略懂略懂”,最好有自己动手的能力,能预估开发投入。这样,才能与开 发工程师建立平等对话,提出的需求和设计才不会被人一略而过。《越光宝盒》里面诸葛亮不是有句台词么,什么都懂一点,生活才能更多彩。

  说着容易,实际很难,很多事除非开发自己想明白,劝是没用的。团队里最好有个能一语定乾坤的权威人物,实在和开发沟通不了了,找他定夺。

  工具开发的过程中,在很多情况下,开发本身就是PD,会倾向于简化项目,尽量少做、做自己熟悉的,使得项目顺利完成,并且bug很少,做出来的也许体验不好,但是绝对“够用”。

  其实协同,是你去协同别人,而不是别人来协同你。主动一点,获得更多。

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

重载页面后Web对象的重用

测试中经常会出现在两个页面中的使用同一个对象,出现这样的情况我们一定是使用同一个对象来处理,这样才不会出现重复对象,就比如我们使用百度搜索,当我们打开百度时有一个搜索框,在输入一些内容提交后,页面会重载并且搜索框这个对象仍然存在,这个时候如果我们需要再次控制搜索框这个对象我们一定会想到直接使用之前对象库里的那个搜索框对象,因为它们其实就是同一个对象。

SystemUtil.Run "iexplore.exe"
 Set oBrowser = Browser("micClass:=Browser")
 Set oEdit = oBrowser.Page("micClass:=Page").WebEdit("name:=wd","index:=0")
 oBrowser.Navigate www.baidu.com
 
 With oEdit
 .Set "zzxxbb112"
 .Submit
 End With

 oEdit.Set http://blog.csdn.net/zzxxbb112

  我们可以看到在运行以上脚本后,QTP首先是输入搜索内容然后提交,在提交的瞬间也就是页面还有跳转完成时就提前输入了另一个值,而这并不是我们想要的效果,我们需要的是等页面跳转完成之后再输入另一个搜索内容。解决这个问题的办法是添加同步函数sync。

SystemUtil.Run "iexplore.exe"
 Set oBrowser = Browser("micClass:=Browser")
 Set oEdit = oBrowser.Page("micClass:=Page").WebEdit("name:=wd","index:=0")
 oBrowser.Navigate www.baidu.com
 
With oEdit
 .Set "zzxxbb112"
 .Submit
 End With

 oBrowser.Sync
 oEdit.Set http://blog.csdn.net/zzxxbb112

  在添加同步之后,QTP就会等待页面缓冲完成之后,才对搜索框进行输入操作,但是问题又来了,我们运行以上脚本后却碰到了另一个问题。QTP无法对重载页面后的搜索框对象进行操作,但其实他们是一个对象,脚本提示:oEdit参数不正确。

  这个问题的原因其实是因为当页面同步完成时,测试对象还没有被同步,因此导致我们无法对其进行操作,而报出了以上的错误。不过幸好QTP提供了一个方法可以解决此问题。

SystemUtil.Run "iexplore.exe"
 Set oBrowser = Browser("micClass:=Browser")
 Set oEdit = oBrowser.Page("micClass:=Page").WebEdit("name:=wd","index:=0")
 oBrowser.Navigate www.baidu.com
 
With oEdit
 .Set "zzxxbb112"
 .Submit
 End With

 oBrowser.Sync
 oEdit.init
 oEdit.Set http://blog.csdn.net/zzxxbb112

  执行以上脚本后成功做到了在WEB页面加载后对象的复用。

  obj.init —- 此方法为QTP的隐藏方法,在帮助文档中都没有任何的介绍,用于重新同步页面上的测试对象。我们可以通过使用VS2008改装过的DEBUG引擎来查看此方法。

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

自动化测试ROI实践

  自动化测试是一项“一旦开始,就需要持续投入”的工作,所以它一直是测试领域的一块鸡肋。不做吧,好像手工测试重复得让人有些厌倦,而且手工测试时间也缩短不了。做吧,害怕投入的比回报要多。

   没实施自动化的团队有各种各样的困扰。有的说:“项目有太多的老代码需要补充自动化测试脚本,补不起!”有的说:“项目开发太紧张,如果同时还要自动 化,等不起!”还有的说:“自动化测试工具太贵了!买不起!”确实,各种各样的“伤不起”使得大量的组织在“要不要自动化”这个问题上总在了解和观望,踌 躇不前。

  我们阅读了一些关于自动化测试ROI的文章, 发现大多都是介绍各种不同的计算方法,但来自实际的数据分享比较少。所以,2011年当我们组织想推行自动化测试的时候,为了打消大家(尤其是管理层)对 于自动化测试的投入和产出方面的疑虑,计算我们自己的自动化测试投资回报率ROI(Return on Investment)成了我们启动时就考虑的问题。本文将分为四部分介绍我们的实践方法和结果。

  第一部分:业界计算自动化测试ROI的方法

  简言之,ROI = 收益/投入。但收益如何计算,投入包括哪些,众说纷纭,并没有一个定论。

  在Dion Johnson的“test automation ROI”中给出了三种计算自动化测试ROI的方法。第一种方法“简单ROI”着重从“钱”的方面去看。它考虑了工具、培训、机器等各种费用,并把测试时间 的投入通过单位时间的工资转化成为钱。第二种方法“效率ROI”与第一种方法不同的是从测试效率的角度,只考虑了时间投入所产生的收益,而没有考虑其它如 购买工具方面的投入。这个方法比较适合测试人员计算收益。第三种方法“降低风险ROI”着重计算自动化测试与手工测试相比在降低风险方面的收益。它会假设 不做某种自动化测试,相关的风险一旦成为事实所带来的损失,从而计算ROI。这个方法比较适合管理人员从整体考量自动化的收益。

  那么,目前我们的团队期望自动化测试能带来哪些收益,尤其是哪些收益是目前不能奢望的?我们的经理愿意提供多少资源投入自动化测试呢?带着这些问题,我们开始了自己对自动化测试ROI的定义和度量。

  第二部分:我们计算自动化测试ROI的方法

  在度量自动化测试的收益方面,角度很多。我们选择的是从“多、快、好、省”四个方面去看。

  更多

   鉴于我们处于自动化测试的初级阶段,我们打算暂时先不去追求“更多”。即我们不奢望一年之内整个项目组在一个版本里做更多的工作,因为在自动化投入初期 难以提高团队的生产力。我们也不奢望测试人员马上能有更多时间去做更有价值的工作(相对于一次测试的多次重复执行)。因为测试人员通过自动化测试从测试执 行上节约出来的时间需要投入到自动化工具和技能的学习上去。

  更快

   在时间维度上,我们希望能够更快地发现和修复稳定的主流程上的明显的严重缺陷。如果一个测试人员手工测试多个功能,那么测试执行的并行度总有个上限。而 多个并行执行的自动化测试脚本可以更快速地验证版本,一次性地报告问题。这尤其在测试初期版本不稳定,或者是每日构建的时候有用。有时,甚至是在我们不觉 得有测试必要的时候,自动化测试可以及时报告刚引入的问题。另一方面,更快地发现缺陷也意味着可能可以更快地修复缺陷。

  更好

  我们希望自动化测试可以帮助我们实现对“更好”的追求,包括质量、信心、士气三个方面。

  1、更好的质量

   更好的质量最容易被理解成为更少的缺陷。但这里需要强调的是“更少的缺陷个数并不仅仅能依靠我们基于界面的自动化测试来达到”。我们这里希望自动化测试 能够帮助我们减少生产环境中某种特定类型的缺陷。这些缺陷包括环境或者配置相关的缺陷、在主流程上本来正常但因为后期修改影响到的功能、以及容易被忽略的 地方(如:同一功能的多个入口、不常使用的功能)等。

  2、更强的质量信心

  在内部 测试中,我们希望借助自动化测试来提升的是对质量的信心。这主要体现在:(1)对于小版本和并行版本的质量更好地把关。小版本通常要求更快速的响应。并行 版本通常要求测试人员频繁切换环境和被测对象。而人在压力下也更容易犯错。所以,我们常碰到的是匆忙中由于疏忽,一些比较重要或者明显的问题没有被及时发 现。(2)对缺陷修复的质量更好地把握。根据统计,大约7%的缺陷修复会产生新的缺陷,而这些新缺陷有时会出现在前面已经测试过并且不会再手工测试的地 方。对于如上两种情况,重复利用自动化测试脚本可以不需要额外的投入,快速得到关于整个版本稳定性的信息和质量信心。

  3、更高的士气

   对于测试团队,我们希望自动化测试可以唤起更高的工作热情。这一方面来自于可以部分地将测试人员从大量重复的测试执行中解放出来,另一方面来自于新技 术、新工具带来的新鲜感。开发团队和终端用户会是自动化测试的间接受益者,因为开发团队能感到问题会更快地暴露出来,终端用户会感到应用程序更稳定了。甚 至在不远的将来,如果测试时间可以借力自动化而缩短,那么用户希望的功能也能更快地交付使用了。

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

MySQL数据库性能优化之索引优化

大家都知道索引对于数据访问的性能有非常关键的作用,都知道索引可以提高数据访问效率。

  为什么索引能提高数据访问性能?他会不会有“副作用”?是不是索引创建越多,性能就越好?到底该如何设计索引,才能最大限度的发挥其效能?

  这篇文章主要是带着上面这几个问题来做一个简要的分析,同时排除了业务场景所带来的特殊性,请不要纠结业务场景的影响。

  这是 MySQL数据库性能优化专题 系列的第三篇文章:MySQL 数据库性能优化之索引优化

  系列的第二篇文章:MySQL 数据库性能优化之表结构优化

  系列的第一篇文章:MySQL 数据库性能优化之缓存参数优化

  索引为什么能提高数据访问性能?

  很多人只知道索引能够提高数据库的性能,但并不是特别了解其原理,其实我们可以用一个生活中的示例来理解。

   我们让一位不太懂计算机的朋友去图书馆确认一本叫做《MySQL性能调优与架构设计》的书是否在藏,这样对他说:“请帮我借一本计算机类的数据库书籍, 是属于 MySQL 数据库范畴的,叫做《MySQL性能调优与架构设计》”。朋友会根据所属类别,前往存放“计算机”书籍区域的书架,然后再寻找“数据库”类存放位置,再找 到一堆讲述“MySQL”的书籍,最后可能发现目标在藏(也可能已经借出不在书架上)。

  在这个过程中: “计算机”->“数据库”->“MySQL”->“在藏”->《MySQL性能调优与架构设计》其实就是一个“根据索引查找数 据”的典型案例,“计算机”->“数据库”->“MySQL”->“在藏” 就是朋友查找书籍的索引。

  假设没有这个 索引,那查找这本书的过程会变成怎样呢?朋友只能从图书馆入口一个书架一个书架的“遍历”,直到找到《MySQL性能调优与架构设计》这本书为止。如果幸 运,可能在第一个书架就找到。但如果不幸呢,那就惨了,可能要将整个图书馆所有的书架都找一遍才能找到我们想要的这本书。

  注:这个例子 中的“索引”是记录在朋友大脑中的,实际上,每个图书馆都会有一个非常全的实际存在的索引系统(大多位于入口显眼处),由很多个贴上了明显标签的小抽屉构 成。这个索引系统中存放这非常齐全详尽的索引数据,标识出我们需要查找的“目标”在某个区域的某个书架上。而且每当有新的书籍入库,旧的书籍销毁以及书记 信息修改,都需要对索引系统进行及时的修正。

  下面我们通过上面这个生活中的小示例,来分析一下索引,看看能的出哪些结论?

  索引有哪些“副作用”?

  图书的变更(增,删,改)都需要修订索引,索引存在额外的维护成本

  查找翻阅索引系统需要消耗时间,索引存在额外的访问成本

  这个索引系统需要一个地方来存放,索引存在额外的空间成本

  索引是不是越多越好?

  如果我们的这个图书馆只是一个进出中转站,里面的新书进来后很快就会转发去其他图书馆而从这个馆藏中“清除”,那我们的索引就只会不断的修改,而很少会被用来查找图书

  所以,对于类似于这样的存在非常大更新量的数据,索引的维护成本会非常高,如果其检索需求很少,而且对检索效率并没有非常高的要求的时候,我们并不建议创建索引,或者是尽量减少索引。

 如果我们的书籍量少到只有几本或者就只有一个书架,索引并不会带来什么作用,甚至可能还会浪费一些查找索引所花费的时间。

  所以,对于数据量极小到通过索引检索还不如直接遍历来得快的数据,也并不适合使用索引。

  如果我们的图书馆只有一个10平方的面积,现在连放书架都已经非常拥挤,而且馆藏还在不断增加,我们还能考虑创建索引吗?

  所以,当我们连存储基础数据的空间都捉襟见肘的时候,我们也应该尽量减少低效或者是去除索引。

  索引该如何设计才高效?

  如果我们仅仅只是这样告诉对方的:“帮我确认一本数据库类别的讲述 MySQL 的叫做《MySQL性能调优与架构设计》的书是否在藏”,结果又会如何呢?朋友只能一个大类区域一个大类区域的去寻找“数据库”类别,然后再找到 “MySQL”范畴,再看到我们所需是否在藏。由于我们少说了一个“计算机类”,朋友就必须到每一个大类去寻找。

  所以,我们应该尽量让查找条件尽可能多的在索引中,尽可能通过索引完成所有过滤,回表只是取出额外的数据字段。

  如果我们是这样说的:“帮我确认一本讲述 MySQL 的数据库范畴的计算机丛书,叫做《MySQL性能调优与架构设计》,看是否在藏”。如果这位朋友并不知道计算机是一个大类,也不知道数据库属于计算机大 类,那这位朋友就悲剧了。首先他得遍历每个类别确认“MySQL”存在于哪些类别中,然后从包含 “MySQL” 书籍中再看有哪些是“数据库”范畴的(有可能部分是讲述PHP或者其他开发语言的),然后再排除非计算机类的(虽然可能并没有必要),然后才能确认。

  所以,字段的顺序对组合索引效率有至关重要的作用,过滤效果越好的字段需要更靠前。

  如果我们还有这样一个需求(虽然基本不可能):“帮我将图书馆中所有的计算机图书借来”。朋友如果通过索引来找,每次都到索引柜找到计算机书籍 所在的区域,然后从书架上搬下一格(假设只能以一格为单位从书架上取下,类比数据库中以block/page为单位读取),取出第一本,然后再从索引柜找 到计算机图书所在区域,再搬下一格,取出一本… 如此往复直至取完所有的书。如果他不通过索引来找又会怎样呢?他需要从地一个书架一直往后找,当找到计算机的书,搬下一格,取出所有计算机的书,再往后, 直至所有书架全部看一遍。在这个过程中,如果计算机类书籍较多,通过索引来取所花费的时间很可能要大于直接遍历,因为不断往复的索引翻阅所消耗的时间会非 常长。(延伸阅读:这里有一篇以前写的关于Oracle的文章,索引扫描还是全表扫描(Index Scan Or Full Table Scan))

  所以,当我们需要读取的数据量占整个数据量的比例较大抑或者说索引的过滤效果并不是太好的时候,使用索引并不一定优于全表扫描。

  如果我们的朋友不知道“数据库”这个类别可以属于“计算机”这个大类,抑或者图书馆的索引系统中这两个类别属性并没有关联关系,又会怎样呢?也 就是说,朋友得到的是2个独立的索引,一个是告知“计算机”这个大类所在的区域,一个是“数据库”这个小类所在的区域(很可能是多个区域),那么他只能二 者选其一来搜索我的需求。即使朋友可以分别通过2个索引检索然后自己在脑中取交集再找,那这样的效率实际过程中也会比较低下。

  所以,在实际使用过程中,一次数据访问一般只能利用到1个索引,这一点在索引创建过程中一定要注意,不是说一条SQL语句中Where子句里面每个条件都有索引能对应上就可以了。

  看完这些分析,我想大家应该了解索引优化的一些基本思路了吧。

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

Java集合框架总结:TreeSet类的排序问题

     摘要: 程序运行结果:true [TreeSet.Z@1fb8ee3, TreeSet.Z@1fb8ee3] 9  说明:  程序中把同一个对象添加了两次,因为z1对象的equals()方法总是返回false,而且compareTo(Object obj)方法总是返回1。这样TreeSet会认为z1对象和它自己也不相同,因此TreeSet中添加两个z1对象。而TreeSet对象保存的两...  阅读全文

posted @ 2012-05-04 11:51 顺其自然EVO 阅读(300) | 评论 (0)编辑 收藏

常用数据结构:线性结构

  数据结构是计算机存储、组织数据的方式。常见的数据结构分类方式如下图:

  常用的线性结构有:线性表,栈,队列,循环队列,数组。线性表中包括顺序表、链表等,其中,栈和队列只是属于逻辑上的概念,实际中不存在,仅仅是一种思想,一种理念;线性表则是在内存中数据的一种组织、存储的方式。

  顺序表

  顺序表将元素一个接一个的存入一组连续的存储单元中,在内存物理上是连续的。如下图:

  顺序表存储密度较大,节省空间;但需要事先确定容量,在时间性能方面,读运算较快,时间复杂度为O(1);查找运算为O(n/2),和链表同样;插入运算和删除运算如果要操作中间一个元素,比如3,那么就需要把3后面的元素全部进行移动,因此时间复杂度相对链表要大一些,插入时间复杂度最好为O(0)或最坏为O(n);删除时间复杂度为O([n-1]/2);

  链表

  链表拥有很多结点,每个结点前半部分是数据域,后半部分是指针域,指针域指针指向下一个结点;链表可分为单链表、循环链表和双链表。

  单链表:

  从上图可以看出,单链表的上一个结点指针指向下一个结点,最后一个结点的指针域为null。

  结点的删除:

  删除一个结点,如删除上图中q结点,只需将p结点中的指针域指向a3,然后将a2释放掉(free)即可。

  结点的插入:

  插入一个结点,如插入上图中s结点,首先将s的指针域指向a2(也就是把s的next赋值为p的next),然后将p结点的指针域指向x即可(p的next指向x)。

循环链表

  循环链表与单链表唯一不同之处是,循环链表的最后一个结点指针不为空,而是指向头结点。结点的插入和删除和单链表非常相似,就不再示范了。

  双链表

  双链表拥有一前一后两个指针域,从两个不同的方向把链表连接起来,如此一来,从两个不同的方向形成了两条链,因此成为双链表。因此,双链表的灵活度要大于单链表。

  结点的删除:

  双链表的操作比单链表要稍显复杂(按照单链表思路来做其实也不难),如上图,要删除p节点,首先需要将a1的后驱指向a3,然后将a3的前驱指向a1,最后将p节点释放掉即可。

  结点的插入:

  如上图,插入q结点,首先要按照方向,将步骤拆分,首先将q节点的前驱指向p结点后驱,紧接着将x后驱指向a2;然后按照顺序完成图中所示的3、4步即可。

  从空间性能来看,链表的存储密度要差一些,但在容量分配上更灵活一些。从时间性能来看,查找运算与顺序存储相同,插入运算和删除运算的时间复杂度为O(1),要更优于顺序存储,但读运算则弱一些,为O([n+1]/2),最好为1,最坏为n。

  栈

  上面提到栈属于一个逻辑概念,栈的实现可以用顺序也可以用链式。它遵循先进后出原则,如下图:

  Java中测试代码如下:

  1. package com.snail.test;  
  2.  
  3. import java.util.Stack;  
  4.  
  5. public class TestStack {  
  6.  
  7.     public static void main(String[] args) {  
  8.           
  9.         Stack<String> stack = new Stack<String>();  
  10.         stack.push("NO1");  
  11.         stack.push("NO2");  
  12.         stack.push("NO3");  
  13.           
  14.         System.out.println("初始数量:" + stack.size());  
  15.  
  16.         while(!stack.isEmpty()){  
  17.             System.out.println(stack.pop());  
  18.         }     
  19.           
  20.         System.out.println("取完后的数量:" + stack.size());  
  21.     }  
  22. }



  队列

  队列遵循先进先出的原则,如下图:

  Java中测试代码如下:

  1. package com.snail.test;  
  2.  
  3. /**  
  4.  *  
  5.  * @author Zang XT  
  6.  */ 
  7. import java.util.Queue;  
  8. import java.util.LinkedList;  
  9. public class TestQueue {  
  10.     public static void main(String[] args) {  
  11.         Queue<String> queue = new LinkedList<String>();  
  12.           
  13.         queue.offer("NO1");  
  14.         queue.offer("NO2");  
  15.         queue.offer("NO3");  
  16.           
  17.         System.out.println("初始数量" + queue.size());  
  18.         String str;  
  19.         while((str=queue.poll())!=null){  
  20.             System.out.println(str);  
  21.         }  
  22.         System.out.println("取出后数量" + queue.size());  
  23.     }  
  24. }

  运行结果顺序为:初始数量3,NO1,NO2,NO3,取出后数量0。

  队列还有一种形式为循环队列,如下图:

  循环队列有两个指针,头指针head和尾指针tail,尾指针一般指向的不是队尾元素实际地址,而是指向实际地址的下一个空地址,因此,循环队列一般牺牲最后一个空间,用来计算该队列是否满了,判断方式是tail+1 = head,既该队列已满。

  为了尽可能的说清楚,插了大量图片,希望理解。以后有时间将继续分析树、图等数据结构。

posted @ 2012-05-04 11:49 顺其自然EVO 阅读(248) | 评论 (0)编辑 收藏

软件测试团队学习的三种形式

 团队学习不但可以促进个人成长,还有利于提高团队的核心竞争力。因此,团队学习在构建学习型组织的过程中是非常重要的一个方面。牛根生曾提出:必须坚持团队学习,学相同才能思相近(共识),思相近才能言相和(共鸣),言相和才能行相辅(共振)。我们测试团队在近5年内每年都在组织大家进行团队学习。本文将介绍我们经历的三种不同的组织形式。

  一、兴趣小组

  爱因斯坦说过“兴趣是最好的老师。”在原本就繁重的工作之外,唤起学习欲望的最佳切入点可能就是兴趣了。但团队学习必须找到大家共同的兴趣。所以,我们先每个人列举出几个自己感兴趣的关键字,然后看看它们交叉最集中的地方,从中再讨论并选取两到三个作为本年团队学习的方向。定好主题后,每个人选择参加其中的一到两个小组,并自由推举一个小组协调员,分头开展学习,定期交流。

  兴趣很重要,但有趣的是,实践下来我们发现很多人并不是真正有兴趣,或者准确地说是没有意识到自己并不是真正有兴趣。让我们一起来看看你认为你感兴趣的东西是否经得起以下两个问题的检验。

  问题一:你愿意投入么?我所指的投入是真金白银哦!它包括你的金钱、时间和精力。如果要占用你的一些业余时间,你乐意么?如果要你自己花些钱参加一次活动,你愿意么?别在那想着心仪的姑娘,说你感兴趣,却连一顿饭都舍不得和她吃。别在那看着财经节目热血沸腾,说你想理财,却连一个投资都不做。

  问题二:你能坚持多久?即使你愿意付出,但时光荏苒,环境变迁,当别人质疑你的选择,重重的困难阻碍你的追求,你的付出并没有期盼的回报,你还能够坚持多久?兴趣如果不伴随着承诺,将难以持久。

  当然,在兴趣小组里,即使你刚开始并没有太大的兴趣,也不见得加入兴趣小组就是一件没有意义的事情。比如,存在一种可能:你觉得自己找不到能象你想象中那么感兴趣的东西而感到懊恼和茫然。就象我们曾经热血澎湃地说要学习行业知识,但收集了一些专业名词后就无疾而终。我们也曾经组织过对同一行业领域软件的学习,但最终因为配置过于复杂而搁浅。其实我很理解工作相关的兴趣并不那么容易让你愿意投入,因为比起购物或者宅在家里这样的兴趣爱好,对工作技能或者知识的兴趣在开始的阶段,更多的时候意味着付出、困惑、挫败。其实,感到懊恼和茫然并不可怕。相反,我觉得这是重新思考自己真正感兴趣的新开始。也许你会感到自己需要一个更小的关注点,也许你会意识到自己的学习还需要和实践多一些结合。这些否定过去的经历会带领你下一步走向一个更明确的方向,正如我们也是这样一路摸索着走来。还存在另外一种可能:置身同一个兴趣小组中,你的身边有几位特别执着于此的同事。他们的热情感染了你;他们的见解启发了你;和他们在一起,你拥有独自学习无法获取的资源。所以我感到,最差的情况,通过加入兴趣小组至少可以帮助你了解自己是否真的对某件事情有兴趣。比较好的情况,你的兴趣能在一群志趣相投的人的带动下中得到更多的培养和发挥。

  二、学习小组

  学习小组和兴趣小组大同小异。我理解的不同之处在于:学习小组的学习内容可能是大家并不了解和感兴趣,但有学习的必要的。比如,一个新的技术(如云计算)或者软件开发模式(如敏捷开发)。

  当大家沉浸学习的热情中,因为众多的资料和分享而感到充实欣喜时,我不禁要担忧:有多少知识真的能改变我们的思维模式?有多少的技能能运用到我们的工作中去?几年前,我们曾经组织过对经典书籍的集体学习,但最终发现由于难以和工作相结合,不到半年那些知识也大都淡忘了。

  为了团队学习能取得更好的实际效果,如果说兴趣小组更多的是靠个人的热情和持续投入,学习小组更多的是靠基层管理人员的引导。因为高层肯定强烈反对光学不练,弄不好可能在一定程度上打击了大家学的热情;而个人大多根据喜好进行学习,追求个人发展,不大容易把个人需要和公司的需要联系起来。对于那些分享就是结束的学习活动,基层管理人员应该尽量控制其比例,并引导团队了解:学习的气氛很重要,但对于职场人士,学习只是手段,帮助公司和客户实现价值才是目标。

  三、实践社区(Community of Practice)

  何为“实践社区”?简而言之,就是一群有类似职业/技能/兴趣的人非正式地聚集在一起形成的交流实践经验的虚拟社区。

  与兴趣小组和学习小组不同的是,实践社区更注重实战,因而其对人的影响也从认知层面到了操作层面。由于软件开发的唯一性、独特性,即使是别人总结的最佳实践,也是建立在特定的前提基础上。所谓“纸上得来终觉浅,觉知此事要躬行”。比如,大家都在进行团队学习,为什么他们会采用这样的方法?为什么我们采用了类似的方法效果却相差甚远?为什么我们的最佳实践在别的地方却行不通?了解了背后的原因后,就可以更客观和全面地比较多个做法,从而摸索出特定情况下的最佳实践。

  我们对于实践社区的做法是细分测试的流程,定义其主要输出物。然后每个项目都在这些共同的环节提供各自的实际样本。在有差异之处进行充分讨论,最终形成大家的共识,流程整理为指导文档,输出物整理为模板,都设立基线。以后大家共同工作以此为基础,并定期回顾和修改。我们追求的并不是统一,而是不统一处有一个可以接受的理由。我们追求的也不是规范,而是特定情况下最适用的方法。除了已有实践的分享,我们也少量吸纳了一些外部的最佳实践,在个别项目中先试行,然后从实践社区中推动到更多的项目中去。比如缺陷正交分析法、测试覆盖率度量和持续集成等。另外,我们还在考虑借鉴开发团队的代码道场,组织一些测试执行道场。我们感到与其它两种团队学习方法相比较,实践社区最容易在组织级别产生实际效果,因而也更容易得到项目和管理团队的支持。

  无论你的团队采取哪种学习组织形式,热情、承诺、务实是我们实践过程中总结下来的三个要素。无论你走到哪里,找到属于你的圈子,和大家一起学习和成长吧!

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

MySQL数据库性能优化之表结构优化

  很多人都将<数据库设计范式>作为数据库表结构设计“圣经”,认为只要按照这个范式需求设计,就能让设计出来的表结构足够优化,既能保证性能优异同时还能满足扩展性要求。殊不知,在N年前被奉为“圣经”的数据库设计3范式早就已经不完全适用了。这里我整理了一些比较常见的数据库表结构设计方面的优化技巧,希望对大家有用。

  这是MySQL数据库性能优化专题系列的第二篇文章:MySQL 数据库性能优化之表结构优化

  系列的第一篇文章:MySQL 数据库性能优化之缓存参数优化

  由于MySQL数据库是基于行(Row)存储的数据库,而数据库操作 IO 的时候是以 page(block)的方式,也就是说,如果我们每条记录所占用的空间量减小,就会使每个page中可存放的数据行数增大,那么每次 IO 可访问的行数也就增多了。反过来说,处理相同行数的数据,需要访问的 page 就会减少,也就是 IO 操作次数降低,直接提升性能。此外,由于我们的内存是有限的,增加每个page中存放的数据行数,就等于增加每个内存块的缓存数据量,同时还会提升内存换中数据命中的几率,也就是缓存命中率。

  数据类型选择

  数据库操作中最为耗时的操作就是 IO 处理,大部分数据库操作 90% 以上的时间都花在了 IO 读写上面。所以尽可能减少 IO 读写量,可以在很大程度上提高数据库操作的性能。

  我们无法改变数据库中需要存储的数据,但是我们可以在这些数据的存储方式方面花一些心思。下面的这些关于字段类型的优化建议主要适用于记录条数较多,数据量较大的场景,因为精细化的数据类型设置可能带来维护成本的提高,过度优化也可能会带来其他的问题:

  1、数字类型:非万不得已不要使用DOUBLE,不仅仅只是存储长度的问题,同时还会存在精确性的问题。同样,固定精度的小数,也不建议使用DECIMAL,建议乘以固定倍数转换成整数存储,可以大大节省存储空间,且不会带来任何附加维护成本。对于整数的存储,在数据量较大的情况下,建议区分开 TINYINT / INT / BIGINT 的选择,因为三者所占用的存储空间也有很大的差别,能确定不会使用负数的字段,建议添加unsigned定义。当然,如果数据量较小的数据库,也可以不用严格区分三个整数类型。

  2、字符类型:非万不得已不要使用 TEXT 数据类型,其处理方式决定了他的性能要低于char或者是varchar类型的处理。定长字段,建议使用 CHAR 类型,不定长字段尽量使用 VARCHAR,且仅仅设定适当的最大长度,而不是非常随意的给一个很大的最大长度限定,因为不同的长度范围,MySQL也会有不一样的存储处理。

  3、时间类型:尽量使用TIMESTAMP类型,因为其存储空间只需要 DATETIME 类型的一半。对于只需要精确到某一天的数据类型,建议使用DATE类型,因为他的存储空间只需要3个字节,比TIMESTAMP还少。不建议通过INT类型类存储一个unix timestamp 的值,因为这太不直观,会给维护带来不必要的麻烦,同时还不会带来任何好处。

  4、ENUM & SET:对于状态字段,可以尝试使用 ENUM 来存放,因为可以极大的降低存储空间,而且即使需要增加新的类型,只要增加于末尾,修改结构也不需要重建表数据。如果是存放可预先定义的属性数据呢?可以尝试使用SET类型,即使存在多种属性,同样可以游刃有余,同时还可以节省不小的存储空间。

  5、LOB类型:强烈反对在数据库中存放 LOB 类型数据,虽然数据库提供了这样的功能,但这不是他所擅长的,我们更应该让合适的工具做他擅长的事情,才能将其发挥到极致。在数据库中存储 LOB 数据就像让一个多年前在学校学过一点Java的营销专业人员来写 Java 代码一样。

  字符编码

  字符集直接决定了数据在MySQL中的存储编码方式,由于同样的内容使用不同字符集表示所占用的空间大小会有较大的差异,所以通过使用合适的字符集,可以帮助我们尽可能减少数据量,进而减少IO操作次数。

  1、纯拉丁字符能表示的内容,没必要选择 latin1 之外的其他字符编码,因为这会节省大量的存储空间。

  2、如果我们可以确定不需要存放多种语言,就没必要非得使用UTF8或者其他UNICODE字符类型,这回造成大量的存储空间浪费。

  3、MySQL的数据类型可以精确到字段,所以当我们需要大型数据库中存放多字节数据的时候,可以通过对不同表不同字段使用不同的数据类型来较大程度减小数据存储量,进而降低 IO 操作次数并提高缓存命中率。

  适当拆分

  有些时候,我们可能会希望将一个完整的对象对应于一张数据库表,这对于应用程序开发来说是很有好的,但是有些时候可能会在性能上带来较大的问题。

  当我们的表中存在类似于 TEXT 或者是很大的 VARCHAR类型的大字段的时候,如果我们大部分访问这张表的时候都不需要这个字段,我们就该义无反顾的将其拆分到另外的独立表中,以减少常用数据所占用的存储空间。这样做的一个明显好处就是每个数据块中可以存储的数据条数可以大大增加,既减少物理 IO 次数,也能大大提高内存中的缓存命中率。

  上面几点的优化都是为了减少每条记录的存储空间大小,让每个数据库中能够存储更多的记录条数,以达到减少 IO 操作次数,提高缓存命中率。下面这个优化建议可能很多开发人员都会觉得不太理解,因为这是典型的反范式设计,而且也和上面的几点优化建议的目标相违背。

  适度冗余

  为什么我们要冗余?这不是增加了每条数据的大小,减少了每个数据块可存放记录条数吗?

  确实,这样做是会增大每条记录的大小,降低每条记录中可存放数据的条数,但是在有些场景下我们仍然还是不得不这样做:

  1、被频繁引用且只能通过 Join 2张(或者更多)大表的方式才能得到的独立小字段。

  2、这样的场景由于每次Join仅仅只是为了取得某个小字段的值,Join到的记录又大,会造成大量不必要的 IO,完全可以通过空间换取时间的方式来优化。不过,冗余的同时需要确保数据的一致性不会遭到破坏,确保更新的同时冗余字段也被更新。

  尽量使用 NOT NULL

  NULL 类型比较特殊,SQL 难优化。虽然 MySQL NULL类型和 Oracle 的NULL 有差异,会进入索引中,但如果是一个组合索引,那么这个NULL 类型的字段会极大影响整个索引的效率。此外,NULL 在索引中的处理也是特殊的,也会占用额外的存放空间。

  很多人觉得 NULL 会节省一些空间,所以尽量让NULL来达到节省IO的目的,但是大部分时候这会适得其反,虽然空间上可能确实有一定节省,倒是带来了很多其他的优化问题,不但没有将IO量省下来,反而加大了SQL的IO量。所以尽量确保 DEFAULT 值不是 NULL,也是一个很好的表结构设计优化习惯。

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

WP刷机

http://www.wpkong.com/thread-8247-1-1.html

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

软件测试缺陷处理注意事项

  一、针对nobug的缺陷

  1、产品经理针对产品建议类的缺陷若本版本暂时不修改,可以将bug进行nobug处理,但需要让其将缺陷提交到jira作为产品建议记录,并且在缺陷备注说明jira id。同时测试人员将缺陷的summary前加上【jira建议】以便测试分析时筛选。

  2、针对系统集成类的缺陷,所谓系统集成类的缺陷是本项目无法修改,需要其他项目才能修改的缺陷。这类缺陷产品经理可以将缺陷nobug处理。测试人员需将缺陷的summary前加上【系统集成】以便测试分析时的筛选,同时测试人员还需将缺陷拷贝一份到相应项目的TD-单元集成测试中,并发送邮件通知相应项目的项目经理、产品经理并跟进缺陷处理情况。

  3、针对无法重现的缺陷,若确实无法找到规律并解决,产品经理可以nobug处理;但测试人员仍需进行进行缺陷验证,若重现此缺陷将缺陷open起来并修改相应的缺陷描述;若下一循环验证确实没有重现,在缺陷的summary前加上【无法重现】一遍测试分析时筛选。

  4、针对描述不同但可能产生原因是同一个缺陷,开发人员解决缺陷若判定为重复缺陷将缺陷nobug,测试人员验证nobug缺陷时若该缺陷仍然存在则将该缺陷进行reopen操作,并说明reopen原因。

  5、针对修改需求的缺陷,产品经理、开发人员若有进行修改需求则不能让其将缺陷nobug处理;需要修改用需、软需后将缺陷fixed处理。若开发人员将此类缺陷nobug,测试人员可以将缺陷open起来重新修改。

  二、针对reopen的缺陷

  1、上一循环发现功能未实现的缺陷,在这一循环已实现但实现的功能存在某一功能错误,此时测试人员可以将上一循环的缺陷closed,并重新提交一个新缺陷,无需进行reopen操作。

  2、测试人员reopen缺陷时需在comments说明这个缺陷reopen的原因再进行操作reopen。

  3、原则上我们提出的缺陷没有修改而开发人员将缺陷fixed处理了,我们验证缺陷时均采用reopen操作。但测试负责人可以自己把握这个度,可以视项目情况、开发人员等情况适当放松,比如一些很小的缺陷,比如提示信息修改不完全,或者一些很小的需求问题修改不完全,可以跟缺陷解决人说明并让其修改,将缺陷closed处理。

  4、验证缺陷时因为其他缺陷的影响导致此缺陷无法验证,此时仍判定为缺陷无修改将缺陷reopen处理。

  三、针对deffred的缺陷

  原则上这些缺陷我们可以不用进行处理,但部分项目存在产品经理忘记将deffred的比较严重或影响项目结项的缺陷open起来处理,导致项目最后一个循环才来着急的处理这些缺陷。测试负责人可以在每个循环测试前关注deffred的缺陷,若判定这些缺陷较为影响产品质量需提醒产品经理或项目经理及时对这些缺陷进行处理。

  当然,各个项目仍存在一些特殊的情况可能会需要特殊处理的,以下几个问题请各测试人员务必答复(尤其是测试负责人);

  1、测试过程中还遇到哪些处理缺陷时不知如何操作或纠结的情况,可举例说明?

  2、针对以上处理缺陷的流程和方法有何意见或建议?

  3、针对缺陷处理的流程有何补充,或者在你所接触的项目还有其他处理缺陷的流程吗?

posted @ 2012-05-03 10:06 顺其自然EVO 阅读(383) | 评论 (0)编辑 收藏

仅列出标题
共394页: First 上一页 330 331 332 333 334 335 336 337 338 下一页 Last 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜