当前位置:  开发笔记 > 编程语言 > 正文

单元测试的合理代码覆盖率是多少(以及为什么)?

如何解决《单元测试的合理代码覆盖率是多少(以及为什么)?》经验,为你挑选了10个好方法。

如果你要求单元测试的最小代码覆盖率,甚至可能作为提交到存储库的要求,它会是什么?

请解释你是如何得出答案的(因为如果你所做的只是选择一个号码,那么我本可以自己完成这一切;)



1> Jon Limjap..:

Alberto Savoia的这篇散文正好回答了这个问题(以一种非常有趣的方式解决了这个问题!):

http://www.artima.com/forums/flat.jsp?forum=106&thread=204677

Testivus On Test Coverage

一天早上,程序员问大师:

"我准备写一些单元测试了.我应该针对什么代码覆盖?"

大师回答说:

"不要担心报道,只要写一些好的测试."

程序员微笑,鞠躬,然后离开了.

...

那天晚些时候,第二个程序员问了同样的问题.

大师指着一壶开水说:

"我应该在那个锅里放几粒米饭?"

看起来困惑的程序员回答说:

"我怎么可能告诉你?这取决于你需要喂多少人,他们有多饥饿,你正在服务的其他食物,你有多少米,等等.

"没错,"大师说.

第二个程序员微笑,鞠躬,然后离开.

...

在一天结束时,第三位程序员来到并询问有关代码覆盖率的相同问题.

"百分之八十也不少!"主人用严厉的声音回答说,把拳头砸在桌子上.

第三个程序员微笑,鞠躬,然后离开了.

...

在最后的回复之后,一位年轻的学徒找到了这位大师:

"大师,今天我无意中听到你用三个不同的答案回答了有关代码覆盖的相同问题.为什么?"

伟大的大师从椅子上站起来:

"快来和我一起喝点新鲜的茶,让我们谈谈吧."

在他们的杯子里装满了热的绿茶之后,这位伟大的大师开始回答:

"第一个程序员是新手,刚刚开始测试.现在他有很多代码,没有测试.他还有很长的路要走; 在这个时候专注于代码覆盖将是令人沮丧和无用的.他最好习惯于编写和运行一些测试.他以后可以担心报道."

"另一方面,第二个程序员在编程和测试方面都非常有经验.当我回答问她应该放入多少粒米饭时,我帮助她意识到必要的测试量取决于许多因素,她比我更了解这些因素 - 毕竟这是她的代码.没有单一,简单的答案,而且她足够聪明,能够处理真相并与之合作."

"我明白了,"年轻的学徒说,"但如果没有一个简单的答案,那你为什么回答第三个程序员'百分之八十也不少'?"

这位伟大的大师笑得如此之大,以至于他的肚子,证据表明他喝的不仅仅是绿茶,而是上下颠簸.

"第三个程序员只想要简单的答案 - 即使没有简单的答案......然后无论如何都不会遵循它们."

年轻的徒弟和头发花白的大师在沉思的沉默中喝完了他们的茶.


完美答案.度量标准没有很好的代码.您可以编写100%覆盖率的糟糕代码,但这并不能使代码正常工作.来自我的+1,惭愧我不能更多:)
听起来像是反对代码覆盖的一般概念的论据,作为评估单元测试有用性的指标.我敢肯定每个人都认为这不是一个完美的指标,但个人经验应该有希望在CC%和单位测试效率之间显示一些相关性......
理智 - 您的陈述恰恰反映在对"第二开发者"的回应上.个人经验应该决定它.
4年后,仍然有用.今天早上我的两位同事就把它拉了下来.
对我来说,这个轶事代表了一种理想主义的观点.在具有竞争优先级的项目团队的现实世界中,代码覆盖率达到0%.我们需要一个必需的数字才能在团队中建立单元测试习惯.我来到这个问题寻找关于确定我不熟悉的区域的数字的一些指导,这实际上没有任何帮助.我很高兴其他场景中的人发现它很有用.
这是2015年和指标*做*做出好的代码.它们是良好代码的指标,虽然你可以编写一些*工作*但它会在某些时候将软件开发转变为成本中心,你将陷入维护困境.所以,是的,指标不会产生良好的代码,但它们确实表明了.即使是臭名昭着的代码行也表明你的团队每月可以输出多少.
不,但是,如果我说,具有可塑性的问题,将一个任意百分比分配给一个问题就不会是谨慎的.问题的"合理"部分似乎是主观的.
许多人不是跟随绝对代码覆盖百分比,而是跟踪随时间的变化.假设你有20%的测试覆盖率.虽然这个数字当时可能会或可能不会令人满意,但如果数字向下变化,则会引发有关代码质量的问题.
"吸食热绿茶"(可以说)是不可饮用的,味道很苦.温度至关重要.http://www.thefragrantleaf.com/green-tea-brewing-tips
故事的道德:80%!
我知道了,所以您认为除了“根据您的个人经历做出决定”之外,没有其他可以共享的有价值的信息吗?
我一生中“第一次”对代码进行了测试,发现我的测试并没有涵盖所有内容。我已经准备好测试属性的“设置”功能。我现在知道我不需要。
一个年轻的学生来到毕达哥拉斯。他问:“我有一个直角三角形,但我怎么知道最长边的长度呢?” 毕达哥拉斯非常聪明和冷静,他只是笑了。他宣称:“这我不能告诉你,因为它取决于三角形!”
@JonLimjap-有区别,也有共同点。一个共同点是,这两个问题都具有依赖性。在两种情况下回答“取决于”都是正确的。在这两种情况下,回答这些依赖关系是什么以及它们如何影响结果都是正确而完整的。
CC%与代码审查相得益彰.不要让垃圾测试.作为评论者,您应该首先查看测试,看看代码应该做什么.从那里你可以判断代码.如果我不得不说我会说这个关于CC%(直接来自我的屁股的数字)30%,可能不太好.50%意味着你可能正在捕捉一些东西,你正在努力.75%好多了,这可能是一个很好的目标.90%非常酷,可能是一些腰部.100%你可能在作弊或你的报道插件坏了.

2> Gishu..:

如果100%覆盖率是您的目标(而不是对所有功能进行100%测试),则代码覆盖率是一种误导性指标.

你可以通过一次击中所有线来得到100%.但是,您仍然可能错过测试命中这些行的特定序列(逻辑路径).

您无法获得100%但仍测试了所有80%/ freq使用的代码路径.测试每个'抛出ExceptionTypeX'或类似的防御性编程守卫你测试的是'很高兴'而不是'必须拥有'

因此,请相信自己或您的开发人员要彻底,并通过他们的代码覆盖每条路径.务实,不要追逐神奇的100%报道.如果您使用TDD代码,则应获得90%以上的奖金.使用代码覆盖来突出显示您错过的代码块(如果您使用TDD,则不应该发生...因为您只编写代码以进行测试通过.没有合作伙伴测试,代码就不会存在.)


我不确定你的第二点是什么意思"但仍然测试了你所有的代码路径".如果你实际上意味着全路径覆盖,那么没有100%线路/分支/决策覆盖,你就不能拥有全路径覆盖.事实上,由于生成路径中分支的组合性质,在任何非平凡的程序中通常无法获得全路径覆盖.http://en.wikipedia.org/wiki/Code_coverage#Other_coverage_criteria
- 异常 - 如果你不测试你的异常处理,你怎么知道你的代码在发生这种情况时不会爆炸? - Setters/Getters - 我认为上下文敏感,但是你的测试肯定应该作为测试套件的一部分执行它们,如果不是,它们实际上是在使用它们吗?
您不会测试每个可能的异常; 当然你不能这样做.您应该旨在测试处理异常的每个代码块.例如,如果您要求在块X引发异常时,在数据库中记录异常,则屏幕底部的绿色条纹变为红色,并向教皇发送电子邮件; 那就是你应该测试的.但是您不必测试可能触发这些事件的每个可能的异常.
+1"使用代码覆盖率来突出显示您错过的代码块".这基本上是指标的好处.

3> tofi9..:

代码覆盖率很高,但功能覆盖率更高.我不相信我写的每一行.但我确实相信我想要提供的所有功能的100%测试覆盖率(即使是我自己带来的超酷功能,也没有在会议期间讨论过).

我不在乎我是否会有测试中没有涉及的代码,但我会关心我是否会重构我的代码并最终有不同的行为.因此,100%的功能覆盖是我唯一的目标.


如果您可以提供所有功能而无需遵守所有代码行,那么那些额外的代码行在那里做什么?
这是一个很棒的答案.满足其要求的代码比满足某些任意LoC覆盖度量标准的代码更有价值.
@JensTimmerman理论上你是对的.但是,100%的代码覆盖率在时间上过于昂贵,并且迫使我的团队这样做不仅使他们失去动力,而且还使我的项目在截止日期前运行.我喜欢在中间的某个地方,测试功能(称之为:集成测试)是我感觉舒服的.我不测试什么代码?技术异常处理,(范围/参数)检查可能需要.简而言之,我学到的所有技术管道都是根据我自己的经验或我读到的最佳实践来应用的.
我通过列出应该包括在测试中或排除在测试之外的常见情况,使这一步骤更进一步。这样,我们就永远不会追求某个百分比,而要覆盖所有功能代码库的功能。

4> killscreen..:

接受的答案提出了一个很好的观点 - 没有一个数字作为每个项目的标准都有意义.有些项目不需要这样的标准.在我看来,接受的答案不足之处在于描述如何为特定项目做出决定.

我会这样做.我不是测试工程专家,很乐意看到更明智的答案.

何时设置代码覆盖要求

首先,你为什么要首先强加这样一个标准?一般来说,当你想在你的过程中引入经验信心时."经验信心"是什么意思?那么,真正的目标正确性.对于大多数软件,我们不可能在所有输入中知道这一点,因此我们决定说代码经过充分测试.这是更容易理解的,但仍然是一个主观标准:无论你是否遇到它,总是可以辩论.这些辩论是有用的,应该发生,但它们也暴露了不确定性.

代码覆盖率是一个客观的衡量标准:一旦您看到您的覆盖率报告,就没有关于标准是否有用的歧​​义.它证明是正确的吗?完全没有,但它与代码的良好测试有明确的关系,这反过来又是我们提高其正确性信心的最佳方式.代码覆盖率是我们关心的不可估量的质量的可测量近似值.

具有经验标准的一些特定情况可以增加价值:

满足利益相关者.对于许多项目,有许多对软件质量感兴趣的参与者可能不参与软件的日常开发(经理,技术主管等).说"我们要写所有的我们真正需要的测试"并不令人信服:他们要么需要完全信任,要么通过持续的密切监督来验证(假设他们甚至有技术理解这样做.)提供可衡量的标准并解释他们如何合理地接近实际目标更好.

规范团队行为.除了利益相关者之外,如果您正在一个多人编写代码和测试的团队中工作,那么对于"经过充分测试"的资格,存在模糊性的空间.您的所有同事对于什么级别的测试足够好有同样的想法吗?可能不是.你如何调和这个?找到一个您可以同意的指标,并将其作为合理的近似值接受.这在大型团队中尤其(但并非唯一)有用,例如,潜在客户可能无法直接监督初级开发人员.信任网络也很重要,但如果没有客观的衡量标准,即使每个人都善意地行事,集体行为也很容易变得不一致.

保持诚实.即使您是项目的唯一开发者和唯一的利益相关者,您也可能对软件有一定的品质.您可以使用代码覆盖率作为合理的近似值,让机器为您量身定做,而不是对软件的测试结果进行持续的主观评估(这需要工作).

要使用哪些指标

代码覆盖率不是单一指标; 有几种不同的测量覆盖率的方法.您可以设置哪一个标准取决于您使用该标准满足的要求.

我将使用两个常用指标作为您何时可以使用它们来设置标准的示例:

声明范围:测试期间执行了多少百分比的声明?有助于了解代码的物理覆盖范围:我编写了多少代码,我实际测试过了?

这种覆盖支持较弱的正确性参数,但也更容易实现.如果你只是使用的代码覆盖,以确保件事得到测试(而不是测试质量的超出了一个指标),那么语句覆盖可能就足够了.

分支覆盖:当存在分支逻辑(例如,a if)时,是否已对两个分支进行评估?这样可以更好地了解代码的逻辑覆盖范围:我测试过代码可能采用的路径有多少?

这种覆盖范围是一个更好的指标,表明程序已在一系列综合输入中进行了测试.如果您使用代码覆盖率作为正确性置信度的最佳经验近似值,则应根据分支覆盖率或类似情况设置标准.

还有许多其他指标(行覆盖类似于语句覆盖,但是对于多行语句产生不同的数字结果;条件覆盖和路径覆盖类似于分支覆盖,但反映了更详细的可能排列的视图你可能遇到的程序执行.)

要求的百分比

最后,回到最初的问题:如果设置代码覆盖率标准,该数字应该是多少?

希望在这一点上很清楚我们正在谈论一个开始的近似,所以我们选择的任何数字都将是固有的近似值.

一些人可能选择的数字:

100%.您可以选择此选项,因为您希望确保所有内容都经过测试.这并没有给你任何关于测试质量的见解,但确实告诉你一些质量的测试已触及每个声明(或分支等).再次,这回到了信心程度:如果你的覆盖率低于100% ,您知道您的代码的某些子集未经测试.

有些人可能认为这很愚蠢,你应该只测试代码中非常重要的部分.我认为你应该只维护代码中非常重要的部分.通过删除未经测试的代码也可以改善代码覆盖率.

99%(或95%,九十年代以来的其他数字.)适用于你想表达类似于 100%的置信水平的情况,但留下一些余地,不要担心偶尔难以测试的角落码.

80%.我已经看过几次这个号码,并不完全知道它的来源.我认为这可能是对80-20规则的一种奇怪的挪用; 通常,这里的目的是表明您的大多数代码都经过了测试.(是的,51%也会"最",但80%更能反映大多数人的意思.)这适用于"经过良好测试"不是高优先级的中间地区(你不喜欢)我想浪费在低价值测试上的努力),但是你仍然希望有一些标准.

我在实践中没有看到低于80%的数字,并且很难想象一个人会设置它们的情况.这些标准的作用是增加对正确性的信心,低于80%的数字并不是特别值得信赖.(是的,这是主观的,但同样,我们的想法是在设定标准时进行一次主观选择,然后再使用客观测量.)

其他说明

以上假设正确性是目标.代码覆盖仅仅是信息; 它可能与其他目标相关.例如,如果您担心可维护性,您可能会关心松耦合,这可以通过可测试性来证明,而可测试性又可以通过代码覆盖来测量(以某些方式).因此,您的代码覆盖率标准也为近似"可维护性"的质量提供了经验基础.


好答案。它是唯一在工业环境中将测试作为团队问题进行测试的解决方案。我没有审查所有内容,我的团队非常聪明,但是绿色。我将一个新项目的最低百分比设置为90%,作为初级开发人员的健全性检查,并不是因为我认为它“足够”。“ 90%”和“肯定,否定和无效”对于聪明的年轻开发人员来说是简单的口头禅,我知道他们会做得很好,但是没有经验继续编写多余的测试用例在你的脑后。

5> Eponymous..:

我最喜欢的代码覆盖率为100%带星号.星号是因为我更喜欢使用允许我将某些行标记为"不计数"的行的工具.如果我已经覆盖了100%的"计数"线,我就完成了.

基本过程是:

    我编写测试来练习我能想到的所有功能和边缘情况(通常使用文档).

    我运行代码覆盖工具

    我检查未覆盖的任何线路或路径以及我认为不重要或无法到达的任何线路或路径(由于防御性编程)我标记为不计

    如果没有提到这些边缘情况,我会编写新的测试来覆盖缺失的行并改进文档.

这样,如果我和我的合作者在未来添加新代码或更改测试,有一条明确的线路告诉我们,如果我们错过了重要的事情 - 覆盖率降至100%以下.但是,它还提供了处理不同测试优先级的灵活性.


@ErikE Asterix当然是来自高卢的一个短而无畏的战士,他为单调的罗马占领创造了例外,因此标记异常的小印刷符号以他的名字命名.(更严重的是,谢谢,我已经解决了拼写错误.)
您是否愿意包含"允许[您]将某些行标记为不计数行的工具"?
@domdambrogia作为PHP中的一个例子,如果使用Bergmann的代码覆盖库,用[`// codeCoverageIgnore`]注释一行(https://github.com/sebastianbergmann/php-code-coverage/blob/master/src/ CodeCoverage.php#L691)并且它将被排除在覆盖范围之外.

6> Jon Limjap..:

我还有另外一个关于我想分享的测试报道的模式.

我们有一个庞大的项目,通过twitter,我注意到,通过700次单元测试,我们只有20%的代码覆盖率.

斯科特汉塞尔曼用智慧的话回答道:

它是正确的20%?是否代表用户最受欢迎的代码的20%?您可以添加50多个测试,仅添加2%.

再次,它可以追溯到我的Testivus代码覆盖率答案.你应该在锅里放多少米饭?这取决于.


它的用处更多……您的覆盖范围是花在应用程序的核心功能上,还是无用地测试琐碎的功能/必备功能?

7> Martin G..:

对于一个设计良好的系统,单元测试从一开始就推动了开发,我认为85%是一个非常低的数字.设计为可测试的小班不应该难以覆盖.

通过以下方式解决这个问题很容易:

覆盖的线不等于测试逻辑,不应该读取百分比太多.

没错,但是有一些关于代码覆盖的要点.根据我的经验,如果使用正确,这个指标实际上非常有用.话虽如此,我还没有看到所有系统,我敢肯定有很多系统很难看到代码覆盖率分析增加任何实际价值.代码看起来如此不同,可用测试框架的范围可能会有所不同.

此外,我的推理主要涉及非常短的测试反馈循环.对于我正在开发的产品,最短的反馈回路非常灵活,涵盖了从类测试到进程间信令的所有内容.测试可交付的子产品通常需要5分钟,对于如此短的反馈循环,确实可以使用测试结果(特别是我们在此处查看的代码覆盖率指标)来拒绝或接受存储库中的提交.

使用代码覆盖率指标时,您不应仅具有必须满足的固定(任意)百分比.在我看来,这样做并没有给你代码覆盖率分析的真正好处.而是定义以下指标:

低水位标记(LWM),在被测系统中见过的最低数量的未覆盖线

高水位标记(HWM),是被测系统中有史以来最高的代码覆盖百分比

如果我们不超过LWM并且我们不低于HWM,则只能添加新代码.换句话说,不允许代码覆盖率降低,并且应该涵盖新代码.请注意我应该说和不应该(在下面解释).

但是,这是不是意味着不可能清除那些你再也没用过的旧的经过严格测试的垃圾了?是的,这就是为什么你必须对这些事情务实.在某些情况下,规则必须被打破,但对于典型的日常集成,我体验到这些指标非常有用.它们给出了以下两个含义.

推广可测试代码.添加新代码时,您必须努力使代码可测试,因为您必须尝试用测试用例覆盖所有代码.可测试代码通常是件好事.

遗留代码的测试范围随着时间的推移而增加.当添加新代码而无法用测试用例覆盖它时,可以尝试覆盖一些遗留代码,而不是绕过LWM规则.这种有时必要的作弊至少给出了积极的副作用,遗留代码的覆盖范围将随着时间的推移而增加,使得这些规则的看似严格的执行在实践中非常实用.

而且,如果反馈循环太长,在集成过程中设置这样的东西可能完全不切实际.

我还想提一下代码覆盖率指标的两个更广泛的好处.

代码覆盖率分析是动态代码分析的一部分(与静态代码分析相对,即Lint).在动态代码分析过程中发现的问题(通过purify系列等工具,http://www-03.ibm.com/software/products/en/rational-purify-family)就像未初始化的内存读取(UMR),内存泄漏等只有在执行的测试用例涵盖代码时才能找到这些问题.在测试用例中最难覆盖的代码通常是系统中的异常情况,但如果您希望系统正常失败(即错误跟踪而不是崩溃),您可能需要付出一些努力来覆盖异常情况在动态代码分析中也是如此.只是运气不好,UMR会导致段错或更糟.

人们为保持100%的新代码而感到自豪,人们讨论测试问题的热情与其他实现问题类似.如何以更可测试的方式编写此函数?你将如何试图掩盖这种异常情况等.

而且是否定的,完整性.

在一个涉及许多开发人员的大型项目中,每个人都不会成为测试天才.有些人倾向于使用代码覆盖率指标作为代码测试的证据,这与事实相差甚远,正如许多其他问题的答案所述.如果使用得当,它是一个可以为您提供一些好处的指标,但如果它被滥用,它实际上可能导致不良测试.除了上面提到的非常有价值的副作用之外,覆盖线仅显示被测系统可以达到某些输入数据的那一行,并且它可以在不挂起或崩溃的情况下执行.



8> 64BitBob..:

如果这是一个完美的世界,100%的代码将由单元测试覆盖.然而,由于这不是一个完美的世界,这是你有时间的问题.因此,我建议减少对特定百分比的关注,并更多地关注关键领域.如果您的代码编写得很好(或至少是合理的传真),那么API应该有几个关键点,其中API会暴露给其他代码.

将测试工作集中在这些API上.确保API 1)记录良好,2)编写与文档匹配的测试用例.如果预期结果与文档不匹配,那么您的代码,文档或测试用例中都存在错误.所有这些都很好地审查.

祝好运!



9> Greg Trevell..:

很多商店都没有重视测试,所以如果你的价格高于零,至少会有一些价值升值 - 所以可以说非零也不错,因为许多商店仍然为零.

在.Net世界,人们经常引用80%的合理性.但是他们在解决方案层面说这个.我更倾向于在项目级别进行测量:如果您有Selenium等或者手动测试,30%可能适用于UI项目,数据层项目的20%可能没问题,但95%+可能对业务来说非常可行规则层,如果不是完全必要的话.因此,总体覆盖率可能是60%,但关键业务逻辑可能要高得多.

我也听过这个:渴望100%,你会达到80%; 但渴望80%,你会达到40%.

底线:应用80:20规则,让您的应用程序的错误计数指导您.



10> stephbu..:

85%将是签入标准的良好起点.

我可能会根据运输标准选择各种更高的标准 - 取决于被测试的子系统/组件的重要性.


你是怎么得到那个百分比的?
主要是通过实验.对于与Dev相关的单元测试,代码覆盖率很容易达到80-90% - 更高通常需要神圣的测试干预 - 或者非常简单的代码路径.
推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有