测试的方方面面

来源:互联网 发布:.net域名崛起 编辑:程序博客网 时间:2024/05/21 15:50

如何提高测试效率:

      1、合理详细的测试计划

      2、尽早介入业务需求

      3、调整心态,始终保持愉悦的工作心情

      4、提高接受测试的标准,减小版本的输出次数

      5、测试负责人做好测绘死文档的评审

     6、加强与其他成员的沟通:如变更、进度、风险

     7、配合开发 赢得准中与支持

     8、自动化:测试周期长,版本发布频繁的足以引入

     9、数据化业绩

     10、提高测试人员的技能,补充理论知识


如何做性能测试:

    1、测试目标不明确

     2、测试计划不详细

     3、数据不具备代表性

     4、环境前后不一致

     5、测试描述不清晰

     6、技术储备不足


TCL 的测试基本点 :

1、功能  功能界面

                 然后按模块划分

 2、 性能《-- 用户操作概率大的 可以写脚本 进行 压力测试

 3、用户体验:UI 的友好性

                           用户操作习惯

                           支持的外设操作(鼠标、键盘、遥控器、多屏幕互动等)


测试人员必备的素质:

对自己

1.不搞清问题不撒手的决心决不从自己手中放过1个bug

2.坐的住,耐得了寂寞1杯茶,1张纸,在电脑前待一天

4.善于分析问题,善于总结分析bug,能够发现大量同类型的bug

5.不断学习的精神首先是业务要精通,然后是计算机的知识要全面,不一定要深入

6.不怕重复的精神测试本身就是重复,重复再重复,特别是做产品的,如果怕重复,还不如趁早改行

 

对别人

3.善于沟通善于与公司不同职务的人沟通,需求往往不是通过1次需求会审就能全部明白的

 

如何更好地与开发工程师沟通

 作为测试工程师,在日常工作中接触最多的当然是团队中的开发工程师,如何和开发工程师进行有效的交流是测试工程师面对的重要问题。一般来说,在一个团队中,总是有开发人员喜欢和不喜欢的测试工程师,这两者之间的工作效率和效果都有很大的差异。当然,不能武断地说测试人员不喜欢的测试工程师就一定是效率低下的测试工程师,或者说是不合格的测试工程师,但一般来说,那些容易得到开发人员认可的工程师在测试时总能够更好地发现缺陷和敦促开发人员解决缺陷。
测试工程师和开发工程师承担的是开发工作的两个不同方面,说得极端一点,一个是创建,一个是破坏,虽然两者的 最终目的都是一样的,但在达成目标的方式上却有很大的差异。因此,在为同一个目标奋斗的过程中,发生冲突也是难免的,但通过下面的一些建议,换个视角看看开发人员的生活和工作,可能很多的冲突就能化解于无形了。
Cem Kaner在《Testing Computer Software》书中有一段话: “The best tester is not the one who finds the most bugs or who embarrasses the most developers. The best tester is the one who gets the most bugs fixed.” (最好的测试人员不是发现最多BUG或是使得最多开发人员不自在的人,而是能够[说服开发人员]修正最多BUG的人),建议大家好好理解这句话。
    至于我个人,是从开发工程师转为测试工程师的,对于开发工程师的处境和想法也曾有过切身的体会,或许是这个原因,让我在和开发工程师交流的过程中还算是比较顺利,和他们相处得也还不错。在我的测试经历中,也接触过相当多的开发工程师,这里我把和开发人员交流的经验归结为“五要四不要”:
1、要耐心和细心
    细心是测试工程师的一个基本素质,测试工程师是对质量负责的人,涉及到质量问题,就不能含糊,因此一定要细心,细心对待每一个可能的BUG、细心对待每一段 被你检查的代码,细心对待每一个你撰写的BUG报告,细心对待你发出的每一封邮件。细心是一种态度,你的态度迟早会感染和你合作的开发人员,而这往往是合作愉快的基础。
至于说到耐心,在我的工作经历中,不厌其烦地向开发人员解释一个BUG,让他认识到BUG的重要性是经常的事情,其实想想也很正常,对任何人来说,被人指出自己的缺点和不足都不是让人舒服的事情,因此,一点不耐烦的情绪就可能引起对方很大的反感,给自己的工作带来不必要的麻烦。
2、要懂得尊重对方
    开发是一件需要全面和综合考虑的工作,开发工作中,由于各种原因导致程序中出现问题是很正常的现象,作为测试工程师,发现了这些问题并不值得你夸耀,也不能说明你比开发工程师聪明。一个好的测试工程师一定是懂得尊重开发工程师的人,尊重对方的技术水平,尊重对方的代码。我接触过的开发人员都是挺和善的,一般来说,对他们最大的尊重就是承认他的专业水平,承认他的代码。对他们来说,代码就像是自己的孩子一样:)因此,记得在合适的时候表达你对他的尊重,赞扬一下他代码的精妙之处。
3、要能设身处地为对方着想
    开发工程师一般都处在较大的工作压力下,他的上司直接考核他们的指标很大程度上是已完成的代码,所以在工作任务紧张的时候,对于测试工程师报上来的BUG会 拖延解决甚至是推脱,给测试工程师的感觉就是很不合作。那么在这个时候,就需要设身处地的为对方着想了,每个人都会为自己的工作在内心排定优先级,如果他认为解决你发现的BUG不是重要的事情,那么最大的可能就是你并没有向他解释清楚这个BUG的严重程度。
    发现BUG是我们的责任,敦促BUG得到解决是我们更重要的责任,因此,我们可以心平气和地和开发人员坐下来讨论一下BUG的严重程度,和他一起排定BUG的优先级别并确定解决的时间。
4、要有原则
    不要忘记,测试工程师需要对产品的质量负责,在这一点上一定要有原则。测试工程师可以和开发工程师建立良好的个人关系,但在具体的事情上,一定要按照公司的相关流程来处理。当然,在坚持原则的同时,可以采用一些委婉的表达方式,可以在允许的情况下尽量体谅开发工程师,但请记住,一个有原则的测试工程师才能真 正帮助开发工程师,才能赢得开发工程师的尊重。
5、要主动承担
    如果开发工程师要求你承担部分不属于你的责任,比如,定位你发现的BUG到代码一级,或者是帮助他编写部分文档和代码(不要不相信,真的有这样的事情),那么你会怎么做呢?在我的测试经历中,这些事情都遇到过,我的原则是在可能的情况下尽量多承担。其实都是工作上的事情,有能力的话,多做一点也无妨。当然, 肯定有人不同意我的意见,在这里我也不想争辩,个人意见而已,仅供参考:)
在我的测试经历中,我会根据自己的进度和时间安排尽可能地提供更多的关于BUG的参考意见,甚至是定位到代码一级,这种方式不是正规的方式,但对于提高自己被信任的程度是非常有益的。但在主动承担时,一定要明确是在自己确有余力的情况下才能去承担,否则,婉拒是最好的对策。

【四不要】
1、不要嘲笑
    不要嘲笑你所发现的BUG,即使是非常愚蠢的错误也绝对不要嘲笑,说不定那个错误是因为开发工程师联系加班24小时犯下的,对别人的工作始终应该尊重。如果 你觉得有必要提醒他不再犯一些经常犯的错误,可以采用这样的方式:编写一份测试过程中发现的开发人员常犯错误的文档(记住,千万不要写上谁犯了这些错误),用轻松的口气调侃一下,发送给开发人员。这种方法我采用过,开发人员都能很快接受。
2、不要在背后评论开发工程师
    永远不要在背后评论开发工程师的技术能力,这个绝对是非常忌讳的事情,一时的口舌之快或许会使你永远不再能同他良好地合作,要知道,开发工程师最在意地就是别人对他的技术能力的评价。其实这个不仅仅是作为测试工程师的准则,也应该是做人的准则。
3、不要动辄用上层来压制对方
    在出现和对方的意见分歧的时候,应该采用什么方式说服对方呢?直接向上层求助当然是一个办法,但这种办法带来的负面左右也是很明显的,首先是作为上层的处理结果可能不一定符合你的愿望(在很多公司,开发工程师的地位高于测试工程师的地位,这种地位的不平等导致上层在处理分歧时会有一定的偏向性);其次是动辄 拿出上层来压制对方只能给他人留下无用的印象。所以在出现分歧时,尽量尝试通过沟通解决吧,实在不行,再动用最后的手段。
4、和开发人员的沟通不要只有BUG
    除了在BUG记录单上,在其他的地方也让和你合作的开发工程师接触到你吧:),午餐或是集体活动的时候多和对方聊聊天,一方面可以增进彼此的感情,混个脸熟,打交道的时候也方便;另一方面,从他那里了解业务的知识和他负责模块的方方面面,对自己也是提升。我个人就很喜欢和开发工程师沟通,开发工程师其实一 般都是比较健谈的,尤其是对自己程序的精妙之处,多了解一些,多接触一些,对自己总是有益的。

    写了这么多,其实关键的就是两点:多从别人的角度去想想,所谓“换位思考”,多尊重对方就一定能得到对方的尊重与配合;其次是加强和开发工程师的沟通,让他清楚地认识到你的工作对他的价值,你发现的每一个BUG的重要性。
我一直认为,一个好的测试工程师一定是在公司里被所有人尊重的快乐分子,而不应该是一个“铁面判官”:)当然,作为我个人来说,绝对不敢说自己做的已经很好了,不过,我经常都记得提醒自己:尊重对方。

 

燕子(化名)从前是学经济贸易的,由于对测试行业的强烈兴趣,毕业后在北京新科海学校学习软件测试工程专业。工作不到一年的时间里,她已经从测试员升职到测试主管了。对于学习、工作,她积累了许多点点滴滴的经验,愿意与大家分享。

  走入测试行业:兴趣、知识

  说实话,我做测试工作的时间不是很长,学完软件测试工程师的课程后,到现在也就是一年多的时间吧,不过,我愿意自己学习和工作中积累起的这些点滴与大家分享。

  我走入测试行业完全是因为兴趣,兴趣产生学习和工作的热情,真的是一点都不假。从我选择走入这个行业,学习、工作,从测试员到测试主管,我都是快乐的,也很充实,很有成就感。

  我觉得,在决定走入测试行业后,就要在这方面多做准备和积累,首先要有坚实的测试理论基础,这些知识不仅是学习的时候要学的扎实,在以后的工作中还要继续不断的完善。其次,要有一定的行业知识。毕业后找工作时,有做手机测试的,也有做外包测试的。我做的是ERP产品。大家都知道,ERP(Enterprise ResourcePlanning)就是企业资源计划系统,是指建立在信息技术基础上,以系统化的管理思想,为企业决策层及员工提供决策运行手段的管理平台。我在学习测试专业前曾接触到ERP,所以,在毕业的找工作的时候就往这方面发展了。

  说到找工作,我觉得精心制作简历是一方面,同时还要有灵活的面试技巧。有时还要把在生活中学到的东西应用到面试中去。我记得我第一次去面试的时候比较凑巧,面试前的头天晚上我在电视里刚好看到一个和面试有关的节目,结果,第二天在我自己去面试的时候就被我用到了。当时是在问到薪金待遇时。我觉得这是很多人包括我自己在面试时都会觉得是比较头疼的问题,因为,说的多了,不行;说的少了,也不行。这时,你就要用一些技巧了。这时你可以先试探性的询问对方公司在招聘这个职位的时候是怎么规定的?等你了解了这些后,你再就自己的技术能力来衡量相应薪金的比价,另外就是看这个公司的实力,还有一点就是行业内这个职位的大致待遇情况。这样的话,在你说出你对薪金的要求的时候,如果,应聘的公司较小,但是还是存在一定发展空间而且你也想试试的情况下,你要得工资低,对方会考虑到可能是你已大致了解了公司的实力所以才开出这样的条件,而不是你自己的技术不行;如果你看到这个公司的状况还是比较好的,是家有一定实力的公司,这时,你可以适当抬高自己的身价。

  我的应聘还是比较顺利的,第一天应聘,第二天就上班了。我记得当时面试的时候大约谈了两个半小时,就一次性面试过关。另外我自己也比较引以自豪的是我是我们公司唯一一个在两个月之内转正的。
初来乍到:熟悉环境,尽快融入

  开始进入公司的时候首先要熟悉公司的环境。在一些大的公司可能会给大家熟悉环境的时间,还会安排一些相应的培训什么的。我当时进的那家公司比较小,没有什么相关的培训,当初只是我们部门经理拿来一些相关的资料,文档,让网管给配置工作环境。不过小公司有小公司的好处,他会很快让你介入到工作当中,给你分配任务。所以,你必须尽快的在一到两周之内熟悉公司各个方面的环境,尤其是人员环境。我觉得人际关系在整个公司里面也是很重要的一方面,夸张一点说甚至是比你的本职工作还要重要的。因为,掌握技术是你智商方面的问题,而与人交往就不是那么简单,因为我们的兴趣、爱好可能差别很大,性格也有内向和外向的,所以在进入社会步入工作岗位后与人交往真的是很考验一个人。如果你在公司人际关系搞得好的话,工作各方面的协调顺利,工作的进展也会很顺利。

  还有就是要尽快的熟悉公司的测试环境,操作系统、开发语言、平台,接着就是要了解公司的产品,掌握产品相关的知识。像我们公司是自己研发的经销群、财务这样的一个系统。你要了解公司产品的时候,可以向产品研发部,或设计部要些相关的说明文档,尽快的介入这个行业,熟悉自己要做的测试项目。说实话,我是学习经贸专业的,不是学计算机的,所以我当初的时候有点晕,我就直接拿着产品自己在那儿摸索,自己写出一个产品使用说明。向这样的事情,可能在大的公司会有专门的配选,在小公司可能就要自己学习产品了。不过,我觉得这样是挺锻炼人的,又发掘了你另一方面的潜能呢。

  
  尽可能多的参加研发部的会议

  员工间的技术交流。在我们公司像这样的会一周大概要有一到两次,大家相互交流工作进展情况,或者是一些相关的技术方面的交流。不一定是非常正式的,但我感觉这样的会议是非常有必要的。

  还有就是公司研发部召开的会议,你也要一定要也应该的介入、参加。我当初介入最早的是他们的研发意向,然后他的一些需求调研啊,还有其他的一些设计啊等等一些会议。像这样的会议我觉得是一定要抽出时间来参加的,因为这确实是对你的工作有很大的帮助的。因为在立项会议上,你可以了解项目的可操作性,以及项目的特点;在调研会议上,了解需求,市场需求是开发的依据,也是测试的依据。同时一定要参加需求更改会议,以便你更好的进行测试工作。在这些都做到位后,我们就开始写测试计划了。

        测试计划

  写测试计划就像我们在课堂上学到的那些,测试计划、测试用例,开始我们的测试流程。这时就是具体应用的时候。写测试计划的时候要跟研发部要详细设计文档、产品规格说明书和需求调研的说明(产品使用说明)这样的相关文档。如果在大公司的话,他的设计部会写产品使用说明或者是一些测试规约。还有就是一定要他的开发计划,因为你做每一步测试是根据开发进度来进行的,开发计划是必不可少的。

  最后根据上述的文档,从时间、内容、资源、所用工具,还有人力安排,这样一份简单的测试计划已经成形。像一般小的公司,他会对哪个人在哪天完成那项工作是很关注的,像我们原来学的那种比较完整的文档,在这样小的公司是需要变通的,因为他们也没有很多的人力物力没有很多的时间去看那样的文档。

  编写测试用例首先要根据产品的特点编写。你的产品的特点在产品没有成型之前,你肯定不是特别了解也不是特别清楚,但是你可以根据它的框架大概的给搭出来,你能想到的尽量给细化写到文档里面,然后在测试过程中不断的完善。如果在测试执行的过程中突然间发现一个比较好的测试用例,一定要及时给补充进去,你不给它补充上去是你的一大损失,因为你以后的工作中可能还会需要这样的文档,或者以后接手你工作的人,他可能会看到这个文档,这对他以后的工作也会有很大的帮助。在大的公司有专门的测试设计人员来编写这些东西,在小公司就是测试主管或者测试员编写。像我们公司从测试用例、测试计划、测试执行什么的都是我来做的。当初是因为公司比较小,我自己做,本来是给我招了一个助手,也就用了大概一两个月吧。我个人的感觉是除非你招特别熟练的,对行业,对测试技术各方面都比较熟悉的,一来就能上手工作的还行。如果不这样,招一个刚毕业的应届生,他对测试行业不是很了解,而小公司人手本身就少,你根本就没有时间给他做培训,而你还要工作,也没有那么大的精力去手把手的教人家。

  在设计测试用例的时候要考虑周到,不要重复。就我的工作来说做ERP产品就是注意各个模块的借口以及数据测试。有好多的接口,比如说销售模块是和财务模块在测试时是会发生重复的部分,这个要自己注意。行业性比较强。

接下来说执行测试。要按照测试用例来执行。你不能说做了测试用例而在工作的时候根本就不看,这样对你的工作是没有帮助的。因为你按照测试用例来执行的话基本就是按照自己的思路来做,这样你走到哪一步心里都非常的清楚。这样最大的好处就是减少重复的工作,可以提高工作效率。我想这点无论是在小公司还是大公司,还是就我们工作的本身都是很重要的。

  然后,最好是做测试日记录,目的就是明确自己测试到哪里,以免重复工作。就我自己来说,我在做测试的时候每天都会做测试日记,一个是记录我今天发现了多少个bug,工作到哪一步了?做了哪些工作。我发现这个做测试日记录是很有意思的。每天测出了多少各bug,我虽然在那个bag管理工具上录了一遍,但是我还是要把它记录下来。我当初第一天去上班的时候,第一次接触到这个执行测试的时候,我记得特别清楚,我是找出了65个bug。我觉得这说明两个问题,一个是我工作特别认真,一个是研发部有问题确实是有问题。所以,你不要觉得搞研发的都很厉害,很牛啊,你会有点怵。当初我们公司也是联想、方正、惠普的这三个主力支柱,但是我没有觉得怵,虽然他们很自负。基本上很小的错误都能提出来,他们认为那根本不是bug。但是你到了讨论会或技术交流会、评估会的时候可以提出来,因为这是你作为一个测试员最基础的必须的工作,也是你对工作认真负责的态度。

  和开发人员的沟通。这个是对测试人员很重要的。这个我在前面提到过,每个人不是独立的在做事情,工作中都是需要相互的配合,特别是测试工作,有问题,你需要及时的和研发人员沟通。如果你连沟通都做不好,那么,你的测试工作根本就没有办法进行。在这当中,你要坚持自己的原则,就是对事不对人,因为,这个产品有问题,它就是存在bug,那么,就要有人负责去修改。你不能说,对方是部门领导你就不敢坚持自己提出的问题。第二,就是要坚守其他的测试原则,这就是我们在学习理论的时候所掌握的一些知识。因为,我们学习时的课程设计就是根据项目来设置的,很多东西基本和实际工作中相吻合。

  作为测试负责人,在测试工作中我给自己订了一个基本的工作流程,现在也就当作是部门的规章制度在执行。就是录入bug以后,我会在下面做bug描述,开发人员是否要修改,为什么要修改,大概时间是多少,这样督促对方的话,会有利于工作的进度。不然,如果工作没有完成,就会出现相互推诿的现象。
查出bug后就是督促开发人员修改bug。同时也要注意bug管理工具。自己要用好bug管理工具,也要督促开发人员用好bug管理工具。因为,有很多开发人员还都是比较懒的,他当时会跟你说,都有什么bug,你到我的机器上演示给我看不就行了吗?这是一个不好的习惯,也很费时间。所以,你一定要督促他们使用bug管理工具。这是我深有体会的,而且,还在两次较大的公司会议上提出,最终是被大家所接受认同。大家都知道,一般开发的男同事较多,做测试的女孩子较多,你在提出问题的时候态度不要太强硬,在日常的工作中委婉的提醒他,大家一般都不会太为难你的。不但工作解决了,同事间的关系也很融洽。

  接着就是测试报告的编写。这些我们在就业班的时候都学过,就是测试背景、内容、测试通过率。以及产品的优点、缺陷,还有你对项目的建议。这一切都做好了就是开测试评估会了。
 

  关于自动化测试我的个人意见

  我个人认为现在是自动化成风。现在很多的公司,无论是大是小,无论这公司有没有用过这个测试工具,他都会问你会用几种测试工具,会自动化测试吗?我当时去面试的时候,也遇到这个问题,当时我首先问他的是,咱们公司做过手工以外的不管是性能啊还是功能其他测试吗?他们回答说没有。一个没有做好手工测试的产品,是坚决不能用工具代替手工的。自动化测试是不能代替手工的。自动化测试用好了可以节省时间提高效率。但是如果你用不好,反而会增加自己的工作量。如果你的需求和界面一直在增加,那么自动化也是用不起来的。我觉得适合自动化测试的公司,一个是产品对安全和性能要求严格的;一个可以有专人对教本文档进行维护的。像那些手工测试不过关,需求经常变动,人员少,产品的GUI 经产改动的公司都不太适合用自动化测试。

  一不小心就整理了这么多点滴出来,还真没想到自己还是很能写的嘛。估计这和我在公司除了做测试工作,还做些其他工作有关。我说过,因为我们是小公司,所以,一些产品的使用说明、产品的安装说明,包括客服培训,都是由我来写的。在测试之余,一些和测试无关的工作我也会去做,比如测试制度的编写,OA 产品管理员,售前咨询顾问 这样的工作。我想我就是这么锻炼出来的。

 

测试工具系列

 IBM Rational PurifyPlus

是一组程序运行时的分析软件。她包括了程序性能瓶颈分析软件Quantify, 程序覆盖面分析软件PureCoverage,和程序运行错误分析软件Purify。

cppunit

junit

QTP

C++Test

vunit

pclint

 

代码检视

1、与详细设计的一致性
 只要将检视的代码对照详细设计进行比较就很容易检查出代码是否和详细设计一致,采用逐行逐字阅读进行比较的方法进行。
2、头文件检查
头文件检查主要关注以下方面:
(1) 是否包含有多余的其他头文件
(2) 头文件是否内聚,即是否多个模块共用一个头文件
(3) 头文件内的内容是否清晰,是否分类排放好并给出了足够的注释
(4) 是否使用了象 #ifdef __LIST_H__ 之类的宏定义保证头文件不被重复引用
3、宏定义检查
(1) 宏定义中有参数和表达式时,参数和表达式是否都用括号括起来了。例如:
#define ADD(a, b) (a + b)  //正确的应该是 ((a) + (b))
这个定义中就没有将参数a和b括起来,如果使用时a和b是表达式的话,就会因为运算符顺序问题而出问题。
(2) 续行符\是否使用正确
4、常量
常量方面主要检查的主要问题如下:
(1) 常量是否使用了宏来进行定义
(2) 程序中是否存在魔鬼数字
(3) 16进制数据是否在前面加上了0x
(4) 常量是否来自规格
(5) 不来自规格的常量的值是否合理
5、全局变量与共享变量需要检查的主要问题如下:
(1) 全局变量是否必须的,是否可以改成局部变量
(2) 是否有全局范围内变量和局部范围内变量重名情况
(3) 是否有多个任务访问共享变量,是否进行了有效的保护
(4) 当全局变量只限于本文件内使用时,是否定义成静态的
(5) 多个任务读写共享变量时,是否可以将读写操作封装成独立函数,而不是在每个模块里都进行加锁解锁操作
6、 静态变量和函数
静态变量和函数检视时主要问题如下:
(1) 静态变量的使用是否正确
(2) 每次使用静态变量时是否需要重新初始化
(3) 对不需要重新初始化的静态变量在多次使用后是否有溢出的问题。
(4) 文件内部使用的函数是否要定义成静态的
7、 数据结构
数据结构方面考虑的主要问题如下:
(1) 数据结构里的成员类型定义是否正确
(2) 结构体里面变量顺序安排是否合理,数据是否对齐
(3) 是否存在冗余未用的成员变量。
(4) 类里面是否有私有变量和私有函数放到了公有的定义里去了
8、初始化
初始化考虑的主要问题如下:
(1) 变量使用前是否需要初始化
(2) 类的构造函数中是否对需要初始化的成员都进行了初始化
(3) 数组的初始化是否正确
(4) 内存或数组在每次使用前是否需要初始化清零
(5) 多个变量初始化赋值时是否存在顺序问题
(6) 静态变量和全局变量的初始化是否存在初始化顺序问题
9、字符串
(1) 字符串是否以’\0’结尾
(2) 字符串是否会超长
(3) 字符串使用的空间大小是否存在差1问题
(4) 使用字符串指针时,指向的位置是否存在差1问题
(5) 字符串指针是否可以为空,为空时会有什么现象?
(6) 字符串内容为空(即第一个字符为’\0’)时会发生什么现象?
(7) 字符串中如果有转义字符“\”字符时,是否正确地写成了“\\”
(8) 在对字符串进行拷贝或连接操作时,是否对空间大小进行校验?
10、输入检查
输入校验需要检视的主要问题如下:
(1) 函数参数是否需要进行检查
(2) 从文件读取的数据是否进行校验
(3) 使用全局数据时是否需要进行校验
(4) 通信收到的数据是否需要进行校验
(5) 从消息中接受到的数据是否需要进行校验
11、边界条件
凡是牵涉边界条件的地方都需要进行边界检查,以下的一些问题供参考:
(1)循环变量上的边界是否正确
(2)变量的取值是否有边界条件限制,边界是否给出并书写正确
(3)空间边界,如内存大小,数组大小是否正确,是否存在差1和越界情况
(4)数据结构边界,如链表的头一条记录和最后一条记录等边界情况
(5)服务器连接数量最大是多少
12、内存分配和释放
内存分配方面需要检查的有以下几点:
(1) 分配的大小是否正确,是否分配了过大的内存或者分配的内存大小不足,分配的内存大小是否存在差1错误
(2) 内存分配是否经过判断或者进行异常处理
(3) 重新分配一块内存时,是否将原有内存释放
(4) 分配的内存是否需要初始化清零
(5) 是否有在大循环中不断分配内存导致可能出现系统内存不足情况
释放方面需要检查的有以下几点:
(1) 所有的分支路径上是否将分配的内存进行了释放
(2) 是否将已经释放的内存重复释放
(3) 释放的是否是空指针
(4) 释放多块内存时是否存在释放的先后顺序问题
使用realloc()时要考虑以下几点:
(1) 新增空间是否需要初始化清零
(2) 是否还有指针指向老的内存块,并在realloc()后使用指向老的内存块的指针。
13、类型转换
类型转换的检查有以下问题供参考:
(1)类型转换是否采用安全的转换机制
(2)当采用强制转换时是否会出问题
(3)signed 和unsigned转换是否存在问题
(4)是否将小空间的类型转换成了大空间的类型
(5)类型转换是否会造成截断、溢出或越界
14、数组使用
数组的使用也是很容易出错的一种,不幸的是现在还没有足够好的方法能保证数组越界一类的问题得到完美的解决,所以通过对数组的检视来保证质量就很重要了,下面给出检视数组的一些建议:
(1)类型是否正确
(2)多维数组是否数据存放顺序正确
(3)数组使用时是否会越界,空间大小是否存在差1错误
(4)作用域是否正确
(5)数组大小是否太大导致浪费
15、指针使用
指针在C/C++中是使用最广泛的一种语法,指针使得语言的功能强大起来,但也给程序质量带来了很大麻烦,使用指针时是极易出错的,可以说C/C++代码中的缺陷大部分都与指针有关,下面给出检视指针的一些问题参考:
(1)指针是否初始化
(2)指针类型定义是否正确
(3)使用前是否申请了内存
(4)引用是否正确,是否引用了释放掉的空间
(5)指向的空间是否正确
(6)是否存在使用野指针现象
(7)释放后再使用时是否需要重新初始化
(8)是否使用了空指针,函数指针是否为空就被调用
(9)指针是否需要校验
(10)指针进行类型转换时是否会引起问题
(11) 指针地址运算是否有误,在地址相加时是否考虑了相加的数字要乘以指针类型所占空间的大小。比如int *p; p+1相比p的大小不是大于1,而是大于一个整数所占空间的字节数。
16、函数
函数方面的一些检视建议如下:
(1)函数调用的参数传递是否正确,
(2)是否有形参和实参使用错误的问题,
(3)函数的返回值和输出是否需要校验,
(4)调用的函数是否对全局数据产生影响
(5)函数功能是否单一,是否在函数里处理了多个不同的功能
(6)函数参数是否需要定义为const
(7)函数是否过长(一般以不超过200行为宜)
17、系统和标准库调用
调用系统函数和库函数时,以下一些检视建议供参考:
(1)系统调用是否正确,调用参数设置是否正确
(2)是否按照标准文档中的要求和注意事项进行了调用
(3)对于存在BUG的系统函数是否采取了规避措施进行调用
(4)对调用系统函数是否需要在调用前进行了输入校验
(5)调用后是否需要对输出进行校验
18、判断循环条件
在程序中的判断和循环条件中,也存在着一些有时通过测试难以发现的问题,主要的检视建议如下:
(1)逻辑运算符是否正确,如| 和||,&和&&运算符是否搞混淆掉或键盘失误写错,
(2)逻辑等号==是否误写成等号=
(3)运算符顺序是否正确,运算符| 、&,||、&&,=、== 的运算顺序需要特别注意
(4)循环判断中的表达式是否正确地使用了括号将运算顺序区分开,并增加可读性
(5)表达式运算是否存在逻辑上的错误
(6)对浮点数是否误用了精确相等进行比较
(7)循环变量是否进行了初始化
(8)循环的中止条件是否在某些情况下无法到达而造成死循环
(9)循环的边界上是否会造成问题
(10)判断条件是否会恒真或恒假

19、计算
计算错误也是程序中经常遇到的一个问题,大部分计算错误可以经过测试发现,但并不是所有的计算错误都可以很容易通过测试来发现,以下的一些问题供检视时参考:
(1)计算表达式或公式是否书写正确,需要逐字符地进行确认没有输入错误
(2)表达式中运算符顺序是否书写正确,同优先级运算符运算时是否存在自左至右结合或自右至左结合运算结果不同的问题
(3)是否需要使用括号来保证运算顺序的正确性和增加程序的可读性
(4)是否存在计算溢出情况,如两个整数相乘结果超出整数最大范围等情况
(5)截断误差和舍入误差是否会引起问题,误差是否会累积下去导致误差越来越大?
(6)是否存在除零问题(即零做分母的问题),或者两个整数相除结果得到零然后再和其他整数相乘。
(7)是否存在某个变量会累积增加导致长时间运行后的溢出
20、资源释放
资源释放方面的一些检视建议如下:
(1)所有的资源是否都进行了释放
(2)要检查是否存在某条路径遗漏了释放
(3)打开文件是否关闭了,信号量是否释放,句柄是否关闭,锁资源是否释放,是否存在死锁问题
(4)全局的资源是否存在随时间累积增加不减少的问题?
(5)其他各种资源如网络socket等是否在各条对应路径上进行了关闭
(6) 类的析构函数中是否对类中需要释放的成员进行了释放
21、效率
从空间和时间效率方面一些检视建议如下:
(1)多个if判断是否可以改为switch或if…else if结构,例如if(res<0){…}
if(res>1){…} if(res>=0){…}改为if…else if…else就可以减少判断次数
(2)多个相同处理的case语句是否归到一起
(3)在多重循环中,最忙的循环是否在最内层
(4)循环体内的判断语句是否可以移到循环体外

看完上面的检视要点后,找一些代码来试验一下看能否通过上面的内容来提高自己的检视能力。下面就举几个代码检视的实例:
1、求和函数的检视实例
/**   整数求和函数,计算0到指定正整数(包括指定整数)间所有整数的和
       @param int num - 指定的整数求和的上界     
       @return int - 求得的整数之和  
*/
int Sum( int num )
{
       int i, sum;
       for ( i =0; i < num; i++ )
       {
              sum += i;
       }
       return sum;
}
下面按照检视要点来对这个函数进行检视:
先分析以上代码中的变量初始化问题,显然sum变量没有被初始化
进行一致性检查发现函数是求正整数之和,函数参数应该定义成unsigned int类型才更确切
根据计算方面的检视要点进行分析,发现当num较大时可能会造成整数上限溢出,要解决这个溢出问题,有三种方法,一是将参数的类型改成unsigned short或者将返回值改成64位整数类型,或者在程序中对输入参数进行上限校验,校验失败返回-1表示失败。
进行循环边界检查发现i<num应该为i<=num
因此检视出来的主要问题如下:
1)        变量sum没有初始化
2)        函数参数类型定义不准确
3)        当参数num的值大到一定程度时会造成整数上限溢出
4)        循环中的条件i<num写错,应为i<=num
2 、日志文件函数的检视实例
/**   写日志函数,实现将日志信息写入日志文件中的功能
       @param char *pszLogFile - 日志文件名  
       @param char *pszLogMsg - 要写入的日志消息字符串
       @return int - 失败返回-1, 成功返回0    
*/
int WriteLog (char *pszLogFile, char *pszLogMsg)
{
       FILE       *fp;
       fp = fopen(pszLogFile, "w");      
       fseek(fp, 0, SEEK_END);
       if ( fwrite(pszLogMsg, sizeof(char), strlen(pszLogMsg), fp)
                     != strlen(pszLogMsg) )
       {
              return -1;
       }
       fclose(fp);
       return 0;
}

下面按照检视要点来对这个函数进行检视:
从输入校验方面的检视要点来看的话,输入参数没有校验。即没有判断输入的文件名是否合法或是否为空。输入的日志消息字符串是否为空也没有判断。
从函数方面的检视要点可以发现打开文件函数的返回值没有进行校验,即没有判断打开文件是否成功,
从资源释放方面的检视要点来看,打开的文件在return -1;这行之前没有被关闭。
再从系统调用方面的检视要点来看,调用fopen使用不正确的参数,实际上第二个参数不能使用”w”,”w”参数会将文件内容清空掉,以前写的信息都会丢失,应该改成“a+b”。改掉这个参数后,fseek()那个调用就可以不要删除掉了。
除了上面的检视要点外,还需要使用元素分析法来进行检查,从日志文件这个元素进行分析,两条日志信息间应该有分隔符分开的,因此需要对pszLogMsg判断是否有分隔符,如果没有的话,程序中应该给它补上分隔符。
所以总共可以得到上面写日志函数的几个主要问题如下:
1)        输入参数pszLogFile, pszLogMsg没有进行校验
2)        打开文件后没有判断是否打开成功
3)        fopen()第2个参数使用不正确,应该使用“a+b”作为参数
4)        return -1;前没有将打开的文件关闭掉
5)        日志文件中的两条日志信息间的分隔符没有考虑进行处理
3、字符串处理函数的检视实例
/**   删除字符串最右边的特殊字符(包括空格、回车符、换行符、TAB字符),直到遇到非特殊字符为止。 源字符串不能修改,删除特殊字符后的字符串放到返回值中。
       @param char *str - 源字符串指针   
       @return char * - 返回删除特殊字符后的字符串,
                        失败或者删除特殊字符后字符串内容为空时返回NULL; 
*/
char * StrTrimRight(char *str)
{
       int len;
       char *psz;
       if ( str == NULL )
       {
              return NULL;
       }
       len = strlen(str);
       psz = str + len;      
       while ( *psz == '\r' || *psz == '\n'|| *psz == ' ' || *psz == '\t' )
       {
              psz--;
              len--;
       }
       psz = (char *)malloc(len + 1);
       strncpy(psz, str, len);
       return psz;
先从校验的检视要点看,对输入的函数参数进行了校验
从函数方面的检视要点来看,调用的malloc函数没有对返回值进行校验
函数参数是否需要定义为const,按照注释里的说明,原字符串不能修改应将字符串输入参数定义为常量
从循环条件方面看,循环是否会中止呢?只有碰到不等于特殊字符中的字符才会结束,如果一个字符串中只有特殊字符的情况下,循环会执行到psz越过字符串str的头部,导致内存越界,将导致异常出现,或者异常没有出现而此时如果越界后的字符凑巧为特殊字符的话,将导致len变成负数,后果都将不堪设想,因此需要将循环的中止条件再加上对len是否小于等于0的判断
从计算方面看,psz = str + len 使得psz 指向了str字符串尾部的’\0’字符,会导致后面的循环内的代码不被执行,将没有把特殊字符删除掉就复制到返回值去了。
由于是字符串处理函数,因此下面着重从字符串的检视要点进行检查,首先考虑字符串内容为空的情况,在这种情况下,按照注释里的说明,应该返回NULL的,所以漏掉了对输入参数内容为空的校验,需要增加一句 if ( *str == ‘\0’ ) return NULL;
从系统和库调用方面来看,strncpy函数不会在复制后的字符串尾部添加’\0’,因此最后还需要在复制完后添加上’\0’
从边界进行分析,变量len具有边界条件,它的下界是0,当len为0时,显然删除特殊字符后的字符串内容为空,此时需要返回NULL,不需要分配内存和调用strncpy操作,因此遗漏了删除特殊字符后字符串为空的情况的处理。
因此总共可以发现这个函数有以下一些主要问题:
1)  psz = str + len; 导致psz指向字符尾部的’\0’字符,引起程序后面出错
2)  while 循环条件有问题,某些情况下会导致异常,应该加上 len 是否大于0的判断
3)  应加上对输入字符串内容是否为空(首字符是否为’\0’)的校验
4)  malloc()函数分配内存后没有判断是否成功
5)  strncpy没有给复制后的字符串尾部添加’\0’字符,需要另行添加
循环完后没有判断删除后字符串的内容是否为空,应通过len是否大于0来进行判断
字符串输入参数应定义为常量
1.看见了if,就想else
2.看见malloc,就去找free
3.函数调用要小心,需要看看返回值
4.看到for循环,就找边界值
5.看见return要注意,要去前面找资源
6.看见数组要提神,问题往往在下标
7.不要小看字符串,长度是个大问题
8.看到函数不要急,看看初始化,各种路径要小心
9.赋值函数最危险,指针没资源

 

0 0
原创粉丝点击