我的测试生活感悟

2010-08-11  王钧澜 


 
 
 

1. 真的是万事开头难,但我觉得更难的是,每天都坚持做同一件事情。在不被强迫的情况下(如:上班、吃饭、睡觉...),在可自由支配的时间里,现在我每天坚持做的貌似只有GoogleReader。希望我的测试感悟系列也能坚持下来。

2. 在做模块的接口测试过程中,发现开发所犯的错误大多是一些低级的,深刻领悟到:复制粘贴是代码最大的隐患!

3. 最近发现一个BUG,是开发解析xml错了,导致有的节点内容未读上来。就这样一个BUG描述,根本看不出它对产品有多大的影响,也许最了解的人,就是开发自己了。

4. 写的模块接口测试案例多了,渐渐发现了一些自己的代码风格,也许以后可以开专题来讲解一下。测试代码和产品代码是有很大区别的,测试代码其实是有通用的一些模式的,不然就不会出现XUnit之类的东西。可以说XUnit也是一种风格约束。我总结出来的自己的测试代码都会分成以下几个部分:

* Caller

对开发接口函数调用的包装,使得案例有一个统一的入口调用开发的函数。开发接口函数变动,只需要变动我们的Caller。(封装变化)

* Checker

对接口函数调用的验证方式的封装。对被测函数的返回值检查是最基本的,更多的时候,返回值并不能告诉你一切,返回值告诉你它做了什么,但它没有证明给你看它确实做到了

* DataDefine

测试数据是必不可缺的,我将测试数据单独抽离出来,方便管理和组织。

* TestFixtureBases

TestFixture的基类,这是我喜欢使用的方式,定义某一类案例的基类,它们做同样的SetUp和TearDown,共享同样的函数调用。

* TestCases

最终到了测试案例这一分类,如果我们把上面的四个分类都做好了,就会发现,测试案例都可以使用一种非常简洁的方式来表达。在我看来,一个测试案例代码,五行左右代码是最优美的。

* (附加)CommonSpec

有时候,为了让测试案例更加容易理解,我还喜欢使用BDD的方式表述测试案例。因此,我个人可能还会有一个分类叫CommonSpec,定义的一些自然语言相关的函数。可能这个并不一定适合每个人。

5. 上周五去听了一个关于软件架构师的课程,总结一下大约有如下几点收获:

* 架构师首先要明白真正需要解决的问题是什么。例子:老太太买梨

* 一个优秀的架构师,必须有一套自己明确的方法论。

* 政治->经济->技术,架构师容易只看到技术上的问题,其实有时技术问题并不是最大的问题。

* 架构师是参谋长,也是辅导员。有了自己的架构设计,还要将自己的架构设计描述清楚,并推动设计方案的实施。

* (概念部分)架构师的定义,分类,架构设计的过程等等。

Art Of Unit Testing

今天把《Art Of Unit Testing》的前四个章节读完了,作者以自己的亲身经历,使用简洁清晰的语言,为我们展现了单元测试的艺术。

1. 怎么定义一个好的测试案例呢?好的测试案例应该是在N年后还能运行良好并易于维护的。

2. TOOD - Testabled Object-Oriended Design。作者也提到了这个颇有争议的问题,许多人认为,增加代码的可测性的同时,会使得代码变得更加丑陋。而作者不认为是这样,作者认为这样的修改 是另外一种面向对象,同样的也是优美的,这就是TOOD。

3. 为了代码的可测性增加的一些代码,常常不希望编译到最后的产品中。可以有很多办法,比如用宏判断,如果使用的是.NE,还有一种办法,就是在相应的函数或类上面使用这个Attribute:[Conditional("DEBUG")]

4. Action-Driven Testing 与 Result-Driven Testing,两种不同的测试流派,一种检测行为本身,一种检查最后结果。不能说一定谁优谁劣,但作为单元测试,更多的应该是Action-Driven Testing,因为这样可以隔离一些其他外部的不稳定因素,当你的案例失败时,能够更加准备的定位问题所在。(事实上,集成测试就是Result-Driven Testing,一个很大的困惑就是集成测试案例失败了,通常是很难马上定位到原因的。)

5. Stubs和Mocks的区别,这两个东西看起来几乎是一样的,事实上也确实很相似。但是,他们的区别也同样明显:Stubs不会导致案例失败,而Mocks会。换成我的理解就是,Stubs是一些假的东西,它能模拟一些我们想要的结果,而Mock呢,它就是一间谍(Test Spy),告诉我们被测代码做了些什么,于是,我们通过Mock对象来进行检查。

6. One Mock Per Test,一个测试案例中,通常的模式是N个Stub对应1个Mock。如果一个测试案例有多于一个的Mock对象,说明你的案例感情不够专一。而一个测试案例,是可以有多个Stub对象的,他们共同协作模拟一些特定的虚拟场景,然后通过Mock对象,验证我们的被测对象是否对此做出了反应。

淘宝的接口测试白皮书

今天晚上回来后看到淘宝测试团队发出来的《接口测试白皮书》,一口气将它读完,写的还是相当不错的,有非常多值得借鉴和学习的地方。

1. 在工作的流程上,各个测试角色是可以互补的,接口测试的设计、用例可以跟功能和性能测试共享,从而构建出整个产品各个环节的测试案例覆盖程度。

这一点之前感触并不深,现在看来,同一产品的不同测试团队,像共享bug一样,将所有人的案例都组织在一起,一起共享是一件非常值得去做的事情。

2. 我们的客户是调用接口的人,不是开发接口的人。

说的好!之前一直以为是为开发服务,看来是上面的话总结的比较好,为调用接口的人服务。

3. 测试用例设计出来以后应该经过评审,并将评审结果以某种形式记录下来,作为测试实施的最终方案。评审最好由以下这些人员共同参与:需求方、设计人员、开发人员、功能测试人员、接口测试人员以及这些人员的直接主管。

我们这边的接口测试案例的设计评审还是空缺的,上周我还组织了一次功能测试人员和接口测试人员的接口测试案例评审,看来我要继续推动这件事了。

4. 质量评估标准:

* 接口覆盖率是否达到要求。内部接口90%,外部接口95%。

说实话,挺高的。我们目前对自己的要求是至少70%,我们认为追求过高的代码覆盖率的意义并没有想象中的大。相反,过度要求高的代码覆盖率,可能会造成反面影响。

* 测试用例中对接口业务规则的验证是否完整。

关键词:业务规则,保证了业务规则,就保证了用户使用的大部分功能。

* 测试用例中是否覆盖接口之间的关联性测试。

* 遗留的 bug对系统的影响程度。

* 测试用例与测试代码是否一致。

我们主要通过CodeReview和自己的人品,并没有做太多严格的审核。

* 测试用例是否可持续回归。

* 经过测试的接口是否达到了调用方的标准,调用方能否使用该接口来开发出产品设计说明书所设计的应用。

可以看出,淘宝的接口测试评估标准还是挺全面的,做的确实不错!非常值得学习!

5. 还可以继续提高的地方(都是我们想要做的,就不一一点评了):

* 测试数据管理框架构建与统一

* 接口测试项目构建基础框架

* mock 框架化

* 高比例代码自动生成框架

* 接口测试工具集与三方库的本地化应用

6. 测试未来遐想(想象力确实很丰富啊,同样也是我的梦想):

* 测试虚拟化:提供接口测试虚拟机,构建测试虚拟化层。将被测系统运行在虚拟机中,与外部系统剥离,进行内部代码检测、内存检测、数据校验与逻辑检测。

* 测试智能化:智能分析系统代码,智能生成测试代码,智能 mock 外部系统,智能执行测试代码,智能分析测试结果,智能定位缺陷,智能修复缺陷。

7. 测试框架及工具组合:JUnit+DbUnit+Spring TestContext Framework+Unitils+TestNG+CruiseControl+Clover

感叹一下Java相关的框架就是多啊,不像C++,难啊!我们的组合是:GTest + GMock + CCNET(MSBUILD+Svn) + 自己开发的C++代码覆盖率统计工具

谈谈面试

我是一个没有什么经验的面试官,偶尔才参与几次面试。发现面试他人是一件技术要求非常高的工作,我们必须在很短的时间内了解一个人,如果方法不当,很有可能错失一个人才或是招入不合适的人。最近又参加了一个结构化面试的培训,由于之前并没有专门去研究面试,整个讲座听下来还是蛮有收获的。在讲座之后,我们又继续分享和交流了自己面试的一些感想和对结构化面试的一些看法。

1. 什么是结构化面试?按照我的理解就是:面试官使用精心设计的题目,让应聘者作答,作答过程中对题目只重复不解释,对解答的结果进行严格的评分。可以说,结构化面试对面试官的要求非常低,不需要解释题目意思,不回答应聘者提问,不需要随机问任何其他问题,只需要对照答案填1或是0。因此,可以看出,结构化面试对题目的要求是非常高的。

2. 为什么需要结构化面试?很多时候,面试官都是依靠感觉去面试别人,问的问题也比较即兴,感觉好了就招进来。然而,并不是每个面试官的感觉都是对的,依靠感觉做出的判断经常会出现偏差。因此,就需要对面试过程进行结构化,形成固定的模式,依靠高质量的、全面的、科学的试题,来衡量一个人的综合素质。

3. 应聘者只往好的方面答怎么办?结构化面试的试题中,并不一定往好的方面答就能给分。

4. 冰山以上的职业技能容易被发现,冰山以下的职业素质、道德、心态是比较难发掘和衡量的。

5. 面试他人前一定要提前了解应聘者履历,应聘职位的要求,准备一个安静舒适的环境进行面试。

6. 面试时不要轻易打断应聘者,不要发表自己的观点,不要告诉应聘者你答错了,不要把面试结果当场告诉应聘者。

7. 有的面试官比较自大,他们认为从来都不会输,因为被他们拒绝的应聘者根本没有机会展示他们的才能,而被他们招聘进来的人却总是最好的。

8. 有的面试官优越感太强,总是想方设法难倒应聘者,以显示其的威信。

9. 有的面试官不注重形象,给应聘者带来非常不好的印象,从而对整个的公司的形象造成影响。

10. 应该先对职业技能进行面试还是对性格态度心理素质进行面试?我认为应该先对职业技能进行考核,然后再对其他方面进行考核。职业技能的要求就是最基本的,在其上再讨论比如团队合作,工作心态才有意义。

11. 我觉得不应该只招聘同样性格的人,性格可以有多样化,内向的,外向的,都可以。

12. 照搬结构化面试其实是不行的,一定要依据自身特点,进行合理的运用才能获得最好的效果。

13. 面试是一个很大的学问,我现在只能领悟到这么多了。

不要被代码覆盖率蒙蔽双眼

新年新开始,继续我的测试生活感悟。“代码覆盖率”是一个有意思的话题,围绕它的讨论有很多。基本上,人们都认识到了,代码覆盖率并不能说明测试的好坏,它只是一个度量方法,用于度量我们测试的广度。它只能告诉你,你的测试代码覆盖了哪些被测的代码,并没有告诉你,覆盖的被测代码是否测试好。

代码覆盖率有诸多好处:

1. 能一定程度上说明测试覆盖的广度。

2. 通过代码覆盖率结果,能够比较直观的了解到哪些代码未被测试,哪些分支未被覆盖,进而补充相应的测试案例。

3. 代码覆盖率具有非常好的可操作性,可以在一定程度上衡量测试人员的工作。

4. 代码覆盖率给程序员和测试人员以信心。

但是,即使你的代码覆盖率达到了80%或者更高,不要被代码覆盖率蒙蔽了双眼!

1. 好好回想一下覆盖的80%的代码中,你一共发现了几个Bug?

2. 剩下的20%代码,极有可能产生80%的Bug!

3. 覆盖的80%代码中,你真正进行验证的代码函数有多少?

4. 覆盖的80%代码中,你真正了解的代码有多少?或者说,有多少代码是无意间被执行的。

5. 你是否保证了不同操作系统下测试案例的执行?

6. 这80%覆盖的代码中,你是否偷懒省去了某些复杂的检查点的检查?

7. 你是否会因为某个分支只有一行代码,而省去这个分支的测试案例?

8. 你是否存在一个检查点也没有的测试案例?

看了上面的8条,再想想你的80%代码覆盖率,还会感觉测试已经完全,无事可做了吗?

代码覆盖率只是一个最基本的前提,一定要保证,但不是意味着达到指标就代表测试的完成。

永远要记住,80%的代码覆盖率也许只是刚刚开始,被测试代码中到底潜藏有多少Bug,谁也不知道!

237°/2378 人阅读/0 条评论 发表评论

登录 后发表评论