此文是应一位密友之约写的,我并不是专业测试人员,做过的测试也不多,但此文还是值得一看,因为我最不愿意干的事情就是写那些让人看了入睡的文章,所以你可以把本文当作一篇散文,听我这个落魄的开发者谈谈自己的经历和感受。
周正龙:我的虎照没有任何bug。
网民:没有?我看颜色就不对。
周正龙:有什么不对?我用两部相机拍的呢。
网民:角度也很怪异。
周正龙:我冒着生命危险拍出来的。
网民:怎么老虎一动不动?
周正龙:保证没有问题。
网民:那你公开其它的照片。
周正龙:不行,有版权的。
网民:哈哈,我找到了老虎年画。
周正龙:你们造谣,我的虎照绝对没bug,人头担保!
网民:……
我认为软件测试的难点并不在于技术,那么是什么?开发人员和测试人员永远是一对矛盾,这才是最大的难点。why?开发人员说:“我写出来的东西完美无缺。”测试人员:“胡说八道,我立即找一堆bug出来!”所以如何协调开发人员和测试人员,那就真的得凭一些本事了,我并不是一个处理人际关系的专家,否则也不会沦落到今天这种只能写一些自娱自乐无人欣赏的代码的这种地步了,但有一点算我的经验吧,那就是尝试让开发人员把测试人员看作帮助自己提高软件质量的朋友,而不是专门找茬的敌人,也尝试让测试人员把开发人员当作为自己提供测试游戏的知己,而不是只会制造麻烦而又拒绝承认错误的痞子。和周正龙不同,开发人员一般都不是明知故犯,只不过坚持自己是对的跟周先生那种执着有点像……请勿对号入座。
某开发男:“我检查过了,程序绝对没问题……什么?测试报告?写那么多麻烦东西,有病!”
有些人认为:开发人员同时也可以作为测试人员,所以没有必要雇用额外的测试人员。这个观点我曾经同意过,但现在我是不以为然,很重要的一个原因:用同样的方式做出来的事情就非常有可能产生同样的错误,因此开发人员是很难很难发现自己的bug的。作为开发人员中的一员,我很了解这种心态,那就是不高兴承认自己的错误,只要程序按照自己的方式去运行,正确了就“测试通过”了,几乎没有考虑太多的情况,所以在测试人员较少的公司,一种比较好的变通的办法就是“交叉测试”,我测你的,你测我的,但这种方法能发现的问题也比较有限。雇用测试人员,还有一个也是很重要很重要的原因:绝大多数开发人员不愿意写测试文档。其实不光是测试文档了,凡是文档都不太愿意去写,这不是个别,这几乎是个通病,就算强迫开发人员把文档写出来,恐怕质量也是令人不敢恭维,所以我们需要测试专员,专业的测试人员是软件质量的重要保证。微软公司的测试人员跟开发人员的比例在2到3之间,也就是一个开发人员,就对应两到三个测试人员,没有那么多测试人员,我不相信Windows能这么流行。这也就是说:测试人员要做一些开发人员不太愿意做的工作,反过来说也行啊,开发人员要做一些测试人员不愿意做的工作,反正就那意思,专人专事。
某测试男:“测试报告,你的程序错漏百出,报告完毕!”
和开发人员一样,测试人员的水平同样有高有低,我见过高水平的,也见过低水平的,区分他们并不难,只需要看看他们的测试报告,对程序代码精通的开发人员阅读这些测试报告并不是一件难事,测试人员的水平能很快就看出来了,为什么别的不看,就看测试报告?很简单,测试报告对于测试人员来说,就相当于是开发人员的生成代码,内行人看看不就懂了么?你也许见过很多优秀的测试报告,但可能你没见过这么差的测试报告(BTW,我有一个朋友说:“没有最差,只有更差。”),我曾经写过一个小型游戏服务器程序,负责随机发牌这种功能,拿给测试组测试,测试好了之后,我发现只有一条bug记录,但严重度为最高,这个报告这样写:“几率完全不在控制中,程序错漏百出!”我保证你没看错,对,这就是他的测试报告,只有一行字,看完后我差点晕倒,这行字我完全看不出我辛辛苦苦写的程序到底出了什么问题,换成你估计你也不行,更何况他还说“错漏百出”呢,却只有一条bug记录!为什么会有这种低水平的人从事测试工作?那就是对软件测试不够重视,很多公司认为会用电脑的人都能做测试,其实不是这样的。我接触过一个有些水平的测试人员,他有过两年测试经验,确实就不一样,我把我的程序交给他,测试完之后,他给我递交的测试报告中有十多条bug记录,我一开始也不太相信我的程序怎么会有那么多问题?但后来仔细看之后确实发觉自己很多地方做得不到位,他的测试报告非常好,测试手段也比较高明,比如我的程序在运行过程中频繁切换窗口会导致的问题,在Windows98下偶尔出现的声音异常问题(当时开发使用Windows XP系统),程序启动窗口位置不妥影响外观的问题等等,他都测试了出来,除了bug记录,还有大约七八十条测试记录,大多数都标记为pass,每条记录都有足够详细的测试步骤和环境,我认为他工作很认真,可惜后来他离开公司比较早,跟他交流也就比较有限了。当然,并不是所有的bug都是开发人员的过错,偶尔可能是测试人员对功能的误解,或者测试机器上的电脑确实有比较严重的问题,这样经过验证协商,我们都可以把bug记录close掉,这都是有依据可循的,而不是一个“错漏百出”就了事那么简单,如果是这样的话,那测试这个工作也未免太容易了。
测试:快来看看,我发现bug了,这怎么回事?
开发:来了来了……哪里?
测试:嗯?怎么没了?
开发:下次看清楚点再说。
……片刻……
测试:现在出现了,快来看看!
开发:好,马上过去……哪?
测试:怎么又没了!
开发:……
这种情况我以前遇到太多次了,写过程序的人都有这个体会,有些bug的出现机会是非常非常宝贵的,因为程序运行总是带有很大的随机性,也许这个bug在某个时间才会被触发,或者根本就是低概率随机,特别是用C++写的程序,这种问题尤其多,当然随着我经验的不断上升,我以前曾经写出过的bug,现在是越来越少了,我知道如何从代码这个层面上避免出现这种问题,(这个不在本文讨论之列)但即便如此,我也难保证到了测试人员手里一定不出现。反应测试人员水平的还有一个重要指标:就是重现bug的能力。水平高的测试人员能很好地记录bug出现地条件,就好像每次空难的时候,黑匣子总是能很好地帮助事后处理人员找出空难当时的飞机运行情况以及环境参数,以此推测,为什么会出事。如果真的是一个很难重现的bug,就像前面说的,根本就是低概率随机的,那怎么办?那就想办法把bug描述清楚,以截图的形式记录出错现象,用清晰简要的文字,描述清楚当时的运行情况,这是测试人员该做的事情,而不是bug“跑过去就没了”。有些问题确实很难发现,甚至解决了都不知道其所以,我最近写了一个程序,这个程序会加载若干个模块,从模块中调出资源,将资源存入内存中,按道理,这个时候我可以卸载模块了,因为我要的资源已经到位了,接下去我要使用这些资源,就是把它们转变为流,再去调用别的接口,但出现问题了,在加载/卸载若干次之后,Allways出现一个错误,通过调试,这个错误发生在CreateWindow这个Windows API的内部,如果从表面上看,这已经是超出了我的能力范畴,但我知道,这仅仅是表面,其实质一定是在调用到CreateWindow之前,就出现了内存越界之类的错误,但我细心测试了我的程序,所有可能出错的地方都排除了,我的代码既没有越界,也没有泄漏,但问题最后还是解决了,很简单,就是把卸载模块这行代码,挪到使用完内存中的资源之后,就没再出现过这个问题,按照逻辑,我一直想不通为什么会这样,我使用的资源是已经调入我的程序动态分配的内存空间中了,应该跟模块没有什么联系了,可经过大量的测试,发现这么改之后就没再出现过问题,我知道我还是没法完全理解这个复杂的系统,尽管我尽了最大努力。测试人员也是这样的,不能重现所有bug,但他们可以尽量去记录bug发生的各种情况,对于修正bug的开发人员来说,当然是越详细的信息越好。
“你相不相信我的测试结果?你的程序在所有使用华硕主板的机器上会死掉,其它的就没事。”
相信不?不相信?亲眼看看后,我还真的相信了,但一直不知道原因,这个问题确实是我曾经遇到过的问题,也是我遇到过的所有问题中最怪的问题之一,这还真的被一个测试者“总结”了出来,对他来说,能总结出这个问题,非常不容易,为了验证是否的确如此,我还找了一台华硕的笔记本电脑来测试,还真的如此!我也很想知道原因,可我现在还是不知道,而我离开那家公司很久了,我也许之后也永远不知道了,我说这个例子,目的是想告诉大家,有时候真的没有什么“不可能”,所以请不要随便怀疑测试人员总结出来的那些稀奇古怪的bug,表面上的一个bug,也许可以牵扯到非常深层次的问题。
我也不知道再谈点什么好,测试工具,测试流程,这些我想别的地方讲得太多了,但,软件业有一条黄金法则,那就是“没有银弹”,再好的测试工具,再精密严谨的流程,最终都是人在使用,人在执行,没有一种足够强大的工具来完全替代开发人员的工作,对于测试人员来说,也是这样的!除了对工具的引进,流程的改进,更应该重视人员自身能力的提高,我想这也不光是软件行业了。