争论与论证从来都不是新鲜事物,作为软件行业的科技工作者,理应对各种论证的手段了如指掌才是。然而,从各种我参与的有争论的场合来看,事实并非如此。许多论证最终都停在口号式的结论,或是由于自说自话无法进行下去。科学对人类的贡献之一在于科学的方法,而“合理”的论证方式才是科学真理得以彰显的手段。
《论证是一门学问》一书中提到了论证的基本规则,以及各种论证的方式:类比论证、因果论证、演绎论证。这些方法都不是什么难度很高的方法,但在实际的争论过程中,尤其是在微博上进行的论证中(字数的限制也是导致误解的原因之一),却并不经常被论证的双方所遵守。
一个观点包含“前提”和“结论”。前提是为你的结论提供理由的表述。前提一般基于具体的事实或是已经被事实证实的结论,通过前提,借助各种论证的方法就 能推导出结论。这个过程看似简单,在很多情况下却并非显而易见。《论证是一门学问》一书的第3页给出了《福尔摩斯全集》中的《银色白额马》中福尔摩斯的一 个推论过程:
马厩里养着一条狗,然而,尽管有人进入马厩并牵走一匹马,(这条狗)却没有叫……显然,……来者是这条狗相当熟悉的一个人。
在这个推论中,福尔摩斯有两个前提。一个显而易见的前提是,狗没有冲着来人叫;另外,福尔摩斯使用了一个他认为我们都会认可的前提:狗会冲着陌生人叫。这两个前提合起来,便能够得出他的结论:来人是狗熟悉的人。
接下来我们用几个更贴近各位工作实际的例子来展示不合理的推论过程。
例1:
软件测试工程师懂得开发后,会从开发的角度思考问题。这样测试工程师就不能起到与开发工程师在思路上互相补充的效果了。
这个推论过程是一个典型的假言三段论(Hypothetical syllogism,见《论证是一门学问》P80),这里的要点是,只有在连续的两个推论都都没有问题的情况下,最后的结论才是有效的。这里的两个推论分 别是:1,如果软件测试工程师懂得开发,就会从开发的角度考虑问题;2,如果测试工程师从开发的角度考虑问题,就无法起到与开发工程师在思路上互相补充的 效果。
显然,对第一个推论,其要害在于,是否一个人懂得了某种思考方式,就一定会应用这种思考方式?答案显然是否。很容易用反例方法推翻这个推论:成人通常也可以懂得儿童的思维方式,但这并不意味着他一定会用儿童的思维方式去思考问题。实际生活中,大多数父母都能够在懂得儿童思考问题的同时用成人的思考方式考虑问题。
因此,由于第一个推论就不成立,最终的结论显然不可靠。
例2:
很多组织甚至认为独立的测试团队是不需要的,这种观点是错误的!他们认为测试不重要是因为他们对质量不重视!。
这里的前提有两个:1,很多组织认为独立测试团队是不重要的;2,这些认为独立测试团队不重要的组织不重视质量。很显然,稍微深入一点探讨这个结论,就 很容易发现,“很多”这个前提没有数据来源,可能仅仅是推论者的一个主观感觉;另外,由于“很多组织”本身就是一个虚拟出来的概念,更谈不上有任何实例来 说明“很多组织”中的这些都是对质量不重视的公司。反而,针对这个论断,容易举出好些反例来证明它是不可靠的(大多数互联网创业公司都会在很长一段时间内不设置独立的测试团队)。
关于例1和例2提到的话题,我并不想在这里进行讨论。拿它们做例子,不过是说明一个有效的论证应该是什么样子的。
论证中,一方面需要为自己的观点提供可靠的前提,提供合理的逻辑推断过程,同时也需要对自己不认同的观点提出置疑和反驳。与众不同的观点并不可怕,可怕的是无法以符合逻辑的方式捍卫自己的观点。
当对自己不认同的观点提出置疑的时候,反例是最简单的方式。但要举出反例,必须清楚的了解对方观点的定义。由于所有观点就是基于前提(事实)和推理过程的,证明对方的前提的不正确性,或是证明对方的推理过程的不正确性同样奏效。例如,有以下观点:
例3:
Google的测试工程师与开发工程师的比例是1:10,因此只需要少数的测试工程师就能做好测试工作。
这里的前提有三个:第一个是显而易见的前提,“Google测试工程师与开发工程师的比例是1:10”;第二个是隐含的“Google的测试工 作做的很好”;第三个前提隐藏得更深,“Google的测试工作完全是由测试工程师来做的”。这三个前提中的任何一个不成立都会导致这个结论不成立。在我 看来,最容易被击倒的是第三个前提(“Google的测试工作完全是由测试工程师来做的”),实际上,这个在Google内完全不成立。但有趣的是,相当 多的对这个观点的辩驳都集中在第一个和第二个前提上。
例4:
Google的X项目的工程师共有15名,其中测试工程师4名,因此Google所谓的开发与测试人员的比例是1:10是不真实的。
很显然,这个论断根本就偷换了要反驳的结论。“Google的开发与测试工程师比例是1:10”并不等于“在所有Google的项目中开发与测试的比例都是1:10”。因此,要推翻这个前提,其实最简单的方法是拿到Google的开发工程师与测试工程师的总人数比例。
例5:
Google的产品经常出现bug,因此Google的测试做的并不好。这些不好都是由于Google的测试工程师太少造成的。
可靠的前提才能建立可靠的结论。说Google的产品经常出现bug,最好拿出相应的数据。这方面James A. Whittaker显然就老练得多,这哥们在自己blog的为什么要离开google的文章中用了一些他自己的感知数据证明这一点。不过即使这 样,Whittaker也没有说“google的测试做的不好”,原因是“好”与“不好”根本就没有数字上的标准,bug数多少叫做好?bug的影响范围 (人数)与造成的失效成本要不要计算?这个推论的第二个部分则更是“冲动论证”的典型。它同样隐含了两个前提:1,在google中,发现缺陷是测试工程 师的职责;2,测试工程师数量的多少与产品中遗留缺陷的数量呈负相关。可惜的是,这两个前提都不能够成立。
啰嗦了一堆文字,也给出了一些我自己能看到和听到的不合理的论证,不过,这篇文章的用意并不是想在这些例子涉及到的问题上挑起争端,而只是希望大家都能够用更好的论证方式捍卫自己的观点,以及看待别人的观点。
我经历过和了解到的中国的学校(大学、中学、小学均如此),大多都不太在意对学生论证能力的培养,作为这个体制中被培养出来的一员,我在很长时 间内一直没有掌握正确的论证方法。但随着工作中的体验越来越多,接触到了越来越多的优秀同事,才发现自己身上缺少的这种论证方法的确会影响到自己的发展和 工作。鉴于此,我希望通过本文,能够让更多的工程师,尤其是测试工程师了解到论证的方法,希望有更多人能从论证中找到棋逢对手的乐趣。
软件自动化测试,作为手工测试的替代,越来越受到关注。Pekka Klärck,作为Robot Framework的创建者和核心开发者,按照系统级别,介绍了几种不同的自动化测试方法的区别。
一、记录回放的方式流行于商业工具之中,无需编程技能即可快速上手。然而这种方法相对脆弱,一旦UI变化测试就会受到影响,分散的脚本不可重用且难以维护,而且系统在测试前必须可用(也就意味着无法使用A-TDD方法)。因此这种方法并不适合大型自动化测试。
二、线性脚本允许使用各种语言来编写非结构化脚本,脚本直接与被测系统交互。能够快速上手,灵活性强。但是编写脚本需要编程技能,系统中一个改动会影响所有脚本,没有经过模块化或重用的大量脚本难以维护。因此这种方法适合简单任务,不适合大型自动化。
三、模块化脚本由两部分组成:驱动脚本执行测试,测试库函数完成与被测系统交互。驱动脚本编写起来非常简单,这样可以更快地建立新测试,容易维护。然而需要花时间和编程技能建立测试库,并将测试数据嵌入脚本,建立新测试就需要新的测试脚本。因此,只要拥有编程技能,这种方法还是适合大型项目,但不适合非编程人员。
四、数据驱动方法,将数据与测试脚本分离,基于模块化的测试库,一个驱动脚本可以执行多个相似测试,这样非常容易建立新测试。维护工作可以分离,测试人员负责数据,程序员负责写测试库。然而,不同类型测试仍需要新的驱动脚本,初始建立数据解析器和重用组件需要花人力。这种方法适合大型项目,只需要较少的编程技能。
五、关键字驱动,将数据与关键字结合来描述如何使用数据执行测试。这种方法具备数据驱动的优势,同时非编程人员也能建立新类型测试。所有测试由同一个框架来执行,无需不同的驱动脚本。然而初始成本很大,但是可以使用开源方案!因此非常适合大型项目。
Pekka对以上五种方法的介绍其实也是对自动化测试发展史的介绍,同时也体现了RobotFramework背后的设计思想。
除了测试框架的选择,要想做好自动化测试,还要关注其他方面。
自动化测试需要关注可测性。自动化最难的部分是与被测系统交互,特别是GUI层。确保系统容易被测试,比如给GUI元素增加标识、输出易于解析的文本、提供自动化接口等。
系统一般可以分为GUI层以及GUI之下的业务层。GUI层测试需要调用与普通用户同样的接口,但是某些GUI技术缺乏好的工具支持,会使测试变得脆弱,而且执行相对较慢。从业务层开始测试相对容易,执行快。但GUI层仍然需要被测试,以保证GUI正确连接到了业务层,甚至有时GUI层也具有业务功能。Pekka建议考虑对业务层进行完全测试,而部分地对GUI层实行端到端测试。 不是所有系统都具有GUI层,却可能具有API、数据库、服务器、命令行等。自动化测试框架可以调用不同驱动来进行测试。这些非GUI层相对容易测试,只要把测试用例看作另一个客户端而已。
那么自动化测试应该在什么阶段进行?如果开发完成后单独做自动化,这是典型的瀑布式过程,不同团队之间存在沟通障碍,反馈周期慢,产品在后期难以获得可测性,从而导致复杂和脆弱的测试方案。相反,典型敏捷式过程中,程序员和测试人员协同完成自动化。把自动化看作团队开发的一部分,可测性不再是问题,团队做技术决定时就可以考虑可测性和工具选择,程序员可以提前加入提供可测性的钩子特性。
自动化测试需要版本控制和持续集成来支持。将测试和代码放在一起,像管理代码一样管理测试脚本,那么多可用工具,SVN、GIT、Mercurial,没道理不用。持续集成是全方位自动化的关键,当测试或代码有所改动立即执行测试。如果测试运行时间比较长,也可以定期运行。使用Jenkins、Hudson、Cruise Control、 BuildBot吧,自己写定时脚本或Cron Job可以休矣。
选择商业自动化工具还是开源工具?好东西肯定贵,但是贵的不见得好,再便宜的许可证也会阻止整个团队的协作。而且商业化工具难以和其他自动化工具(特别是其他厂商的)或版本控制、持续集成进行整合和定制化。另外,产品终止或公司关门是潜在的风险。开源工具可供选择余地很大,当然也是良莠不齐。开源工具通常容易与其他工具整合,关键是免费,谁都可以随意使用和定制化,还永远不会消失。至于免费软件,越来越少了,很多自由软件都已经开源。免费软件同样不能定制化,且存在中止的风险。
做自动化需要哪些技能?一般来说,包括Python、Ruby、Perl、JavaScript、正则表达式、XPath和CSS定位、SQL语句、版本控制等。
有了自动化,手工测试还需要吗?当然需要!!不过,要避免手工执行脚本来测试,还是将其完全自动化吧,测试人员可以更多关注于探索性测试。 记住,机器擅长回归测试,人类善于寻找Bug。
与以前使用性能工具和终端性能测试做的方式不同,自己亲自部署的性能环境对性能测试的理解,还有测试的经验以及对性能测试开发的一些功底都是一个考验,因为这次是从一行代码都没有到个人发布的第一版性能测试程序(用例)间解决很多难题,所以趁现在有空闲时间备忘下这次做偏网络性能测试的经历。
设计阶段的时候一定需要弄清楚这次性能测试的目的和要点。与用lr的web网页性能测试不同,我是测试更底层或者说是网络层的性能。与手工测试不同,做性能测试务必有需求,即使没有需求都需要组织会议来自己定制一套需求。在做性能测试的经验中,70%~80%是做和开发组相似的工作,所以没有需求的话,写着写着就会融入自己的主观误区,很容易写出来的东西根本不符合项目组的要求,尤其是做socket的编程。对于网络相关的测试,不用太过于关注一些平常web性能的指标,最重点关注是每秒的处理数,服务器的极限值,模拟真实的流程还有根据这些设置值来定制出一个产品的性能说明书。主要的设计参考为同类产品的对比,主流服务器的性能指标,还有产品的峰值。
部署性能测试开发阶段需要根据你的设计和项目组或你自身水平(实际项目由我个人弄)来评定需要那些东西来做开发活动。对于测试开发来说,偏应用的语言和脚本是相对好用的。大多情况下我会选择做常链接不错的java和资料充足的python脚本来制作测试开发,假如是有图形界面的话C++和java是比较好的选择。为什么我会重点提这3个语言,我经历过的自动化组虽然不是全部都用以上的语言,但是在google强大的开源帝国中提供了很多自动化测试框架和模块(例如安卓的java robotium,C++的GoogleTest,支持很多API和多个linux支持的python)本身就带有优势。重点在于这3个语言对oracle或其他数据库都有很好的交互,性能测试很少不和数据库打交道。其次也可以选择你很熟悉的语言做自动化。
开发环境搭建阶段,做测试核心之一的就是返回结果来对期望结果进行匹配,你获取结果的地方最多就是在服务器端,很多时候我们在windows开发,获取结果在linux服务器,所以搭建开发环境对编译器,对打包的工具,对一些项目组现有的工具,还有各自操作系统带有的小工具都要进行考量。必要时甚至可以用lr和QTP来辅助。同时要对项目的协议进行分析,解析包,把底层交互的接口都编写完整,当然项目组做了给你更加好。
程序设计阶段,好比做C++开发和数据库开发的理念不同,做测试开发也有着不同的理念。我们本身是测试代码,在我此次项目经历考量的最多就是操作系统,编译器,公司网络,本身语言对网络方面的性能和限制。我们做的不是安全防御,不是应用系统,最终目的是提出一个说明书和提交bug,所以我们需要知道我们执行程序发现的问题是产品问题还是上述问题,即使用lr测试也是如此。这里说下几个理论:我们的程序做到什么程度?平台化?程序化?脚本化?因为负责的只有我一个人,所以只做到脚本化。还有脚本的分布。因为我们是用例,而且大多是性能用例,不像别的功能用例自动一个个串行执行。所以在我选择了功能强大的语言时我的测试脚本分为应用层(执行用例的函数),特性层(linux,windows,数据库,网络编程的特性函数),忽略底层(因为语言已经封装很好) ,然后因为性能用例的特征做了一个选择的接口层(每次每台测试机只执行一个性能用例),然后根据用例的目的进行分类,测试模拟真实环境的性能指标用例,测试负载的峰值指标用例,测试压力的用例(分测试客户端用例和备用客户端用例,往往压力挂了,自主开发的主用例很难再去给压坏的服务器做判断)
测试的部署阶段,当你的用例第一版正式投入测试的时候,需要关注的是:你实现压力的方式,综合客户端和综合服务器的限制。例如lr这样的性能工具是怎么做到超越一般的并发数的,是靠巧妙的编程方式还是通过提供的服务器,在我自己弄整个过程,我大概也摸清了一小部分lr的底。除了评估出各方面性能所需要准备的测试机外,最重要是如何以最小的代价抓出最多的bug日志,打印日志算是一个影响机子性能的关键点。
总结:下一步不管网页相关的性能是由我做还是使用lr工具,最重要还是要提高代码的函数通用性,我经历的测试组的代码很多封装的惨不忍睹,因为很多测试人员测试时抽空出来写自动化用例不可能会像开发那么专心。其次是继续提升自己对操作系统,数据库和网络本身的一些基本配置问题要更加了解,我提交很多致命单往往都是很简单的东西造成的。最后要按需求走,每做一个改动和新增要知道自己测试和发现的是自己的程序性能问题,还是局域网络问题,或者是原生产品操作系统问题,排除完后提交bug。
小数据:总编写时间3~4个星期的脚本在一个迭代中发现了15个严重级别或以上的单。自己编写性能脚本效率在初中期开发其实不比lr差。
摘要:随着人们对软件质量要求的不断提高,软件开发的每一个环节都应该得到十足的重视,俗话说:“细节决定成败”,就此,本文提供了一个代码审查“思维导图”,希望对所有码农们有所帮助。
代码审查,就好比编辑写完一篇稿子需要审核一样。在如今的开发中,代码审查工作越发重要,如果做的好,对项目会有很大的帮助,如果做的不好,只会费时又费力,或许还会引起一些不必要的麻烦。
下面是一个代码审查的“思维导图”(使用Xmind)。把所有涉及代码审查的要点联系在一起,希望对您能有所帮助。
点击图片查看大图
以下是一些开发者使用代码审查发表的一些精彩评论:
1、我认识一个团队领导,他有一个非常好的代码审查系统,通过发送公共邮件来进行审查。他相信(很多事实表明,使用代码审查有利于项目开展,并且大家一直坚持这个信念)通过这种“公共”代码审查工作来培养团队里面的每个成员,而不是每个成员只负责审查自己的代码。这一做法对整个团队产生了非常好的影响。
2、在代码审查期间,使用TODO和FIXME来标记代码是非常有好处的。但是我目前还尚未使用像gerrit之类的其他工具。
3、代码评审应该作为项目完成计划中的一部分,——在别人还没有对代码进行审查之前,任务都是出于未完成状态。
4、我不喜欢团队审查代码这件事,这几乎是不可能而且没有时间去完成的,甚至在某些情况很难与领导沟通。反而我更喜欢同级评审这个想法,因为有一些初级的家伙不能够正确地执行代码评审(至少在初期)。
随着软件质量的不断提高,代码评审这一话题正在码农之间展开激烈的讨论,对于到底是否需要代码评审,各位码农们,你们又是如何看待的呢?
改进型组织是一个平衡发展的组织,它由业务线、流程线、QA线、IT线、协调线共五线组成,简称五线谱组织。
业务线:负责产品质量、过程质量、为执行负责;
流程线:负责流程质量,为优化流程负责;
QA线:负责识别流程执行偏差,提供执行的第三方可视性,为流程可视性负责;
IT线:负责流程的IT化质量,为流程高效负责;
协调线:负责业务线、流程线、QA线、IT线的平衡发展,负责他们协同工作,为协同、平衡负责。
企业发展的初期,一般由业务线、IT线、协调线构成,IT线的工作一般是维护日常办公,确保其他人员正常工作,协调线由一把手亲自挂帅,业务线为企业赚 取合法的利润,推动公司的进一步发展。这时候的企业我们一般叫人治期的企业,依靠老板的&lsquo人治&rsquo进行管理,因为人 少,人治期管理往往高效,否则无法度过人治期。
度过人治期的企业,规模越来越大,依靠人的管理已经不能适应企业发展的当前需求,因为随 着人员的增加,沟通成本在上升,组织效率在下降,这时需要从人治走向法治,需要把组织中的骨干人员的工作经验,沉淀到公司的流程制度中,形成牛路,在组织 内进行推广,建设成高速公路。高速公路建成后还需要寻找到一条能用数据证明成功的改进之路。本阶段的企业我们称为法治期企业。法治期的企业需要建立流程 线、QA线,强化IT线、协调线。我国的法治建设还有很长的路要走,不仅仅是制度的缺失,更重要的是制度的执行,所以温总理说:遇上一个好总理,不如有一 个好制度。遇上好总理救了一个白血病患儿,如果有一个好的白血病儿的救助制度,挽救的则是上万人的宝贵生命。我不妨补充一句:一个好制度需要一个好机制才 能得到执行,改进型组织就是一个好机制运行的最佳实践。
国内很多企业在从人治走向法治的过程中往往忽略流程线、QA线的人员建设。
比如有的直接导入ERP,造成不上ERP等死,上ERP找死。就其原因,不是ERP本身不好,而是方法不对。ERP的本质就是企业供应链流程的载体,导 入ERP需要梳理供应链流程,需要流程线的人员,流程梳理后需要有人去识别流程的执行情况,需要QA人员。如果我们忽略流程线、QA线的队伍建设,强行把 供应链的流程固化到ERP软件,短期看的确可能提升了效率,从长远看,组织流程优化的效率被降低了。
有的企业在引入ISO9000,CMMI、IPD、6sigma的过程中,常常造成流程和执行两张皮,他们把过程改进等同于引入先进的流程、照搬模型或标准,囫囵吞枣,忽略流程线、QA线人员建设,反反复复折腾3、5年,还是发现流程无法有效执行。他们急于看到过程改进的效果,结果总是欲速则不达。就其根源,还是在于忽略了五条线(业务线、流程线、QA线、IT线、协调线)的平衡发展。
所以我们说,良好的改进型组织是一个业务线、流程线、QA线、IT线、协调线平衡发展的组织。
改进组织:
过程改进必须以项目方式来进行,需要规划好每期项目的目标和范围,规划项目的过程就是开发正确的产品,为过程改进项目提供正确的方向,规划过程改进的组织一般叫做管理导航组,职能类似于产品经理(规划出合适的产品,以满足客户的需要)。
过程改进项目是一个执行主体,主要任务是完成项目目标,正确地开发产品。
业务线
业务线的职责是正确的执行流程,为客户提供优质产品,为企业赢利。业务线就是一个传统的公司,包含市场营销、研发部、生产、采购、计划部、技术支持部、客服部、财务部、人事部、行政部等。
随公司的发展,流程线、QA线的增加,IT线、协调线的强化,公司发展成为一个改进型的组织机构。
矩阵结构是业务线的常见运行模式,业务线由资源线、项目线构成,项目线以项目为单位进行管理,每个资源向资源线、项目线的领导同时汇报。
梳理项目线的工作是企业流程改进主要工作。资源线的工作是基础,项目线是工作效率的直接体现。为平衡资源线与项目线的职责划分,部分公司把平台建设划归资源线负责。一般地:例行工作划归部门工作,项目工作划归项目线工作。
流程线 流程线的职责是定义或优化公司流程,流程线的人员组成由专职EPG和兼职EPG组成,专职EPG来自过程管理部,其擅长领域一般有:过程改进、 CMMI、IPD、ISO9000、6sigma等。兼职EPG则根据改进项目的覆盖范围来自相应的部门。兼职人员需要选择骨干人员,形成公司的牛路,代 表公司的高效的工作方式。
识别牛路,将骨干的知识经验沉淀到公司的流程,通过培训、试点、推广建设成公司的高速公路是过程改进的基础工作。
QMS质量文件体系
我们把流程线发布的所有流程的集合叫QMS质量文件体系,QMS质量文件体系包含架构和若干个过程,每个过程由过程定义、规范(可选)、标准(可选)、培训教材、记录文件组成,记录文件一般有模板、表格、过程检查单、产品检查单;
QMS架构
架构包含QMS概貌图、研发管理流程、供应链管理流程、项目管理流程、文件体系。
过程开发步骤
1、由骨干与专职EPG形成初稿,然后向EPG Leader提交评审申请;
2、EPG Leader审核流程初稿,审核通过后安排评审计划,确定参加评审的人员、时间、地点、分工等;
3、评审人员进行预审,根据个人经验和检查单识别可能的缺陷;
4、通过会议识别正式的缺陷,必要时讨论修复措施,修复并验证缺陷;
5、评审关闭后形成正式的工作产品,纳入受控库,打上基线标签;
6、将基线后的工作产品交业务线客户代表进行统一验收,验收通过后进行统一发布。流程发布一定要注意频率,建议在半年以上。
过程资产库PAL
公司资产库一般作为流程线对外的窗口,资产库内容一般包含QMS质量体系文件、公司最佳实践、度量库(过程能力、过程目标等),资产库一般也提供过程改进建议的收集,发布过程改进项目的最新状态和最新规划。
过程资产库需要在项目的执行过程中得到不断的优化。
建立统一的发布窗口,做好流程线发布流程的受控管理,前者方便流程执行者,后者方便流程线自己。
QA线
QA的工作主要是产品过程审计、流程过程审计,引导流程的工作由EPG、兼职EPG完成,QA工作需要保持独立性,以第三方(独立于流程线、业 务线之外)的声音识别流程执行的偏差,为管理层充当第三只眼睛和耳朵。QA既不能把关项目的过程质量,也不能把关项目的产品质量,产品质量和过程质量都是 业务线的职责。
很多公司因为过程审计没有为项目带来价值从而否认QA价值,让QA去组织技术评审,收集度量数据,参加项目的技术文档评审,QA的工作重心已经发生了偏离,流程的执行情况被掩盖,导致几年之后流程还是无法落地,这与QA的声音不响亮有很大关系。
质量领域没有超人,我们不能把QA假定为一个超人去期望QA解决所有的质量问题,只有一个组织分工合理、职责清晰、和谐运作、全员努力,才能解决公司的质量问题。这就是真正意义的全面质量管理。
版权声明:本文出自 mandy.wang 的51Testing软件测试博客,欢迎转载……
测试管理的内容很多,做好测试管理,重要的是把握住几个关键要素。换句话说,测试管理也是对这几个要素的管理,测试管理要素如图所示:
测试配置管理是通过技术手段或者行政手段对测试过程及产品进行控制、规范的一系列措施。目的是记录和追踪测试全过程及每个阶段的产出物,保证测试人员在测试全过程的各个阶段都能获得有效的产品配置。测试配置管理的内容包括配置项标识、配置项控制、配置状态报告和配置审计。
质量管理是 指测试过程中为保证测试质量所采取的控制手段和措施。测试质量管理包括两方面的内容:测试过程质量管理及产出物质量管理。测试过程质量管理是通过对测试效 率及有效性的分析,加强质量控制手段并改进测试过程。测试产出物质量管理是通过对用例、缺陷的分析和维护,保证测试结果的正确性、准确性、一致性和完备 性。
进度管理是通过对测试过程进行阶段划分,明确测试每个阶段的工作内容和分工,将项目总的实施进度细分为每个阶段的进度,通过控制每个阶段的进度,提供预防和纠偏措施,从而保证整个测试过程的进度。
成本管理是对于测试环境、时间、人力、软硬件等资源的管理和控制。一般说来,成本和进度、质量的关系较密切,三者相互影响相互制约,测试管理的目的之一也是在三者中寻找平衡点。
风险管理是通过风险探测、分析和评估,减少或者回避测试过程中的风险因素。
团队管理是对测试过程中涉及的不同角色和人员的管理,包括组织架构、团队建设、测试培训和人员激励措施等。
做了4个迭代的性能测试, 在没有需求的情况下步步艰辛,把代码和框架独立开发从0到一万多行代码的测试工具(脚本),作为性能测试工具佼佼者Lr,我时而拿他作参考,山寨了它很多 东西,同时带有很多疑问对它实现性能测试的原因渡过了为期3个月的性能测试之旅。以下是我对比测试脚本和LR所得出的详细问题:
1、如何计算每秒处理包的数量
我针对这个曾经研究了很久。在多线程的情况下,压服务器的时候,是专门建立一个线程去采集这些信息,还是说在每个线程里面实现这个时间。后来我采取了后者。因为在到达了某项瓶颈之后,这段时间的变化是很小但是也不能忽略了。
例如下面的伪代码1:
EachThread: BeginTime = time.time() Count = 0 While point: If RevPackage() == true: Count = Count + 1 EndTime = time.time() Runtime = BeginTime – EndTime EachsecondRpackage = float(Count) / float (Runtime) EachsecondRpackage = SumAll(EachsecondRpackage) |
伪代码2:
Count = 0 EachThread: global Count While point: If RevPackage() == true: 加锁 Count = Count + 1 解锁 TraceThread: Time.sleep(runtime) EachsecondRpackage = Count / runtime |
第一种,是每个线程自己算时间,然后在point为true的时间内算出每秒的收到的包,然后把所有线程的包加起来。第二种是线程不做任何算法操作。让 单独线程来做。第一种的好处是数值很准确,同时没有在关键点用了影响性能的锁。第二种则对总执行时间的统计很准确,但是里面用了锁。就2种来说一般第一种 用比较多,但是假如在延时比较大的发包或者关注整体事件流用的过程中,第二种的算法比较准确些(注意有时候延时越小不代表压力越大)。这里我带有的疑问 是,lr他是如何设定这个TPS的数字呢?是否2种结合还是只用了其中一种?
说到了锁,在很多性能测试中都会和数据库打 交道。我们当然想建立n多线程去冲击数据库(无论数据库是不是被测系统),但是数据库本身能够接受的线程就是有限制,而且其限制很低,虽然我们在数据库的 操作用线程锁是可以,但是造成个缺点是假如事件流很多,创建虚拟数据,和下发及时命令再带多并发的操作时,这个锁就会让很多线程(尤其是延时小的线程)会 卡在某个事件流的点上,导致socket断了。也影响数据结果(因为不知道算出来数据是否有别的事件导致出现误差)。解决方法是尽量不影响测试的情况下把 能做的数据库数据先做了,实时的数据库建议先在某个点做集合点,统计够了再做压力冲击。这里就用了Lr的集合点概念,注意的还是算平均值的开始和结束事件 要抓准。
说到数据库,假如你的db知识不是很牛的话测试数据lr是个好首选,但是一些复杂情况下我们不是每种用例都适用Lr测试。这时候你需要非常清晰的了解你的测试需求。下面的伪代码:
Python: for i in range(1000): cursor.execute(SQL); |
C++: For (I = 0;i<1000 ;i++) { cursor.execute(SQL); } |
SQL:
FOR i IN 1 .. 1000 LOOP
(SQL)
commit;
END LOOP;
这里用了py和C++,还有数据库本身的循环,3种循环用的时间都是不一样。SQL的最快,C++其次,然后是PY,不同被测系统的需求用不同的方 式测试性能,假如你直接测试数据库某个存储过程,则能用SQL就用SQL,或者其他语言调用的时候循环都要用SQL的,对比被测产品调用SQL的话,则拿 其中一种语言对比调用被测产品和直接调用数据库的差别。对于LR的疑问它假如测试出很多SQL的性能指标后,到底它是如何解决我上面提到的问题呢?
说到循环,每次我们做完测试报告写完宣讲时,开发人员总会问这个瓶颈是产品的瓶颈,还是你测试脚本的瓶颈?所以作为测试用脚本语言当然是首选, 但是脚本语言的效率不高是弱点,所以每次用脚本语言做多线程压力测试的时候,每个关键的循环尽量调用C++等效率高的语句来做,同时注意调用时间。LR这 块其实用的时候偏事件流的方式做,所以像这种变态的压其实比较少。
说到多线程,这是我研究Lr比较多的一个地方。当我自己写脚本的时候经常会深入研究不同操作系统不同硬件对线程的利用率的影响,还有线程锁,和 该不该配合队列,进程来做测试。当然理想是越多测试机做分布式,甚至用云台来做更好。但是现实情况你不仅仅考虑开多少个线程多少个测试机,而是说100个 线程用1台机器跑,和用10台机器跑的差别,测试产品瓶颈首先要测试网络,系统的瓶颈。一台机器假如到达了50个线程和100个线程所出的吞吐量是一样的 话,那么这台机器最佳启动线程是50个。我听说Lr有队列有线程有进程一起配合的情况下做制作并发测试。我也按照他的负载测试方式设计脚本,但是即使是云 台也存在分析操作系统和硬件的弱点,假设lr在单台服务器做1000(假设数据)个并发(不考虑多条件)的话,它到底是怎么实现并发的?
说到了最关键的操作系统,网络,硬件这块了。很多时候我们高科技的性能测试产物—性能报告变成废铁的。就是这3个造成。linux我最高记录并 发10800个线程(4cpu虚拟双倍),win7最高记录2100个线程(双核),这个仅仅是好看的记录,没了!因为我们IO口就这么大,磁盘读写能力 最大限制,网络带宽也有限制,所以上面开到的线程当然可以增加压力,但是在没穷到只剩1~2测试”服务器”的情况下,最好不要用一个方法,毕竟10台吊丝 台式强过1台高富帅服务器做客户端。同时虽然云计算其中一个概念是虚拟化计算,但是并不代表你每个测试机都把资源利用做虚拟机来做压力,因为最关键的线 程,虚拟机本身的软件和操作系统也消耗了一些线程的地盘,所以利用虚拟化计算做测试,需要谨慎。还有一点就是性能命令top,ps,sar等等的数值,你 要注意那些有用,哪些相对准确,虽然linux提供了很多性能命令,但是不代表他们之间是一模一样的。当然lr也是靠人工配合分析组网,测试机的性能。
最后说下你分析和出测试报告。lr的报告很华丽,很多专用性能测试名词都打上一堆,可爱的老大最喜欢看这个赚奖金的东西。但是实事求是的大牛没 那么容易骗过,把公司网络,各个资源都用上来做性能测试肯定要看到有意义的东西。我脚本投入了很多excel图表(交互式调用偷懒),来帮我做出很多图。 性能测试最重要是分析,我上面说的很多技术都为了准确获得数据分析而设计的。所以现在性能测试从单机到分布式到云都往精确这个关键点发展。很多次带着报告 面对各部分的开发老大,作为一个小QC如何把上百兆的日志和数据理出来跟这些高手报告需要注意很多细节。为什么这个阶段曲线会不没规律?什么是瓶颈?有没 问题?这些数据作为参考数据还是代表有问题?系统该不该优化?下一个迭代的任务和程序设计如何做?这些都必须自己理清楚。对比Lr,唯一的优势就是这些数 据我都知道怎么抓来的,但是要比上这个权威的工具,还是需要继续努力缩小差距。
下一个阶段不再是怎么去查询瓶颈,怎么去发现bug为主,因为敏捷到了接近尾声的时候,我需要变成选型工程师的角色,优化程序框架和处理,分析操作系统是主要任务,来为我们的产品节约成本,是性能测试的其中一个因素之一。
版权声明:本文出自 acbennn 的51Testing软件测试博客:http://www.51testing.com/?299791
原创作品,转载时请务必以超链接形式标明本文原始出处、作者信息和本声明,否则将追究法律责任。
Java异常(Exception)又称例外,是一种运行时错误。Java异常机制就是对于Java异常的处理方法,使用Java异常机制能提升程序的容错性,从而使程序更加健壮与安全。
java异常种类很多,常用的异常包括:算术异常类(ArithmeticException),空指针异常类 (NullPointerException),输入输出异常类(IOException),数组下标越界异常类 (ArrayIndexOutOfBoundsException)、类型转换异常类(ClassCastException)等。
Java中常有如下三种异常处理方法:
1、使用try-catch-finally语句。try语句块放置可能发生异常的代码,catch语句块捕获这些代码产生的异常,finally语句块无论程序是否有异常发生,都会执行。
2、使用throws关键字抛出异常。若某个方法可能发生异常,但不想在当前方法中处理这个异常,那就可以利用throws关键字在该方法抛出异常,然后在调用该方法的代码中捕获该异常进行处理。
3、自定义异常类与throw关键字。
关于自定义异常类的使用,分为如下几个步骤:
1)创建自定义异常类,利用继承思想
2)在方法中通过throw关键字抛出异常对象
3)若在当前抛出异常的方法中处理,使用第一种方法,否则使用第二种方法
第一种异常处理方法测试代码如下:
/** *利用try-catch-finally语句块进行异常处理 */ public class ExceptionTest { public static void main(String[] args) { try { int iNum = 5 / 0; System.out.println(iNum); } catch (Exception e) { e.printStackTrace();//指出异常的类型、性质、栈层次及出现程序中的位置 } finally { System.out.println("第一种异常处理方法测试"); } } } |
运行结果如下所示:
第二种异常处理方法测试代码如下:
/** *利用关键字throws进行异常处理 */ public class ExceptionTest1 { public static int divide(int iNum1, int iNum2) throws ArithmeticException { return iNum1 / iNum2; } public static void main(String[] args) { try { int iNum = divide(5,0); System.out.println(iNum); } catch (ArithmeticException e) { e.printStackTrace();//指出异常的类型、性质、栈层次及出现程序中的位置 } } } |
运行结果如下所示:
我们一定会遇到这样的情况:就只改了一行代码,只用对这个改动的地方回归下就好了,为什么上线的时候影响到了其他的业务需求了?
在解决上面的问题之前,我们先简单做两个问答题吧:
问题1:如果两个业务操作的数据载体不会有交集(包括增删查改),这两个业务在系统上会相互影响吗?
问题2:如果两个业务操作的代码写在两个完全不同的地方(代码上没有交集),这两个业务会相互影响吗?
对于数据业务型系统,我现在还没有遇到两个数据载体没有交集的业务操作会相互影响,如果大家有例子,可以分享下哦。
如果两业务代码上没有交集,那我们完全不能保证他们业务上不会互相影响了,大家可以看下下面这张图。
注:这里的数据实体,即数据的载体。
同一个数据实体,会面临不同业务需求的操作,每个业务对该数据实体的操作范围会不同,但是数据实体中数据的变更会对业务造成影响。往往这些影响,局限在本业务范围内是发现不了的,一些暴露出来的缺陷,反而会让人感觉时现时不现(因为只是部分数据被其他业务修改了),很多同学会联想到是不是并发之类的问题导致的。其实如果跳出这个业务范围,站在全局的角度,就很容易发现问题。
所以我们经常需要回归测试,我们现在有大量的回归脚本支持回归测试,但是某些缺陷是无法通过回归脚本发现的,往往需要我们通过对业务的嗅觉,进行回归点的挖掘,来实现对缺陷的预防。
下面举一个现有回归脚本无法发现的缺陷:
前提:业务一的开发早于业务二
(业务二)对某一实体进行修改操作,该改动涉及到一个(业务一)同样关心的字段。
(业务一)对该实体进行查询操作,在解析上面的字段时,由于无法解析而报错。
在单纯对业务一的持续集成脚本的维度来说,无法解析的属性,应该是要报错的,这个异常流程走的很对。
所以如果单纯从之前的回归脚本进行回归而判断这次修改是否影响到了之前的逻辑,是武断的。
同样依靠同学们对业务的熟知度,来挖掘业务二对业务一的影响。这种做法并非科学,任何一种完全依靠人脑来做决定,是会有遗漏的,是有风险的。
再举一个例子通过查代码去发掘回归点可能遗漏的例子
如何发现一段代码的影响范围,大家是不是做过去看下这段代码将会被哪些代码调用,即对应的下游代码。无疑这么做确实可以发现同一流程下的影响点。但如果不在一个流程里面呢?如果相关同学对将会影响到的业务其实并不熟悉,该怎么办?
我们就需要一张大图,一张业务逻辑大图。这张大图的组成为实体+沉淀+入口。
为什么要做这张大图,这张大图是什么样子的?
我们的系统是基于MVC模型,通俗说法就是通过V调用C去操作Ms(因为M可能很多,哈哈)。所以归根结底,变化的是M,影响的也是M。
M,即Model,它主要与数据载体交互的功能。我们将与M交互的数据载体,称为实体。
沉淀,即业务沉淀,即对应的功能点的IO与控制器的综合体,是业务的精华。
入口,就是记录入口在哪里,方便区分业务。
如果我们有了这样一张大图,同一个实体被多个业务使用到,我们可以轻松得通过实体反向抓取出对应的业务,然后通过对业务沉淀的分析,获取相应的功能影响点。
这张图,我们需要一个好的载体,这里选择MM图。下面我做了一个简单的示例:
其中用了几个标签:t 功能点标签;a 业务沉淀标签;e 实体标签;l 入口标签。
标签的好处就是在编写完成之后,可以方便得进行数据提取,进行业务分析。
MM图化有什么好处呢?
1、大容量
可以把一个系统,甚至一条业务线的业务整理到一个MM图里面。
2、树状结构,方便业务梳理
3、规范化编写
规范化编写,可以方便利用工具进行提取,也方便人工阅读和挖掘。
业务沉淀图形化,规范化,对后续的回归和业务变更会带来很多好处,也会对回归点的判断上,做出更加科学的判断。
精准回归,核心在业务层面,是对业务的充分理解和剖析,是对业务的有效管理和挖掘,但是我们可以在技术层面上为这一系列管理更加高效而实用,大家可以继续关注后续的博客哦。