如果我有一些代码具有80%的测试覆盖率(所有测试均通过),是否可以说它比没有测试覆盖率的代码具有更高的质量?
还是公平地说它更易于维护?
如果我有一些代码具有80%的测试覆盖率(所有测试均通过),是否可以说它比没有测试覆盖率的代码具有更高的质量?
还是公平地说它更易于维护?
Answers:
从严格意义上讲,在确定测试套件的质量之前,不主张任何权利是不公平的。如果大多数测试相互无关紧要,那么通过100%的测试就没有意义。
问题是:在项目的历史中,这些测试中有没有发现bug?测试的目的是发现错误。如果没有,他们将无法通过测试。他们可能只会给您一种错误的安全感,而不是提高代码质量。
为了改善测试设计,您可以使用(1)白盒技术,(2)黑盒技术和(3)变异测试。
(1)以下是一些适用于您的测试设计的优秀白盒技术。白盒测试是在考虑特定源代码的情况下构建的。白盒测试的一个重要方面是代码覆盖率:
if
或while
),您是否有一个测试将其强制为真,而其他测试将其强制为假?[决定范围]&&
)或析取(uses ||
)的条件,每个子表达式是否都有对真/假的检验?[条件报道]break
循环都覆盖了吗?(2)当需求可用时使用黑盒技术,但代码本身不可用。这些可以导致高质量的测试:
(3)最后,假设您已经对白盒覆盖率进行了许多不错的测试,并应用了黑盒技术。你还能做什么?现在该测试您的测试了。可以使用的一种技术是变异测试。
在变异测试下,您希望对程序进行修改(以作为副本),以期创建一个错误。突变可能是:
将一个变量的引用更改为另一个变量;插入abs()函数;从小于变为大于;删除声明;用常量替换变量;删除覆盖方法;删除对超级方法的引用;更改参数顺序
在程序的各个位置创建数十个变体(程序仍需要编译才能进行测试)。如果您的测试没有找到这些错误,那么您现在需要编写一个可以在程序的变异版本中找到该错误的测试。一旦测试发现错误,就可以杀死该突变体并尝试其他突变体。
附录:我忘了提到这种效果:Bug容易聚集。这意味着在一个模块中发现的错误越多,发现更多错误的可能性就越高。因此,如果您的测试失败(也就是说,测试是成功的,因为目标是发现错误),则不仅应该修复该错误,还应该使用来为该模块编写更多测试。以上技术。
只要您以稳定的速度发现错误,就必须继续进行测试。仅当发现的新错误率下降时,您才有信心在该开发阶段进行了出色的测试。
完全没有测试的代码可以具有极高的质量,可读性,美观和高效(或完全垃圾),因此,不能说具有80%测试覆盖率的代码比没有测试覆盖率的代码具有更高的质量。
可以公平地说,覆盖80%良好测试的代码可能具有可接受的质量,并且可能相对可维护。但这确实不能保证。
我将其称为可重构的。如果代码包含大量测试,则重构将变得非常容易。
称其更具可维护性是公平的。
我同意可维护部分。迈克尔·费瑟斯(Michael Feathers)最近发布了一段录像,讲述了他关于“ 可测试性和良好设计之间的深层协同作用 ”的精彩演讲,他在其中讨论了这一主题。他在谈话中说,这种关系是一种方式,即设计良好的代码是可测试的,但是可测试的代码不一定是设计良好的。
值得注意的是,视频流在视频中并不是很好,因此,如果您想完整观看,可能值得下载。
一段时间以来,我一直在问自己这个与“条件覆盖”有关的问题。那么来自atollic.com的此页面“为什么进行代码覆盖率分析”呢?
从技术上讲,代码覆盖率分析可以找到程序中未包含在测试用例中的区域,从而使您可以创建其他测试,以覆盖程序中未经测试的部分。因此,重要的是要了解代码覆盖率可以帮助您了解测试过程的质量,而不是代码本身的质量。
这似乎在这里很相关。如果您的测试用例集能够达到一定水平的(代码或其他)覆盖率,那么很可能会用相当详尽的一组输入值来调用被测代码!这不会告诉您更多有关被测代码的信息(除非代码崩溃或产生可检测的错误),但是可以使您对测试用例集充满信心。
在一个有趣的Necker Cube变更视图中,测试代码现在正在由被测试代码进行测试!
有很多方法可以保证程序能够实现您的预期效果,并确保修改不会产生意想不到的效果。
测试是其中之一。避免数据突变是另一种方法。类型系统也是如此。或正式验证。
因此,尽管我同意测试通常是一件好事,但一定比例的测试可能意义不大。我宁愿依赖Haskell编写的未经测试的内容,也不愿依赖经过良好测试的PHP库