首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件测试 >

片面追求单元测试覆盖率之小弟我见

2012-04-14 
片面追求单元测试覆盖率之我见一些个人之见,讲出来希望大家讨论。这完全是工作中遇到的一些具体问题抽象出

片面追求单元测试覆盖率之我见
一些个人之见,讲出来希望大家讨论。这完全是工作中遇到的一些具体问题抽象出来的一个东西,仅属于个人之见,任何的意见都是欢迎的。

----------------------------------
在工作中,当被问到“如何提高代码质量”,回答无非如下几个,增加评审,代码规约,单元测试。不知起自何年何月,如今一些机构开始引入“单元测试覆盖率”的概念,并由此对程序员提出了覆盖率要达到70%,90%,以此来评判程序员工作的质量,以及产品的质量。这里先预为单元测试下定义以免混淆,即,基于Junit,类与代码级别的,与运行时无关的白盒测试。

而单元测试覆盖率,何以得知呢?一个(当然不是所有)最常使用的办法便是如cobertura之类的工具来执行Junit的测试用例,这些工具不会去统计程序的逻辑,而是判断用例执行到的行数。如果再引入hudson一类的持续集成工具,便可生成漂亮的日报表,管理层也就可能直接地了解这些技术数据。这些都是好的实践,但我想说的并非这些,而是想与大家探讨这些数据是否与产品的质量有着必然的相关。

写过测试用例的朋友们一般地会了解,测试用例与接口有必然的关联,而多数情况下会是直接调用。修改接口会带来测试用例的修改,这是多数情况下不争的事实。有人说为测试可以预留专用的接口,但这种做法在一个要求代码安全的机构中不会得到接受。所以,代码评审/重构或代码上下文变更导致的接口变化,多数情况下会带来测试用例的修改;用例越丰富,这部分的工作量越大,此其一。

其二,讨论单元测试覆盖率与正确代码逻辑的相关性。我们需要衡量的代码的逻辑,乃是在运行时外部触发系统时可能运行的所有逻辑,其包含接口内部逻辑,也包含接口调用逻辑。当接口间存在内容耦合和控制耦合时,合理的测试用例中对于接口间的调用顺序和想定上下文都有要求,与覆盖率并不相关。如a-b-c与c-b-a的调用,覆盖率完全相同,但结果可能完全不同。这一点在测试状态机相关的代码时显得更为重要。

其三,我们经常说到20%和80%的关系。即有80%的时间应当用在20%重要性的事情上。反观程序员写的代码,关键模块与非关键模块的比例也如是。倘时间不是问题自然可以把所有的事情做到完美,一旦时间是问题,哪一个优先,自一目了然。问题是,关键模块由于逻辑复杂,依赖较多,往往是最难测试,其用例也最难写作。人性往往倾向于先易后难。若覆盖率是唯一的指标,最关键的部分便很容易因为覆盖率目标已经达到而被忽略,80%的覆盖恰恰没有覆盖的是最应该测试的代码,很不幸,最易测试的,是那些对于POJO,数据库,配置文件操作的清晰逻辑,通过一个集成测试的用例就可以全部保证的。

那末,为什么覆盖率会成为这样多项目经理趋之若鹜的管理方法呢?显然,这是一个节约管理成本可见收效的举措。只需要把cobertura和hudson配好了放在那里并说明给所有程序员,就可以坐看数字一天一天的上升而觉得质量在一天一天地变好,不需要组织什么评审,不需要去过问每一个人的状况,不需要再去费力地去看报告,何乐而不为?

容我说,懂得我上面说的话,却坚持还要这样做的人可以被看成软件项目管理中的官僚主义。人力就是人力,它不会凭空变少,也不会凭空变多。用在70%-90%覆盖率上的人力成本,与其他方法比起来值与不值?软件工程没有银弹,只有综合各种方法形成最适合自己产品的方法才是最好的质量控制。在我个人看来,就单元测试而言,确定我们拥有高质量的测试用例,确定关键的模块都有相关的测试对应,比简单地追求覆盖率要重要得多。而这些通过传统的评审和走查可以轻易做到的事情,却常常被我们定义流程和日常管理中忽略了。

[解决办法]
很多事情是可以不断改进的
只要跟上面好好的沟通,拿出客观的事实依据,就可以调整该指标
做相应的裁剪

质量是什么?

何谓高质量?

不是超高的标准,做一个民用的小项目当然不能用航天项目的要求来进行测试

主要看客户的要求以及项目的特点,满足客户的要求就是高质量

测试覆盖率也是一方面,如果公司内部要求这些指标,就要花费相应的成本,如果公司认为这些成本和带来的效益相差无几,那就可以追求测试覆盖率

不是所有测试人员都有LZ这样的觉悟和水平的,你站在管理者的角度也要考虑这些方面,你要想如果你作为领导该如何去量化的管理,量化的合理性能够体现你的管理水平和业务水平。

还是恭喜你的,你所在的公司还是在向着正规管理的方向努力着,不管现状如何起码努力方向是对的,积极沟通具体的实现方法吧,设立这些指标应该与所有的利益关系人达成一致才真正有效,询问到你的意见时,你就可以客观的将自己的想法表达出来,听不听是领导的事情取决于领导的水平,说不说是你的事情,尽人事听天命吧,哈哈哈哈

一家之言仅供参考

祝你成功~~
[解决办法]
嗯,同意。很多时候很多人一直在片面地追求工具和数据。
[解决办法]
测试,尤其是单元测试,其成本和效果之间的平衡向来是一个难点。
我觉得LZ的观点基本上是对的,但是,必须有一个前提,员工的素质整体上是高的。管理上的惰性,往往是因为管理是基于人本恶来假定的,关注的是如何让人不犯错误,而不是说,在信任的前提下致力于提升员工的能力。
另一方面,如何说服领导也是一个问题。
[解决办法]
单元测试,最重要,但不那么明显的作用是:让你站在使用者的角度去设计。这与我的实践体验一致,测试最多能保证,发现错误,但不能保证错误不发生。如果把测试当作“质检”我想“设计”就是“生产”,测试起的作用太大,能发现很多问题,或是很重要的问题,就表明生产有严重问题,所以,拼命强调测试,不如努力探索如何生产高质量的东西,探索改进生产的方法,我强调生产,而不是测试。我的实践也证明了个经验的正确性。很多人把测试最重要的东西忘记了,而去强调不那么重要的东西。一看就一知半解。有两种情况,可以强调测试,一是:你的生产已经很好了,为了锦上添花。 二是:你的所有改进生产的办法都想尽了,实在黔驴技穷了,为了做做花架了,或是作点探索,也不管是不是有效。
[解决办法]
做能够做到的(代码覆盖率能够让多数人做到并被别人看到),片面追求代码覆盖率固然不好,但是单就代码覆盖率本身并没有什么错误。刀其实是中性的,但是到了歹徒手中就成了凶器。测试中各种方法、工具、理论总体来说是好的,但是如果让人错误的使用,就会出现非期望的结果。
[解决办法]

探讨
首先,感谢大家的回复,很多是高论。现下继续写作我的观点,愿意和大家继续讨论。期待更精彩的观点。
----------------------------------

开发人员测试(请注意我没有说单元测试)的好处已经基本上成为共识,其目的在于在软件流程的上游发现尽可能多的问题,从而减少质量问题带来的人力成本。实际上,单元……

[解决办法]
我学习测试方面的知识至今不足2月,但是我发现以我找到的资料看,
国内关于软件测试的水平如同软件生产一样落后,就单元测试而言:
1、覆盖率分:逻辑覆盖和物理覆盖,以现有的手段物理覆盖100%是没问题的,
逻辑覆盖很难达到100%,但这是衡量测试手段的重要指标,这个覆盖率是动态的,
也就是说你的测试工具应当允许随时增加测试数据甚至测试用例以满足覆盖要求,
应该说:任何质量反馈都可能促使我们增加覆盖;


接楼下
[解决办法]
如果你有10000个受测对象,你难道要求开发人员写10000个测试吗?
你不觉得是重复劳动吗?如果源代码改了呢?岂不是更加令人崩溃?!

单元测试,测试的是什么?测试的是产品是否达到设计要求,这个标准就是文档,
我所指的文档并不是你所理解的文字的东西,而是项目模型,是整个开发的策动源,
设计人员描述好文档后,文档就能够策动或生成绝大部分的应用程序代码和测试代码,

开发是由文档驱动的,而不是测试,
测试代码和应用程序代码只不过是文档的2个副本,是对同一种应用的2种描述,
一个是实施,一个是观测




[解决办法]
对于XP开发来说,TDD要求语句的原则是:如果删除一些语句仍然可以让TDD通过,那么这些语句就是多余的。

因此TDD是从必要性这个角度来说测试覆盖率的,是从如何让程序员对测试驱动开发技术入门角度来谈的。注意,测试驱动开发不是时候测试,恰恰相反,它要求程序员习惯用测试来表达自己为什么要写程序,在写实现程序之前先写测试然后才是先(而不是相反)。

因此对于XP开发来说,TDD不是传统的测试。虽然使用单元测试工具,但是它根本不是传统的单元测试。
[解决办法]
Kent Beck所发明的xUnit系列,是对之前几十年前的自动测试程序极大的简化,仅仅保留了最少、最必要的一点内容(可能最近三、四年才逐渐被变得更加臃肿和庸俗)。因此,如果第一次接触xUnit工具,就掉进传统的单元测试理论里边去了,就是对xUnit系列工具的初衷开了个国际大玩笑。

可是,仅仅抄袭网上的关于单元测试的文章,对许多沽名钓誉的人是个捷径,从来不去研究软件工程以及xUnit工具的背后的历史。单元测试的覆盖率概念,有至少30年的历史,我的书架上就有至少2本十几年前的、我认为现在也很难找到相当水平的关于传统自动化测试书籍,可是它们毕竟都是过时的、有害的书籍,虽然写得太好、那些理论太能用来忽悠人了。
[解决办法]
在写实现程序之前先写测试然后才是先 --> 在写实现程序之前先写测试然后才实现

传统的单元测试确实额外地写了很多没有什么价值的测试。当一个程序员都写好了实现代码,它立刻写测试来证明自己有错误吗?这是不可能的。它只能写一些将垃圾固定下来当作教条的测试代码,而不是尽可能为系统重构留下灵活性。

而TDD是系统重构的关键保证,是“安全网”。在敏捷开发中最重要的重点之一就是强调开发时只考虑最简单的二三两个属性或者一两个方法的测试,当许多TDD将系统的框架驱动完成时,就重构!通过重构来提高系统性能、改进系统扩展性。如果写传统的单元测试,只在低级的地方给自己设置教条,而在高级的地方没有写下测试代码,与TDD的实际作用正好相反。

热点排行