我刚开始使用 PHPUnit 及其丰富多彩的代码覆盖报告。我知道所有的数字和百分比,除了一个: C.R.A.P 指数。有人能给我一个可靠的解释,它意味着什么,如何分析它,如何降低它?
Basically it wants to be a predictor of the risk of change for a method.
它有两个因素:
cyclomatic complexity
comp(m)
如果该方法具有100% 的覆盖率,那么变更的风险被认为仅与该方法的复杂度相当: C.R.A.P.(m) = comp(m)。
C.R.A.P.(m) = comp(m)
如果方法覆盖率为0% ,那么在复杂度度量中,更改的风险被认为是二次多项式(理由是,如果你不能测试一个改变了的代码路径,那么破坏的风险就会增加) : C.R.A.P.(m) = comp(m)^2 + comp(m)
C.R.A.P.(m) = comp(m)^2 + comp(m)
Hopefully this will help you.
我只是注意到我只提供了一半的答案(阅读部分)。如果你理解了索引的原理,那么改进的方法应该是非常清楚的。但是 @edorian's answer给出了一个更加清晰的解释。
简单来说就是: 编写测试,直到覆盖率接近100% ,然后重构方法以减少循环复杂度。您可以在进行测试之前尝试重构,但是根据实际方法的复杂程度,如果您不能推断(由于所涉及的复杂程度)您正在进行的更改的所有后果,您可能会引入破坏。
@ Toader Mihai 给出了一个可靠的解释。 (+ 1 from me)
编写不太复杂的代码或者编写更好的测试代码
更好的测试代码?
在这种情况下,这仅仅意味着: 更高的代码覆盖率,并且通常会导致编写更多的测试。
更简单的代码?
例如: 将你的方法重构成更小的方法:
// Complex function doSomething() { if($a) { if($b) { } if($c) { } } else { if($b) { } if($c) { } } } // 3 less complex functions function doSomething() { if($a) { doA(); } else { doNotA(); } } function doA() { if($b) { } if($c) { } } function doNotA() { if($b) { } if($c) { } }
(只是一个小例子,你会发现更多的资源,我敢肯定)
首先,让我提供一些额外的资源:
创建者关于垃圾索引的博客文章
以防万一: 循环复杂度解释道.PHP _ CodeSniffer 和 PHPMD 等工具会告诉你这个数字,以防你想知道。
And while it is for you to decide what number is "ok" one often suggested number (that is a litte high imho) is a crap index of 30 resulting in a Graph like this:
(You can get the .ods file here: https://www.dropbox.com/s/3bihb9thlp2fyg8/crap.ods?dl=1 )