在繁重的jquery / backbonejs Web应用程序中期望100%的代码覆盖率是否可行?当实际代码覆盖率在javascript / jquery中徘徊在92%-95%左右时,由于未达到100%覆盖率而导致冲刺失败是否合理?
在繁重的jquery / backbonejs Web应用程序中期望100%的代码覆盖率是否可行?当实际代码覆盖率在javascript / jquery中徘徊在92%-95%左右时,由于未达到100%覆盖率而导致冲刺失败是否合理?
Answers:
这既是现实的也是不现实的。
现实
如果您已经证明自动化测试可以覆盖整个代码库,那么坚持100%的覆盖率是合理的。
这也取决于项目的重要性。越关键,期望/要求完整的代码覆盖范围就越合理。
对于中小型项目,这样做更容易。
不切实际
您从0%的覆盖率开始...
该项目异常复杂,包含许多难以重新创建或触发的错误路径。
管理层不愿意承诺/投资以确保覆盖范围。
我从事的项目范围从无覆盖到体面。从来没有一个100%的项目,但是我有时候确实希望我们能接近100%。
最终,问题是现有的覆盖范围是否满足团队所需的足够情况,以使团队能够轻松地运输产品。
我们不知道失败对项目的影响,因此我们不能说92%或95%是否足够,还是真的需要100%。或就此而言,100%会完全测试您期望的一切。
即使从理论上讲,它充其量也是非常幼稚的和不现实的,而在业务上则是不切实际的。
编写测试非常昂贵,必须编写代码并对其进行自我测试,必须在其实际尝试测试的内容中记录这些代码,必须通过业务逻辑更改来维护该代码,并且测试失败,因为它们已过时。维护自动化测试和有关它们的文档可能比维护代码有时更昂贵。
这并不是说单元测试和集成测试没有用,而是仅在有意义的地方使用,而在可以杀死人员的行业之外,尝试测试代码库中的每一行代码都没有意义。在这些致命的杀伤力之外,很多人会快速编写代码库,因此无法计算出100%代码覆盖率所带来的正投资回报。
在可计算性理论中,停顿问题是根据任意计算机程序的描述和输入确定程序将结束运行还是继续永久运行的问题。
艾伦·图灵(Alan Turing)在1936年证明,不存在解决所有可能的程序输入对的停止问题的通用算法。证明的关键部分是计算机和程序的数学定义,这被称为图灵机。在图灵机上无法停止问题。这是决策问题的第一个例子。
既然您甚至无法证明某事有效100%,为什么要实现目标?
getXXX()/setXXX()
值对象的简单或简单的赋值构造函数是对时间和资源的良好利用,很遗憾,事实并非如此,这是一种非常幼稚的观点,缺乏现实世界的经验来进行备份。请记住,测试代码仍然是必须维护的代码。在每种情况下,编写用于解决问题的代码越少越好。
在大多数情况下,100%的代码覆盖率意味着您已经“作弊”了一点:
基本上,难于测试的部件已被转移到不一定被视为“代码”的区域。这并不总是现实的,但是请注意,所有这些实践都独立于帮助您进行测试之外,使您的代码库更易于使用。
有关真实的100%分支覆盖率示例,请参见如何测试SQLite。
我意识到您的问题专门询问了JavaScript,这是一种完全不同类型的软件产品,但是我想让人们意识到在有足够动机的情况下可以做什么。
即使对于新项目,对于特定应用程序所有部分的单元测试,100%的代码覆盖率也是梦dream以求的。我希望是这样,但是有时候,无论您多么努力地提取外部依赖关系,您都无法覆盖一段代码。例如,假设您的代码必须调用Web服务。您可以将Web服务调用隐藏在界面后面,以便可以模拟该部分,并测试Web服务之前和之后的业务逻辑。但是需要调用Web服务的实际部分不能进行单元测试(无论如何都很好)。另一个示例是是否需要连接到TCP服务器。您可以隐藏连接到接口后面的TCP服务器的代码。但是物理连接到TCP服务器的代码无法进行单元测试,因为如果由于某种原因它关闭了,那将导致单元测试失败。而且,无论何时调用单元测试,都应始终通过。
一个好的经验法则是,您所有的业务逻辑都应具有100%的代码覆盖率。但是必须调用外部组件的部分,它应该具有尽可能接近100%的代码覆盖率。如果您无法到达,那我就不会流汗。
更重要的是,测试是否正确?它们是否准确反映了您的业务和要求?如果您所做的只是测试不正确或测试代码不正确,那么仅具有代码覆盖率就没有任何意义。话虽这么说,如果您的测试很好,那么覆盖率达到92-95%是杰出的。
我要说的是,除非代码的设计目标是允许100%的测试覆盖率,否则100%可能无法实现。原因之一是,如果您进行防御性编码(应该这样做),则有时应使用能处理某些情况的代码,这些情况在您对系统有所了解的情况下就确定不会发生或不会发生。从定义上讲,要用测试覆盖这样的代码将非常困难。没有这样的代码可能很危险-如果您输入错了并且这种情况确实发生了256次,该怎么办?如果不相关的地方发生变化而使不可能的事情变为可能怎么办?等等,因此100%可能很难通过“自然”的方式达到-例如,如果您有分配内存的代码并且您有检查其是否失败的代码,除非您嘲笑了内存管理器(这可能不容易)并编写一个返回“内存不足”的测试,以覆盖该代码可能很困难。对于JS应用程序,它可能是围绕不同浏览器中可能出现的DOM怪癖,外部服务的可能失败等的防御性编码。
因此,我要说的是,我们应该争取尽可能地接近100%,并且有充分的理由来解释差异,但我认为未必会因为失败而无法准确地获得100%的收益。95%可以在大型项目中很好,取决于5%。
如果您是从一个新项目开始的,并且严格使用测试优先的方法,那么完全100%的代码覆盖率是完全合理的,因为在测试完成后某个时刻所有代码都将被调用被执行。但是,由于方法的可见性,您可能未直接对每种方法或算法进行显式测试,并且在某些情况下,甚至可能没有间接测试某些方法。
对100%的代码进行测试可能是一项代价高昂的工作,特别是如果您尚未设计允许您实现此目标的系统,并且如果您将设计工作重点放在可测试性上,那么您可能没有给予足够的关注设计应用程序以满足其特定要求,特别是在项目规模较大的情况下。对不起,但是您不能在没有任何妥协的情况下同时使用这两种方法。
如果将测试引入到以前从未维护过或未进行过测试的现有项目中,那么如果不付出成本来付出努力,就不可能获得100%的代码覆盖率。您可以期望的最好的结果就是提供对代码最关键部分的测试覆盖率。
当实际代码覆盖率在javascript / jquery中徘徊在92%-95%左右时,由于未达到100%覆盖率而导致冲刺失败是否合理?
在大多数情况下,我想说的是,如果您没有达到目标,则应该只将冲刺视为“失败”。实际上,我不希望将sprint视为失败,因为在下一次定义sprint时,为了使您的计划正确,您需要能够从不符合期望的sprint中学习。无论如何,我认为将代码覆盖率作为sprint相对成功的一个因素是不合理的。您的目标应该是做足够的工作以使所有功能都按指定的方式工作,如果您是测试优先的编码人员,那么您应该能够确信自己的测试将支持此目标。您认为可能需要添加的任何其他测试实际上都是糖衣,因此会增加费用,使您无法满意地完成冲刺。
我当然不会这样做,但是我已经在两个大型项目中做到了。如果您已经建立了一个用于单元测试的框架,这并不难,但是它确实可以进行很多测试。
您是否遇到一些特殊的障碍,阻止您达到最后几行?如果不是这样,那么从95%覆盖到100%覆盖率很简单,那么您最好去做。既然你在这里问,我会认为有是什么。那是什么东西
92%可以。我认为真正的问题是:
现在有92%是“新”规范吗?如果下一个Sprint进行了88%的测试,那可以吗?这通常是放弃测试套件的开始。
该软件有效且没有错误的重要性。您出于这些原因进行测试,而不是“出于测试目的”
是否有计划返回并填写缺失的测试?
你为什么要测试?似乎重点是线路覆盖的百分比而不是功能
马丁·福勒(Martin Fowler)在他的博客中写道:I would be suspicious of anything like 100% - it would smell of someone writing tests to make the coverage numbers happy, but not thinking about what they are doing.
但是,甚至有一些标准要求在单位级别100%覆盖。例如,这是欧洲航天界标准(ECSS,欧洲空间标准化合作组织)的要求之一。此处链接的论文讲述了一个有趣的项目故事,该项目的目标是在已经完成的软件中达到100%的测试覆盖率。它基于与开发单元测试的相关工程师的意见。
一些课程是:
也许问问是否可行和合理并不是要问的最有帮助的问题。可能最实用的答案是已接受的答案。我将在更哲学的层面上对此进行分析。
100%的覆盖率是理想的,但是理想情况下,它不是必需的,或者更容易实现。我宁愿考虑它是否自然和人性,而不是可行或合理的。
使用当今的工具几乎无法实现正确编程的作用。编写完全正确且没有错误的代码非常困难。这只是不自然的。因此,在没有其他明显选择的情况下,我们将转向TDD和跟踪代码覆盖率之类的技术。但是,只要最终结果仍然是不自然的过程,您将很难使人们始终如一地快乐地去做。
实现100%的代码覆盖率是不自然的。对于大多数人来说,强迫他们做到这一点将是一种折磨。
我们需要能够映射到我们自然思维模型的流程,工具,语言和代码。如果我们做不到这一点,就无法测试产品的质量。
只需看看今天的所有软件即可。其中大多数都非常定期地混乱。我们不想相信这一点。我们想相信我们的技术是神奇的,并使我们感到高兴。因此,在大多数情况下,我们选择忽略,原谅和忘记我们的技术。但是,如果我们对事情做一个诚实的评估,那么今天的大多数软件都是糟糕透顶的。
以下是使编码更自然的一些努力:
https://github.com/jcoplien/trygve
https://github.com/still-dreaming-1/PurposefulPhp
后者是极其不完整和实验性的。实际上,这是我开始的一个项目,但是我相信,如果我能够花时间去完成它,那对编程技术将是一个巨大的进步。基本上是这样一种想法,即如果合同只表达我们关心的类行为的各个方面,并且我们已经将合同表达为代码,那么为什么不仅要在合同中同时包含类和方法定义。这样,合同就是代码,我们不需要实现所有方法。让图书馆弄清楚如何为我们履行合同。
在新代码上达到100%应该是可以实现的,并且如果您正在练习TDD,则很可能默认情况下会达到目标,因为您非常刻意为生产代码的每一行编写测试。
在没有单元测试的情况下编写的现有遗留代码上可能会很困难,因为遗留代码通常不是在考虑单元测试的情况下编写的,并且可能需要大量重构。鉴于风险和时间表的现实性,这种级别的重构通常不切实际,因此您需要权衡取舍。
在我的团队中,我指定100%的代码覆盖率,并且如果我们发现少于代码审查中的代码覆盖率,则该组件的技术所有者讨论为什么未与开发人员达成100%的覆盖率,并且必须与开发人员的推理保持一致。通常情况下,如果遇到100%问题,开发人员会在代码审查之前与技术所有者联系。我们发现,一旦养成习惯并学习解决一些常见问题的技术,即向遗留代码中添加定期定期命中100%的测试并不像您最初想象的那样困难。
迈克尔·费瑟(Michael Feather)的书“ 有效地使用旧版代码 ”对于我们提出将测试添加到旧版代码中的策略来说,对我们来说是无价的。
不,这是不可能的,而且永远不会。如果有可能,所有的数学都将陷入有限主义。例如,如何测试一个接受两个64位整数并将它们相乘的函数?测试和证明程序正确始终是我的问题。对于除最琐碎的程序以外的任何程序,测试基本上是无用的,因为它仅覆盖少数情况。这就像检查1,000个数字并说您已经证明了哥德巴赫猜想。