最近一直在研究从测试的角度提升软件质量,构建自动化测试机制。在此过程中,发现了n多的问题。因为本人目光短浅,只能确定在工作部门内确实存在如此问题,至于整个公司是否如此,未曾考证。本着解放思想,实事求是,一切从实际出发的马克思列宁主义思想,总结了以下四点。
1 受制于流程
目前的开发流程走的是典型的瀑布模型,各个阶段的时间按需分配好,研发人员只要按部就班的进行就好了,除了到最后大家都抱怨时间不够用之外,好像也没有什么大问题了。每个人都激情饱满投入到自己的工作中,至于这项工作为什么要做,作了有什么意义,就很少有人考虑到了。CMM确实是很好的开发流程,但是它只是一种工具,帮助我们提高生产力,更有效率的开发产品。做任何事情,都应该是人主动,工具只是用来提供方便,人不能让工具牵着走。
单元测试的重要性,每个人都知道,但并不是每个人都能理解为什么要做单元测试,作了有什么用,相信大多数的开发人员写单元测试都是为了应付QA的检查。那么为什么我们的开发流程要有单元测试这么一项呢?迄今为止,人类所能发现的最有效的保证软件质量的方法就是为其编写测试代码(这样做也是基于一种假设,即测试代码是很简单的,简单到不能出错的程度,所以不用编写测试代码的测试代码)。因为测试代码可以自动运行,可重复,而且结果,风险都是预期的,一切都可以控制在人的掌控范围内。而我们常用的代码 review,调试等手段都是不可重复,风险未知的。(不要说“高风险,高回报“ ,这句话用在这里明显不合适)。开发人员的程序完成后,有什么证据能证明代码的质量是合格的呢?空口无凭,这时候,测试代码就是最好的证据。它将一切指标都量化在具体的可考证的测试程序上,使你的工作输出有了可统计的书面资料。
假设程序员不知道上面这些道理,但是我们的领导,QA是肯定知道的,要不然也不会要有单元测试输出了。我们可爱的程序员在开发结束时,也还是为QA输出了单元测试代码,有好多还达到了100%,敬业精神可嘉。现在问题来了,所有的测试代码到此为止,立刻被挂起,再无人过问。 马克思主义辩证法确实博大精神,虽然大家都学过,但是能真正领会在心的人确实不多。任何事物都是不停运动的,我们始终要以运动的眼光看待问题,而不能静止的看问题。软件开发是一个不断渐进的过程,源程序永远不可能停在某一点上,在每一点上,我们都要对其质量进行保证。现在大家都知道要保证开发结束这个点的质量,因为提供了测试代码。但是到修改一个Bug,更改一个问题单后,在此后的每一个点上,都没有人关注测试代码了。如果测试代码只能保证很久以前的,现在已经不使用的某个版本的质量,那么我们当初作写测试代码又是为了什么?
任何流程都是有利有弊,我们在做事的时候要多思考,多用辩证的观点看问题。在每天忙忙碌碌的工作中,停下5分钟,思考一下这样作的意义。
另外,在程序员编写代码的时候,如果用条条框框来限制他,而且这些条条框框对实际工作又没有什么实际意义,那么他就会在其中做一些投机取巧的工作,这一点在实际工作中并不少见。所以在适当的工作中使用适当的流程很重要。
2 盲目看重代码量
现在代码量这个词很时髦,大家都挂在嘴边,数字大的人好像也是好自豪的样子。项目的一切统计数据都是依赖于此。类似各个阶段review的错误数,测试用例必须失败数等等。而且有一点很不好,谁的代码量大,开发速度快,谁就是编程高手,谁的工作输出就多。这也是我们软件质量一直上不去的元素之一。因为我们度量方式出了问题。实现同样的功能,编写1000行代码可能要半个小时,但要编写200行完成,可能就要花费1个小时或者更多。应为前者更多的是copy/paste的堆砌,只涉及很少的脑力劳动,后者则应用了更多的创造性思维在其中。出来的代码质量也是显而易见,后者更容易维护,更容易扩展。现在据我所知道的,部门的大部分代码都是到处是copy/paste,重复,冗余代码一大片。而且很多人还陷在其中,乐此不彼。
说到这里,想起了有一篇文章说,为什么我们以前的产品质量很好,现在的则很差,得出的结论是人没有了以前的那种精神。这固然是一个方面,但我觉得还有更深层次的原因(我觉得我周围的同志都是很有责任心,都很刻苦)。以前的软件生产本身就局限在当时的需求之上,并没有考虑到以后的扩展,所以在架构在拓展性方面很差;很多软件的初始版本开发工作都是新手写的(至少通过看代码可以得出这个结论),很多地方地方都是程序写的很死,根本没有考虑以后怎么办。当然,这些在当时都不是问题,所以当时的软件质量就很好。但是现在情况不同(唯一不变的就是还是新手多),当初隐藏的问题一一都暴露出来了,我要添加一个功能,怎么能加进入已经成为了一个很大的问题了。我相信每个人都有这种体会,要在一个巨大的函数中加几句话实现一个新功能,这里面充斥了大量的if/else,费了大半天看明白点后,再在里面加上一个if/else 实现自己的功能。如果是一个有激情的程序员,想把这些代码重构一下,无奈这些代码的测试代码早就无影无踪了,根本就无法保证重构后的质量,也只能罢手。我们的软件现在就是处在这样一种恶性循环中,只不过现在还没有到无法自拔的地步。
现在,迫切需要进行的是重构项目代码,尤其老代码,重构的结束以建立了完善的单元测试为标志。
3 没有完善的自动化测试机制,凡事靠人力。
作为一个业界高端的企业,我们到现在还没有建立起完善的自动化测试机制,凡事都要靠人力。重构里面有一条经验,事不过三,三必重构,说的是如果代码有3个地方重复了,就要想办法重构了。同理,若你做同样的事情三次以上,就要考虑是否可以让其自动进行了。我们现在的情况是,只要人能作的事情,都由人来做,人不能做的,才让电脑作;而不是想办法让电脑作尽可能多的事情。(如果人能编译程序的话,也一定会有人去做的)如果建立了完善的单元测试,自动化测试脚本,那么每一次出版本后都可以对这些基本功能自动测试,得出测试结果,就不用人力反复验证这些基本功能了。测试部之所以反对研发对程序大改,也是基于此,因为又要将所有的功能测试一遍。试想,如果所有的重复验证工作都可以自动进行的话,那么将节省多少精力和成本,而且出错率比人工要低的多。当然这是一个终极目标,但现在我们连一步都没有迈出去。 部门经常发生问题单漏验,版本编译出错等问题,其中有人的工作态度的问题,但其根本原因是我们妄图凭人力来取代电脑的工作。人不可能做到事无巨细,万事总有疏漏的时候,惩罚措施再怎么严厉,还是会有人会犯,只要有可能犯的错误,就一定会有人犯的。这一点,再完善的流程也保证不了。比如漏合入某个文件导致版本编译不过,其实很好解决。每一个小时自动编译所有文件,按照出错信息的关键字将结果发送给相关人员,这样就能在第一时间发现问题,不用等到出版本的时候才知道出了问题。
只要肯想办法,我们平时的很多工作都可以自动化完成的。像出版本,安装,验证这些基本功能,只要肯作,实现起来并不难。一开始做,好像没有什么实际的好处,但使用的时间越长,你就可以从中受益越多。
4 盲目依赖流程
如果手里只有一把锤子,那么看什么问题都想钉子。就像很多程序员,以为使用的是面向对象的编程语言,编出来的程序就是面向对象的。我们现在的问题是,以为只要严格按照流程作了,出来的产品质量就是过硬的。这就犯了教条主义错误。有些增强性质的项目,可能就是在某个方法加一两句话,也要按照从需求开始的一系列流程来进行。造成巨大的资源浪费。对待问题,应该一切从实际出发,实事求是,使用最合适的手段来解决相应的问题。现在并不是我们的流程还缺什么,而是应该从流程中去掉点什么,使其能和具体的开发有效的结合,提高生产率。
我们的问题单验证,版本验证流程步骤已经很多了,可是还是不能有效的解决问题,原因是不是我们的步骤还太少?此流程建立的时代,自动化的测试工具,理念还很匮乏,所以只能凭借繁杂的手续来保证问题的解决。但是现在,各种自动化的测试工具已经发展的很完善了(相当一部分都是开源免费的),适当的使用工具可以缩短我们的流程,提高我们的效率。
以上4点,我认为是现在急需解决的关键问题。如果它们都被解决了,那么一直困扰我们的其他疑难杂症都会迎刃而解。