经验交流:测试驱动开发感悟★
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
经验交流:测试驱动开发感悟★
第一篇:经验交流:测试驱动开发感悟
最近听到了很多关于软件质量的话题,自己前段时间也参加个PMP(项目管理)的培训,所以一时对于质量控制特别感兴趣,在这里想和大家共同讨论下!
软件质量,是所有人都很关心的东西。
我们在开发过程中为了保证质量,从中引进了软件测试。
它在整个的过程中起到的作用不言而预,但是它也存在一些问题:
1、在软件测试中要保证软件的高质量就必须增加项目的成本,从而需要增加测试人员,延长项目时间,购买或学习测试工具的成本。
2、因为这种测试是依赖与开发完后才提交给测试人员的,所以如果测试中出现BUG,就会出现BUG打回,再次提交测试...,这中间还需要测试人员和开发人员的沟通,这也是一个成本的增加
3、这种方式会使得开发人员对测试人员产生依赖,从而降低代码的质量,减少自己的测试.....我们为什么不能把测试前移呢!让开发人员自己对软件的业务就做个完整的测试,然后把代码提交给测试人员,这样就可以减少BUG的数量,同时可以让测试人员不只关注与功能性的问题,可以关注更深层次的问题(性能,用户体验...),这种方式就是做单元测试。
其实这个东西很早就有了,每个人都知道它,只是如何做的问题,我相信其实很多公司都做到,有些做的很好,但也有些是失败的!我自己经历过失败,体会过它的麻烦和迷惑,也经历了成功,体会到了它的好处。
所以把这些写出来分享下!
软件就是由代码组成的,所以软件的质量就是代码的质量,我们出了BUG就从代码开始入手找问题,然后修改代码。
但是当你的软件从小慢慢变大时候,代码越来越多,彼此之间的关联越来越紧密,这样就带来了一个问题“修改一部分代码后会影响多少?”,如果你拿这个问题去问那些项目中没有单元测试的开发人员,他们给出的答案都是通过“拍脑袋”来的,这样绝对会给你的项目带来风险。
为了降低风险,项目开始要求开发人员做单元测试,但是做过后得出,这真
的可以降低成本吗!花了太多的时间去写测试代码(甚至比开发时间还要多),对于质量的保证也没有达到预期的效果...,项目做完后,发现做单元测试的和没有做成本多很多,所以接着就放弃了!.....这种现象我想是我们都想做它但又不做它的最大因素。
其实我想大家对它的理解有点误差,我认为他最大的用处不是用来测试代码,而是测试设计!代码从是设计来的,保证了设计的正确性不也保证了代码嘛!软件中的未知风险太多了,其实很多出于设计,对于设计很难去评价好,还是坏,很难找到一个衡量的标准,但是我想TDD,给了我们一个标准,虽然不能去完整的评价,但至少可以是一部分,可以降低它的风险。
这里慢慢开始引入了本文的主题,测试驱动开发(TDD)。
我的理解上,单元测试如果不是TDD这种模式,就没有太多的必要去做,因为那样投入做单元测试的成本和收益之间找不到平衡点。
“测试驱动开发”的经历
测试驱动开发简称TTD,全名Test-Driven Developmentd。
它是敏捷开发的一个重要组成部分,来源与“极限编程”。
我接触它是从一年前的那天(具体时间不记得了~ 呵呵!)开始的.....接触记得两年前的某天,我正在公司偷偷地看电视剧“奋斗”,这时看到邮箱中的一封邮件: 部门下了一个确定“要求每个项目开发过程中加入单元测试”。
当我听到“单元测试”的时候,满头的问号,“它是什么东西,做什么用的....?”(当时还很菜,居然还听过单元测试...!),接着不停的开始找资料,足足花了一个星期才把它了解,然后做了一个简单的DEMO,写些简单的测试代码,把它放到Nunit上,看着都是通过的提示,兴奋呀!
这时就和项目中的一个“大牛”开始讨论它了,忽然“大牛”的口中蹦出了三个英文单词“TDD”,然后和我讲了一大堆,我根本就不知道他说什么(水平有限,当时理解不了),只是重复着三个字“明白了”。
接着他说,项目的这个版本你设计的时候,加入单元测试吧,如果可以的话,也试下TDD.....我是一个喜欢挑战的人,所以一开始就玩先写测试代码,结果呢!大家都明白,菜鸟嘛!一定失败咯,
其中的原因是:根本就没有“测试驱动开发”的思想,完全不知道如何开始先写测试代码,而且还没有理解MOCK!下面只有乖乖地和别人一样,等代码写完后再写测试代码。
就在代码写完,开始写测试代码的时候,我们项目组内的人都遇到了相同的问题:
1、系统中程序之间的偶合度太强,业务层,UI,数据层依赖了太多的环境因素,很难分开,所以写测试代码前,还需要去虚拟很多东西
2、花了一天把需要虚拟的东西都做完后,又出现了一个最重要的问题,测试代码太多了,实在写不下去了,一个测试方法(业务比较复杂的)花了半天的时间,这比我写代码时间还多
之后为了完成任务只写了几个简单的测试代码提交。
不久,其他项目组也遇到了这些问题,所以公司最后停止了这个过程。
我当时听到这个消息的时候,心里有点不好受,因为从那时起我就觉得这是很好的过程,出现的这些问题只因为我们的实力还不够,同时它对于开发人员来说也是一个挑战,一个提高。
可现在停止了,意味着失去了一个很好的锻炼平台。
出于不甘心失败,自己暗暗下决心,一定要提高自己的实力,一定要在设计前就写好测试代码!.....迷茫
在之后的一两个月的时间内是很迷茫的,虽然自己下了决心,却不知道从何开始,盲目地在网上找资料,发现有意义的资料太少,身边虽然有牛人在,但是这个东西是只能意会不能言传的。
去公司的图书馆找了些关于敏捷开发和极限编程的书,看完后体会还真是挺深的,加强了对“测试驱动开发”的认识,可自己还是不会.......!
那时的自己连设计模式都不会几个,好象连接口interface都不太会用,至于抽象还是刚刚理解的阶段,对于单元测试,还没有学会MOCK。
不过我的运气还真好,就在这个时候,有个朋友找到我说,有个小项目需要帮忙,问我是否参与呢,由我来负责架构和设计(现在想想,他还真有魄力,敢让我这个菜鸟来架构),我那时也很闲,而且正想找
个实验的项目呢!于是就答应下来了。
项目其实很简单,外贸公司用于发布产品和网上销售的网站。
用户数也没有要求,小公司要求可以用就可以了。
花了一段时间接触客户,做出了简单的项目计划,基本完成了用户需求,然后就开始做基本架构了,架构还是用经典的三层模式,数据库选的是MYSQL,没有用O/R Mapping....这些第三方的框架。
因为出于实践和学习,所以希望都通过自己手写来完成。
接下来开始做具体的设计了,花了几天的时间做完了大概的设计,画完了UML图.....,就剩下代码了!
“单元测试”,任然加入了我的开发过程,在这里我总结了一开始失败的原因,加上自己这段时间的学习,知道了要减少程序之间的偶合度,减少依赖。
可是真到写的时候,又迷茫了.....成熟
经过了一段时间的迷茫和设计的不断返工,计划的不断延误。
终于开始认清了真相,也真的理解了一句话,“质量是设计出来!”,同时明白了“抽象”的必要性,并且还是会使用MOCK了!
哎~,这些收获付出了很多的代价呀!项目的合伙人因为计划不断厌恶,想杀我心都有,每次去用户那里,用户总语气很怪强调“专家”这两个字(我朋友为了接项目,忽悠客户说我是很牛的专家...),我顶着这些压力,还在不停的重构,不停的写着测试代码。
不过,单元测试的过程并没有很大的改善,主要还是一个复杂的方法里面的业务规则很多,而且代码也多,方法内部依赖的环境因素和依赖对象也很多,当出现这种情况的时候,去写它的测试代码简直是一个十分痛苦的事情,而且这种应付不了以后的变化。
这种代码代码本来就多,当需要变化的时候,看代码就需要N久时间,更别说还有心情在去理会测试代码了!我对于这种问题并没有太多的解决办法,只是用时间去填补。
其实经过了这些,我知道自己欠缺什么?!那就是设计,由于设计的不够抽象,对于复杂事物分解的不够简单...,接着跑出去书城,拿着刚发的工资买了N多的关于设计的书籍。
把它们抱回家,当看着这些书的时候,看着正在进行的项目,和那一大堆比代码还复杂的测试代码,觉得值了!
飞跃
“单一职责”
“依赖倒置”
“开放封闭”
“Liskov替换原则”
“迪米特法则”
这些设计的基本原则,大家是否是已经看过了太多次了,但是这些你真的每个都理解了吗?23种设计模式,每种模式都会了吗!会使用吗!你做设计的时候,是否会去思考我应该用何种模式呢?!......这是我花了N久时间才慢慢理解和学会的东西。
时间大概过了半年多,我的小项目已经开始运行,看着它正常的运行和VS2005上测试项目中的一排“测试通过”的标志,无限的喜悦。
我学会了设计,理解了测试驱动开发,并且写测试代码不在烦恼,而是如此的简单,“设计完后就马上去构思测试代码,如果觉得测试代码复杂,又回来修改设计,直到交互都简单为止”,这成为我现在的一种习惯。
学会这些的同时我又拿到了项目Money,真是爽呀!
经历过这些,我的领会是:在做单元测试之前,你必须要学会设计。
设计原则和设计模式是你需要要去掌握和理解的,要让自己在做设计的时候,不会去想“我是否应该用哪种模式”,而已灵活运用,根据具体的情况去做,因为你要做到“无剑胜有胜”!
只有简单的东西才容易写,容易测试。
代码变的简单,单元测试同样会变的简单。
所以其中最关键的就是你如何将复杂的东西简化。
虽然谁都知道这个道理,但是要真正做到还是很不容易的。
需要理解,需要实践,需要时间去积累...这是我做单元测试,并学会测试驱动开发的一个过程,现在虽然自己还是一只“小鸟”,但是我可以让代码看上去简单,有了一大堆测试代码的保证,降低了变更的风险。
工作还在继续,还向着新的目标前进......
第二篇:开发和测试的六道轮回
开发和测试的六道轮回
2012年是移动互联网年,我学习了O-C的开发,开发了较多的功能和内容,对于开发的过程和开发后的质量,以及开发自测有了新的认识。
此前一直站在测试的角度去思考开发如何做测试,如何自测,如何共同保证测试。
当时觉得不是很有难度,应该可以这样做,应该可以做到什么程度。
现在对这个问题有了一些新的看法,也顺便讨论我从从事测试行业以来,如何处理开发能力和测试能力的平衡,内心的所思所想,作为个人的体会和感受,希望与各位讨论。
若隐若现
记得毕业后,我和隔壁班同学一起分到了HW公司的某产品部门,我在测试部门,他在开发部门。
刚开始的半年,我学习了业务、数据库、操作系统、测试工具、测试流程和管理。
半年后,我继续学习测试相关的资料,感到了一些迷茫,在HW是封闭式的环境,接触不到外面的世界,我觉得测试学得差不多了,看到同学每天写代码到很晚才下班,貌似学到了很多东西,成就感明显大于我。
于是,我开始偷偷地拿出来自己带的C++教科书,慢慢学习C++代码,当时我没有自己的电脑,使用公司的电脑学习C++,为的是不让自己忘记C/C++的语法和基本代码,没有完整的学习规划,再加上HW公司的确工作忙,只能慢慢地学习,效果非常不好,基本上自学的代码量不超过百行。
开发能力和刚毕业时有了较大的下降,但是也没有太多的危机意识,觉得自己学到了很多测试方面和OS和DB的知识,在外面能有用武之地。
顺藤摸瓜
在HW工作一年后,我去了A公司。
相对来说,A公司的工作压力要小很多,也接触到了外面的世界,除了学习更多测试相关的知识以外,仍然没有放弃学习和编写代码。
由于接触的产品是C#编写的,需要重新学习C#的语法和基础代码。
由于时间较充裕,加上和开发人员关系和谐,自己可以动手编写测试工具和相关的工具。
清楚的记得自己为了锻炼编写C#的代码,写一个计算器程序,代码量上千行,对于自己开发的计算器程序有种莫名其妙的成就感,体会到了一些编写代码的乐趣;后来乘胜追击编写了一个简单的写代码的Edit工具,有点
类似于UltraEdit。
也就是那个时候,发现自己编写的代码越多,隐藏的bug越多;发现修复了一个bug外,还产生了好几个bug。
也许是自己的编写代码能力有限,清楚地理解了编程不是那么简单的事情。
做出来的工具得到了开发以及开发主管的认可,感觉自己有编程方面的潜力,感觉不错,有些许的成就感,也曾想转岗做开发吧,但是一直没有下定决心,原因不外乎人在江湖,身不由己啊。
我的开发能力得到了展现,希望尽量应用到测试工作上,当时我在SE Team,专门为产品上线后提供后续服务,对于技术支持人员报告的bug,我负责重现和验证,时间上较宽松。
我的开发能力得到提升后,在重现bug后,我都要调试代码,查看问题出现在哪里,有时候找到出现错误的原因,并给出简单的修改建议,开发人员在修复bug时,大致了解我对于该bug修复的注释。
随着时间和实践的增多,后来我不仅仅调试代码找到引起bug的根本原因,还会给出详细的修改缺陷的解决办法或变通方法,给出详细的原代码和新代码,同样也会验证结果。
得到了开发的极大认可,成就感大大的提高,但是仍感觉和开发人员相比比较,我调试代码的能力较弱,投入调试的时间有限。
从结果上来看,自己不仅仅保持了一定的代码编程能力,还可以将开发和测试的关系以及应用过程了解得更深入,相应地持续提高编码能力。
当时也编写了基本的自动化测试代码,由于测试框架封装的较好,测试代码基本上没有太多含金量,这些工作不仅仅是了解这个代码规范,还详细了解了测试框架的架构以及基本实现方式,为后续接触不同的测试框架打下了基础。
东山再起
来到淘宝,我对测试能力保持充分信心。
当时淘宝还是页面自动化的初始阶段,我结合以前对测试框架的架构的理解进行内部交流,为淘宝的测试框架的改进带来了一些新的架构思路,比如Page Model和DB Model。
此事的编程语言变成了Ruby,只好尽快学习Ruby编写自动化测试代码,接着为了编写接口测试代码,马上学习Java,2010上半年我的开发能力还停留在自动化测试代码阶段。
后来
部门实施技术产品化的策略,将测试技术转换到产品中来,必须学会开发产品,所以当时参与了Web应用开发,开发公共用例中心(CTC),从而了解到了更多开发方面的知识。
中间件、Spring、iBatis等等,在Java开发方面有了更多的进步,但个人认为还是皮毛阶段。
2011部门开始提倡测试具有定位bug的能力,在几个项目测试过程中,在时间充裕的情况下也会调试代码,从而找到引起bug的根本原因。
但这个要求在互联网的项目流程中实施起来较难,因为测试阶段本身的时间非常有限,还要花费较多时间调试代码,有些得不偿失。
开发人员和项目经理(PM)也未必真正认可,因为在测试阶段会给项目带来进度上的风险。
但是这个过程,对于测试人员提高前端开发和Java开发方面的技术知识有较大的帮助。
我的个人体会是,测试人员不是一直处在编写代码的时间轴上,测试人员的开发能力随着时间的推移,下降很快,重新捡起来,需要花费较长时间。
当时我在编写前端代码和Web service的Java代码时,投入了很多经理,咨询了很多同事,总算搞定了。
但是3个月后(期间未做任何开发相关的工作),重新开发类似的工具或功能,还是需要花费较多的精力,感觉非常痛苦,真想转做开发岗位了。
当时有很多好的思路和想法,但是苦于自己的开发能力和时间精力有限,大部分未能实现,是个痛苦的事情,所幸自己在代码学习方面一直督促自己,也开发了一些工具和站点。
知己知彼
2012年,部门开始强调开发自测,开展各种开发测试比赛。
我对这种做法一直持保守态度,可能和个人的经历有关,也可能和被测产品有关。
对于互联网产品来说,需要做很多测试工作,完善被测产品的质量和用户体验。
刚开始我的策略较为简单,将测试设计共享和传承到开发人员,开发人员能接受多少,就可以一定程度上避免某些bug,从而在进度和提交测试质量上保持良好的平衡。
开发人员还是比较喜欢这种方式的,但是开发人员很少真正将异常测试场景自测下去。
经过几个项目的试点,发现效果较差,原因肯定有多个,大家也会猜到一些。
语言,重新学习新的开发方式,坚持了一段时间后,自己对于
iOS开发有了一些感觉。
总体上来说,iOS开发比其他的开发更有成就感,因为开发出来的APP看得见摸得着,容易看到成果。
刚开始加入产品的开发团队时,将测试设计的大部分时间用来开发产品的某个功能,感觉比较痛苦,我花了3天才开发出来的功能页面,一个刚毕业不久的开发人员只花了一天就搞定了。
我当时的痛苦只能自我感受,必须持续坚持下去。
为了尽快熟悉iOS开发技术,我多此请教开发人员。
后来开发了tBug,从使用Storyboard到丢弃它,写了更多的代码,看着自己开发的APP,成就感真的比发现bug要强烈多了。
通过在iOS上积累开发经验,这让我更多地理解了开发人员,更多亲自感受开发人员的心态和对于测试的态度,大致包括几个方面。
(1)使用快速迭代时,对于某个功能需求,开发人员编写代码时绝大部分考虑正常流程,较少考虑到异常流程,很多精力是放在如何实现功能,而不是思考用户会在多种场景下,如何使用这个功能(此任务需要测试人员投入很多时间思考)。
(2)开发人员在修复一个bug后,存在一定的思维惯性,只能验证这个bug是否修复,没有较多的时间测试相关的功能流程,而测试人员会发现该bug修复后引出的新的bug。
我针对Bug调试代码后,很快找到引起bug的原因,很快的修改了bug,较少思考修复的方案是否会带来新的bug。
在修复一个bug时,开发人员往往有多种方案去解决这个bug,但是不同的方案会带来不同的结果,有些方案会引发一些新的bug,有些不会。
所以我也经常建议测试人员不仅仅要验证bug,更要思考bug的解决方案,思考这个方案会带来什么影响,从而探索式的使用更多的测试场景去测试它。
(3)开发过程中,考虑如何去测试它,难度不小。
有人会说,使用“测试驱动开发(TDD)”方式,开发之前,先把测试用例写好。
这个方式的确很好,但是对于测试经验较多的人而言,可以这么去做,但是开发人员还是需要耗费较多时间思考如何实现,而不是如何测试它(这就是测试人员与开啊人员思维的差别)。
所以测试人员强迫自己写完代码后,多去测试它以及周围相关的功能。
真正体会持续集成的作用,虽然没有发现bug,但是对产品的质量提供了充分的信心。
(4)开发人员可以发现很多测试人员都发现不了的bug,然后“悄悄地”修复bug。
2011年我经常和开发人员沟通,开发人员说他们发现了好多个bug,已经修复了,测试人员是不会发现的。
我当时无法理解这个事情,现在我总算能明白一些了,开发人员在修复bug时或编写相关功能的代码时,会发现某些问题,然后修复掉,而测试人员完全不知道,很多时候也不会去测试这些场景。
举个例子,APP登陆分为第一次登陆和后续登陆的逻辑区分和判断(包括读写cache和客户端数据库),假设第一次登陆出现错误的结果,测试人员报告bug。
开发人员修复bug时修改了相关的代码,从而引发该业务逻辑的错误,测试人员的大部分测试都不是第一次登陆看到的结果,测试人员很难想象第一次初始化会出现问题。
假设测试人员想到这个场景,需要重新登陆、甚至需要重新安装APP、重新初始化,这些过程都是很麻烦的过程,测试人员不一定有坚定的信念完成这些操作。
如果他知道如何实现功能的代码,调试相关if else代码,进行逻辑的修改,从而可以在白盒层面测试到自己需要测试的部分。
(5)开发人员需要了解的知识面远大于测试人员。
完成一个任务,开发需要实现这个功能,需要付出很多精力。
对于测试来说,完善的测试设计和测试执行,可能需要了解业务逻辑层面,而不是技术层面(如果在白盒层面进行更多的测试,情况会不一样)。
总体时间是固定的,开发人员将在实现功能上耗费更多精力,响应减弱在自测上的投入。
而测试人员刚好相反,测试人员会投入更多的精力去分析功能的异常逻辑是什么、用户的正常使用路径和异常使用路径是什么、用户体验上是否有改善的地方、开发会如何设计这个功能、会存在什么样的风险和问题等等。
希望开发也会用一些时间思考测试人员如何测试程序,这样或许能帮助提高自测的质量。
六道轮回
上面讨论了个人做开发期间的一些感受,希望真正的站在开发的角度去理解测试,从而更好的从测试角度去测试产品、提高开发的质量。
我需要解释这篇文章标题的含义了。
我在2009年问过一位在微软总部工作的测试开发工程师,微软的测试最大的核心价值观是什么。