为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

如何提高产品开发品质PPT课件

2021-11-05 61页 ppt 292KB 12阅读

用户头像 机构认证

熊猫图文

公司专注课件、范文、教案设计制作等。用户至上,受到广大客户的一致好评,公司秉着用户至上的原则服务好每一位客户

举报
如何提高产品开发品质PPT课件如何提高产品开发品质讲解内容目前开发过程存在的问题1产品开发品质保障流程2代码重构3测试驱动4日构建5一、目前开发过程存在的问题没有完善的品质保障流程质量低下的代码不重视测试产品开发流程现状开发人员编写代码调试,肉眼观察有问题没问题(自认为)可交付的代码编译修正编译错误登记到JIRA上客户提出需求或现场发现bug产品品质管理严重缺失该流程的最终目标和工作重心都是完成产品功能开发,品质管理严重缺失。产品的开发质量完全靠开发人员的个人责任心以及工作经验来保障,缺乏一个稳定可靠的质量保障流程。这种流程开发出来的产品往往是质量不可靠,...
如何提高产品开发品质PPT课件
如何提高产品开发品质讲解内容目前开发过程存在的问题1产品开发品质保障流程2代码重构3测试驱动4日构建5一、目前开发过程存在的问题没有完善的品质保障流程质量低下的代码不重视测试产品开发流程现状开发人员编写代码调试,肉眼观察有问题没问题(自认为)可交付的代码编译修正编译错误登记到JIRA上客户提出需求或现场发现bug产品品质管理严重缺失该流程的最终目标和工作重心都是完成产品功能开发,品质管理严重缺失。产品的开发质量完全靠开发人员的个人心以及工作来保障,缺乏一个稳定可靠的质量保障流程。这种流程开发出来的产品往往是质量不可靠,需要经常返工的劣质产品。质量低下的代码是导致产品品质不好的根本原因质量低下的代码体现在以下几个方面:重复的代码过长的函数过大类过长的参数列表过度复杂的逻辑判断数据泥团没有专职测试人员来进行功能性测试工作在目前的开发流程中,开发出来的代码只经过开发人员自己简单的测试,没有专职的测试人员来进行详细的功能性测试。这样导致的结果往往是提交到现场的代码会带有不少BUG,一定要经过多次返工才能达到较高的品质。而且这样做的另一个后果是把客户当作测试人员,会给客户留下产品品质不稳定这样一种非常不好的客户体验。开发人员在开发过程中不重视单元测试单元测试是提高产品品质非常重要的一个方法,而我们的开发人员往往会忽视这一点。如果没有单元测试,仅仅依靠测试人员的功能性测试,那么这样的测试工作量会非常大,每次修改一个功能,可能会影响到的其他功能都要一一测试,不仅测试时间会非常长,而且效果也不好,很多细节不一定每次都能测到,这些都是产生BUG的隐患。同时由于我们业务需求都非常复杂多变的,没有一个完善自动化测试流程,而仅仅依靠人工测试,对产品品质的影响是不言而喻的。我们的目标!编写出逻辑清晰、结构简洁、扩展性良好、可测试性高的优秀代码。强化单元测试工作,提高单元测试覆盖率,搭建自动单元测试集,通过日构建来持续集成,对产品质量进行全面控制。通过严格的产品质量管理流程,强化质量管理工作,将所有BUG消灭在公司内部。二、产品开发品质保障流程开发质量管理本开发流程的目标是开发出质量优良的产品,流程的重心在于质量管控,通过质量保障人员对产品质量进行全面把关。对于没有编写单元测试的代码直接打回!质量保障人员负责进行功能性测试,并对提交出去的代码负责。质量保障人员另一个职责是思考如何持续改进产品质量。需求管控对每个需求进行分级评审,最大程度的降低需求变更的频度。所有需求开发前都经过内部评审,对于一些复杂需求把握更加准确,不至于在开发时候产生较大偏差。所有需求的开发工作都有经过客户签字的开发工作量评估,为商务工作开展创造有利条件。所有需求都有详细开发,片区人员可以安排相应的测试计划。全过程管控所有缺陷和经过评审的需求都必须在JIRA上登记,否则不予开发。开发计划通过JIRA进行精确体现。片区人员可以通过JIRA实时跟踪产品开发进度。方便后续各类工作量的统计。三、利用代码重构来提高代码质量重构(Refactoring):是对软件内部结构的一种调整,目的是在不改变外部行为的前提下,提高其可理解性,降低其修改成本为什么重构(1)改进软件的。程序员对代码所做的为了满足短期利益代码改动,或再没有完全清楚增个架构下的改动,都很容易是代码失去它的清晰结构,偏离需求或设计。而这些改动的积累很容易使代码偏离它原先设计的初衷而变得不可立即和无法维护。重构则帮助重新组织代码,重新清晰的体现结构和进一步改进设计。为什么重构(2)提高代码质量,更易被理解容易理解的代码可以很容易的维护和做进一步的开发。即使对写这些代码的程序员本身,容易理解代码也可以帮助容易地做修改。程序代码也是文档。而代码首先是写给人看的,让后才是给计算机看的。重构帮助尽早的发现错(Bugs)重构是一个codereview和反馈的过程。在另一个时段重新审视自己或别人代码,可以更容易的发现问题和加深对代码的理解。重构是一个良好的软件开发习惯。为什么重构(3)重构可以提高开发速度重构对设计和代码的改进,都可以有效的提高开发速度。好的设计和代码质量实体提高开发速度的关键。在一个有缺陷的设计和混乱代码基础上的开发,即使表面上进度较快,但本质是试延后对设计缺陷的发现和对错误的修改,也就是延后了开发风险,最终要在开发的后期付出更多的时间和代价。项目的维护成本远高于开发成本.何时重构?添加或者修改功能时一并重构为了增加一个新的功能或者修改原有的功能,程序员需要首先读懂现有的代码。修补错误时一并重构为了修复一个Bug,程序员需要读懂现有的代码。CodeReview时一并重构何时不该重构?代码太混乱,设计完全错误。与其Refactor,不如重写。明天是DeadLine永远不要做Last-Minute-Change。推迟重构,但不可以忽略,即使进入产品期的代码都正确的运行。重构方法介绍:提取函数(1)Stringname=request.getParameter("Name");if(name!=null&&name.length()>0){......}Stringage=request.getParameter("Age");if(age!=null&&age.length()>0){......}Stringname=request.getParameter("Name");if(!isNullOrEmpty(name)){......}Stringage=request.getParameter("Age");if(!isNullOrEmpty(age)){......}privatebooleanisNullOrEmpty(finalStringstring){if(string!=null&&string.length()>0){returntrue;}else{returnfalse;}}重构方法介绍:提取函数(2)提取函数是我最常用的重构手法之一。当我看见一个过长的函数或者一段需要注释才能让人理解用途的代码,我就会将这段代码放进一个独立的函数中。有数个原因造成我喜欢简短而有良好命名的函数。首先,如果每个函数的粒度都很小,那么函数之间彼此复用的机会就更大;其次,这会使高层函数读起来就像一系列注释;再者,如果函数都是细粒度,那么函数的覆写(override)也会更容易些:的确,如果你习惯了看大型函数,恐怕需要一段时问才能适应达种新风格,而且只有当你能给小型函数很好地命名时,它们才能真正起作用,所以你需要在函数名称下点功夫,一个函数多长才算合适?在我看来.长度不是问题,关键在于函数名称和函数本体之间的语义距离,如果提炼动作可以强化代码的清晰度,那就去做,就是函数名称比提炼出来的代码还长也无所谓。重构方法介绍:去除临时变量(1)重构方法介绍:去除临时变量(2)我喜欢尽量除去函数内的临时变量。临时变量往往形成问题,它们会导致大量参数被传来传去,而其实完全没有这种必要。你很容易失去它们的踪迹,尤其在长长的函数之中更是如此。而且,临时变量的存在,往往会阻碍提取函数等其他重构手法的进行。重构方法介绍:重新命名函数(1)publicStringgetItemName(intitemSort,StringitemName){return""+itemSort+"、"+itemName;}publicStringformatItemName(intitemSort,StringitemName){return""+itemSort+"、"+itemName;}重构方法介绍:重新命名函数(2)我极力提倡的一种编程风格就是:将复杂的处理过程分解成小函数。但是,如果做得不好,这会使你费尽周折却弄不清楚这些小函数各白的用途、.要避免这种麻烦,关键就在于给函数起一个好名称;函数的名称应该准确表达它的用途;给函数命名有一个好办法。首先考虑应该给这个函数写上一句怎样的注释,然后想办法将注释变成函数名称。人生不如意十之八九:你常常无法第一次就给函数起一个好名称,这时候你可能会想,就这样将就着吧,毕竟只是一个名称而已。当心!这是恶魔的召唤,是通向混乱之路,千万不要被它诱惑!如果你看到一个函数名称不能很好地表达它的用途,应该马上加以修改。记住,你的代码首先是为人写的,其次才是为计算器写的。而人需要良好名称的函数。想想过去曾经浪费的无数时间吧,如果给每个函数都起一个良好的名称,也许你可以节约好多时间。取一个好名称并不容易,需要经验,要想成为一个真正的编程高手,取名称的水平是至关重要的。重构方法介绍:以多态取代条件表达式(1)publicclassPlanUtil{publicvoidsetPlanState(intplanYear,intitemId,intdataType){switchdataType{case1:setPrePlanState(planYear,itemId);case2:setColPlanState(planYear,itemId);case3:setAftPlanState(planYear,itemId);default:thrownewRuntimeException("不正确的计划类型:"+dataType);}}//...更新建议计划状态publicvoidsetPrePlanState…//...更新综合计划状态publicvoidsetColPlanState..//...更新开工计划状态publicvoidsetAftPlanState..publicclassPlanUtil{publicstaticPlanUtilcreate(intdataType){switch(dataType){case1:returnnewPrePlanUtil();case2:returnnewColPlanUtil();case3:returnnewAftPlanUtil();default:thrownewRuntimeException("不正确的计划类型:"+dataType);}publicabstractvoidsetPlanState(intplanYear,intitemId,intdataType);publicabstractvoidsavePlan(intplanYear,intitemId,intdataType);}重构方法介绍:以多态取代条件表达式(2)//保存计划数据publicvoidsavePlan(intplanYear,intitemId,intdataType){switchdataType{case1:savePrePlan(planYear,itemId);case2:saveColPlan(planYear,itemId);case3:saveAftPlan(planYear,itemId);default:thrownewRuntimeException("不正确的计划类型:"+dataType);}}//...保存建议计划数据publicvoidsavePrePlan…//...保存综合计划数据publicvoidsaveColPlan…//...保存开工计划数据publicvoidsaveAftPlan…publicclassPrePlanUtilextendsPlanUtil{publicvoidsetPlanState(intplanYear,intitemId,intdataType){….更新建议计划状态方法}publicvoidsavePlan(intplanYear,intitemId,intdataType){…保存建议计划数据方法}}publicclassColPlanUtilextendsPlanUtil{publicvoidsetPlanState(intplanYear,intitemId,intdataType){….更新综合计划状态方法}publicvoidsavePlan(intplanYear,intitemId,intdataType){…保存综合计划数据方法}重构方法介绍:以多态取代条件表达式(3)//调用更新计划状态的方法planUtil.setPlanState(year,itemId,dataType);//调用保存计划数据的方法planUtil.savePlanyear,itemId,dataType);publicclassAftPlanUtilextendsPlanUtil{publicvoidsetPlanState(intplanYear,intitemId,intdataType){….更新开工计划状态方法}publicvoidsavePlan(intplanYear,intitemId,intdataType){…保存开工计划数据方法}}//调用PlanUtilplanUtil=PlanUtil.create(dataType);//调用更新计划状态的方法planUtil.setPlanState(year,itemId,dataType);//调用保存计划数据的方法planUtil.savePlan(year,itemId,dataType);重构方法介绍:以多态取代条件表达式(4)多态最根本的好处就是:如果你需要根据对象的不同型别而采取不同的行为,多态使你不必编写明显的条件式。正因为有了多态,所以你会发现:「针对typecode(型别码)而写的switch语句,以及[针对typestring(型别名称字符串)而写的if-then-else语句]在面向对象程序中很少出现。多态能够给你带来很多好处。如果同一组条件式在程序许多地点出现,那么使用多态的收益是最大的。使用条件式时,如果你想添加一种新型别,就必须杳找并更新所有条件式。但如果改用多态,只需建一个新的subclass并在其中提供适当的函数就行了。class用户不需要了解这个subclass,这就大大降低了系统各部分之间的耦合程度,使系统升级.更加容易。重构方法介绍:以委托取代继承(1)//继承解决publicclassBusPlanManagerServiceImpl{publicvoidsetPlanState(intplanYear,intitemId,intdataType){….更新建议计划状态方法}publicvoidsavePlan(intplanYear,intitemId,intdataType){…保存建议计划数据方法}}publicclassPrePlanServiceextendsBusPlanManagerServiceImpl..publicclassColPlanServiceextendsBusPlanManagerServiceImpl..publicclassAftPlanServiceextendsBusPlanManagerServiceImpl..//委托解决方案publicclassBusPlanManagerServiceImpl{publicvoidsetPlanState(intplanYear,intitemId,intdataType){PlanUtilplanUtil=PlanUtil.create(dataType);//调用更新计划状态的方法planUtil.setPlanState(year,itemId,dataType);}publicvoidsavePlan(intplanYear,intitemId,intdataType){PlanUtilplanUtil=PlanUtil.create(dataType);//调用更新计划状态的方法planUtil.savePlan(year,itemId,dataType);}}重构方法介绍:以委托取代继承(2)继承是一件很棒的事,但有时候它并不是你要的。常常你会遇到这样的情况:一开始你继承了一个class,随后发现superclass中的许多操作井不真正适用于subclass。这种情况下你所拥有的接口并末真正反映出class的功能。或者,你可能发现你从superclass中继承了一大堆subclas并不需要的数据,抑或者你可能发现superclass中的某些protected函数对subclass并没有什么意义。你可以选择容忍,并接受传统说法:subclass可以只使用superclas、功能的一部分。但这样做的结果是:代码传达的信息与你的意图南辕北辙,这是一种混淆,你应该将它去除。如果以委托取代继承,你可以更清楚地表明:你只需要受托类的一部分功能。接口中的哪一部分应该被使用,哪一部分应该被忽略,完全由你主导控制。这样做的成本则是需耍额外写出委托函数,但这些函数都非常简单,极少可能出错。重构方法介绍:引入参数对象(1)publicListgetYearPlanList(StringoperatorID,StringplanYear,StringiSeason,StringplanType,StringdataType)..publicListgetLastYearPlanList(StringoperatorID,StringplanYear,StringiSeason,StringplanType,StringdataType)publicvoidfillPlanData(StringoperatorID,StringplanYear,StringiSeason,StringplanType,StringdataType){PlanDataplanData=newPlanData();planData.setYeraPlanList(getYearPlanList(operatorID,planYear,iSeason,planType,dataType));planData.setLastYeraPlanList(getLastYearPlanList(operatorID,planYear,iSeason,planType,dataType));}publicclassPlanParamObj{privateStringoperatorID;privateStringplanYear;privateStringiSeason;privateStringplanType,;privateStringdataType;publicPlanParamObj(StringoperatorID,StringplanYear,StringiSeason,StringplanType,StringdataType){this.operatorID=operatorID;this.planYear=planYear;this.iSeason=iSeason;this.planType=planType;this.dataType=dataType;}}重构方法介绍:引入参数对象(2)publicListgetYearPlanList(PlanParamObjparamObj)..publicListgetLastYearPlanList(PlanParamObjparamObj)..publicvoidfillPlanData(StringoperatorID,StringplanYear,StringiSeason,StringplanType,StringdataType){PlanParamObjparamObj=newPlanParamObj(operatorID,planYear,iSeason,planType,dataType);PlanDataplanData=newPlanData();planData.setYeraPlanList(getYearPlanList(paramObj));planData.setLastYeraPlanList(getLastYearPlanList(paramObj));}重构方法介绍:引入参数对象(3)你常会看到特定的数组参数总是一起被传递。可能有好几个函数都使用这一组参数,这些函数可能隶属同个class,也可能隶属不同的classes。这样一组参数就是所谓的dataClump(数据泥团),我们可以运用一个对象包装所有这些数据,再以该对象取代它们。哪伯只是为了把这些数据组织在一起,这样做也是值得的。本项重构的价值在于缩短了参数列的长度,而你知道,过长的参数列总是难以理解的。此外,新对象所定义的访问函数还可以使代码更具一致性,这又进一步降低了代码的理解难度和修改难度。本项重构还可以带给你更多好处。当你把这些参数组织到起之后,往往很快可以发现一些「可被移至新建class」的行为。通常,原本使用那些参数的函数对那些参数会有一些共通措施,如果将这些共通行为移到新对象中,你可以减少很多重复代码重构方法介绍:函数迁移(1)publicclassRepUtilFunc{privateListinitFundList(…){….this.copyFundView(fView,planView);//汇总投资计划数据…}privatevoidcopyFundView(FundViewfView,PlanViewplanView){fView.setFund(fView.getFund()+planView.getFund());fView.setUpprefund(fView.getUpprefund()+planView.getUpprefund());fView.setDownprefund(fView.getDownprefund()+planView.getDownprefund());}}publicclassRepUtilFunc{privateListinitFundList(…){….fView.copyFundView(planView);//汇总投资计划数据…}}重构方法介绍:函数迁移(2)publicclassFundView{privatedoublefund;privateStringupprefund;privateStringdownprefund;…getset方法}publicclassFundView{privatedoublefund;privateStringupprefund;privateStringdownprefund;…getset方法publicvoidcopyFundView(PlanViewplanView){this.setFund(this.getFund()+planView.getFund());this.setUpprefund(this.getUpprefund()+planView.getUpprefund());this.setDownprefund(this.getDownprefund()+planView.getDownprefund());}}重构方法介绍:函数迁移(3)「函数迁移」是重构理论的支柱。如果一个class有太多行为,或如果一个class与另一个class有太多合作而形成高度耦合,我就会迁移函数。通过这种手段,我可以使系统中的classes更简单,这些classes最终也将更干净利落地实现系统交付的任务。常常我会浏览class的所有函数,从中寻找这样的函数,使用另一个对象的次数比使用自己所驻对象的次数还多,就会进行函数迁移。重构方法介绍:将过程化设计转换为面向对象设计有时间的话用一个实际例子进行展示。四、测试驱动开发方法简介测试驱动开发(TestDrivenDevelopment,英文缩写TDD)是极限编程的一个重要组成部分,它的基本思想就是在开发功能代码之前,先编写代码的单元测试用例。也就是说在明确要开发某个功能后,首先思考如何对这个功能进行测试,并完成测试用例的编写,然后编写相关的代码满足这些测试用例。循环进行添加其他功能,直到完成全部功能的开发。代码整洁可用(cleancodethatworks)是测试驱动开发所追求的目标。测试驱动开发优点(1)需求向来就是软件开发过程中感觉最不好明确描述、易变的东西。这里说的需求不只是指用户的需求,还包括对代码的使用需求。很多开发人员最害怕的就是后期还要修改某个类或者函数的接口进行修改或者扩展,为什么会发生这样的事情就是因为这部分代码的使用需求没有很好的描述。测试驱动开发就是通过编写测试用例,先考虑代码的使用需求(包括功能、过程、接口等),而且这个描述是无二义的,可执行验证的。通过编写这部分代码的测试用例,对其功能的分解、使用过程、接口都进行了设计。而且这种从使用角度对代码的设计通常更符合后期开发的需求。可测试的要求,对代码的内聚性的提高和复用都非常有益。因此测试驱动开发也是一种代码设计的过程。开发人员通常对编写文档非常厌烦,但要使用、理解别人的代码时通常又希望能有文档进行指导。而测试驱动开发过程中产生的测试用例代码就是对代码的最好的解释。测试驱动开发优点(2)快乐工作的基础就是对自己有信心,对自己的工作成果有信心。当前很多开发人员却经常在担心:“代码是否正确?”“辛苦编写的代码还有没有严重bug?”“修改的新代码对其他部分有没有影响?”。这种担心甚至导致某些代码应该修改却不敢修改的地步。测试驱动开发提供的测试集就可以作为你信心的来源。当然测试驱动开发最重要的功能还在于保障代码的正确性,能够迅速发现、定位bug。而迅速发现、定位bug是很多开发人员的梦想。针对关键代码的测试集,以及不断完善的测试用例,为迅速发现、定位bug提供了条件。我的一段功能非常复杂的代码使用TDD开发完成,真实环境应用中只发现几个bug,而且很快被定位解决。您在应用后,也一定会为那种自信的开发过程,功能不断增加、完善的感觉,迅速发现、定位bug的能力所感染,喜欢这个技术的。测试驱动开发基本过程明确当前要完成的功能。可以记录成一个 TODO 列表。快速完成针对此功能的测试用例编写。测试代码编译不通过。编写对应的功能代码。测试通过。对代码进行重构,并保证测试通过。循环完成所有功能的开发测试驱动开发案例(1)需求:实现Fibonacci数列Fibonacci数列简介:Fibonacci数列从第0项开始依次为0,1,1,2,3,5,8……的数列,它存在如下特点:第0,1个数为0,1。从第2个数开始,该数是前面两个数之和。测试驱动开发案例(2)先编写测试代码:importjunit.framework.TestCase;               publicclassFibonacciTestextendsTestCase{publicvoidtestFibonacci(){FibUtilfb=newFibUtil();   }   }  编写完测试代码之后在Eclipse中运行该测试类,发现Junit运行出错(显示了一条红色杠)这是在预料之中,因为我们还没有编写FibUtil类。测试驱动开发案例(3)为了使测试通过,那么下面开始编写FibUtil类publicclassFibUtil  {  }  然后再次运行测试类。这时会发现测试成功。测试驱动开发案例(4)下面增加测试用例,开始测试Fibonacci数列的实现函数fib:publicvoidtestFibonacci(){FibUtilfb=newFibUtil();assertEquals(0,fb.fib(0));   }由于出现编译错误,所以需要在FibUtil类中增加fib方法如下:publicint fib(int i) {                      return 0;            }  运行测试用例,通过!测试驱动开发案例(5)继续增加测试用例,判断1的情况:publicvoidtestFibonacci(){FibUtilfb=newFibUtil();assertEquals(0,fb.fib(0));assertEquals(1,fb.fib(1));   }运行测试用例,提示失败。于是对fib函数进行了小小的修改:publicint fib(int i) {                      if(i==0)return 0;        elsereturn1;    }  运行测试用例,通过!测试驱动开发案例(6)继续增加测试用例,判断2的情况:publicvoidtestFibonacci(){FibUtilfb=newFibUtil();assertEquals(0,fb.fib(0));assertEquals(1,fb.fib(1));assertEquals(1,fb.fib(2));   }运行测试用例,提示通过!测试驱动开发案例(7)继续增加测试用例,判断3的情况:publicvoidtestFibonacci(){FibUtilfb=newFibUtil();assertEquals(0,fb.fib(0));assertEquals(1,fb.fib(1));assertEquals(1,fb.fib(2));assertEquals(2,fb.fib(3));   }运行测试用例,提示失败!测试驱动开发案例(8)对fib函数进行修改:publicint fib(int i) {                      if(i==0)return0;        if(i<=2)return1;return2;    }  运行测试用例,通过。这里return2可以表示为return1+1,修改函数:publicint fib(int i) {                      if(i==0)return0;        if(i<=2)return1;return1+1;    } 运行测试用例,通过。测试驱动开发案例(9)继续增加测试用例,判断4的情况:publicvoidtestFibonacci(){FibUtilfb=newFibUtil();assertEquals(0,fb.fib(0));assertEquals(1,fb.fib(1));assertEquals(1,fb.fib(2));assertEquals(2,fb.fib(3));assertEquals(3,fb.fib(4));   }运行测试用例,提示失败!测试驱动开发案例(10)根据对Fibonacci数列定义的解读“从第2个数开始,该数是前面两个数之和”,因此原来fib函数中的return1+1中第一个1可以写成fib(i-1),第二个1可以写成fib(i-2),修改函数如下:publicint fib(int i) {                      if(i==0)return0;        if(i<=2)return1;returnfib(i-1)+fib(i-2);    }  运行测试用例,通过!测试驱动开发案例(11)继续增加测试其他测试用例:publicvoidtestFibonacci(){FibUtilfb=newFibUtil();assertEquals(0,fb.fib(0));assertEquals(1,fb.fib(1));assertEquals(1,fb.fib(2));assertEquals(2,fb.fib(3));assertEquals(3,fb.fib(4));assertEquals(5,fb.fib(5));assertEquals(8,fb.fib(6));assertEquals(13,fb.fib(7));   }运行测试用例,都提示成功!因此,我们得到了正确的Fibonacci数列函数,驱动源于测试.五、使用自动单元测试集实现日构建在福建大计划产品的开发过程中,我们通过配置自动单元测试集合进行了简单的日构建的实践。什么是日构建(DailyBuild)?所谓日构建,通俗来讲就是每天把所有的工作产品集成起来,并尽可能让其处于可测试状态。日构建是持续构建集成在以日计的较小发生频度下的特殊称谓。通过日构建,可以让你及时发现产品中存在的Bug,避免Bugs的累积,节约开发时间,并且提高软件的质量。5.1日构建流程更新CVS编译代码运行所有测试用例生产测试报告5.2准备单元测试用例集将所有的junit测试用例都集中到一个测试用例集(junitsuite)中,后续只需要测试这个junitsuite就能够实现对所有测试用例的全面测试。publicclassAllTestSuite{publicstaticTestsuite(){suite.addTestSuite(DbSchemaTest.class);suite.addTestSuite(SysUtilServiceTest.class);...}5.3编写ANT文件编写自动单元测试的ant文件,利用ant实现更新CVS,编译代码、运行AllTestSuite的单元测试并生成测试报告等功能。同时还需要编写build.bat,通过运行build.bat来执行ant任务。5.4在服务器上建一个专门的自动测试目录指定一台服务器作为专门的测试服务器(目前是207)。在服务器上建立一个目录存放CVS更新下来的源代码和ANT文件。5.5在测试服务器上建立运行单元测试的自动任务打开服务器的开始->所有程序->附件->计划任务功能,新建一个build.bat的自动任务,设定每天3次定时自动运行。每天到点build.bat就会运行指定的ant任务,更新最新的CVS代码,编译后进行junit测试,并把测试结果生成在指定目录下。5.6开发人员电脑上建立定时查看测试结果的自动任务在开发人员电脑上建立自动任务,定点去查看服务器上指定目录的测试结果。6、Q&A
/
本文档为【如何提高产品开发品质PPT课件】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索