【发布时间】:2011-06-11 12:47:35
【问题描述】:
我刚开始使用 PHPUnit 及其丰富多彩的代码覆盖率报告。我理解所有的数字和百分比,除了一个:C.R.A.P 指数。谁能给我一个可靠的解释,说明它的含义,如何分析它以及如何降低它?
【问题讨论】:
标签: php unit-testing phpunit
我刚开始使用 PHPUnit 及其丰富多彩的代码覆盖率报告。我理解所有的数字和百分比,除了一个:C.R.A.P 指数。谁能给我一个可靠的解释,说明它的含义,如何分析它以及如何降低它?
【问题讨论】:
标签: php unit-testing phpunit
基本上,它希望成为一种方法变更风险的预测器。
它有两个因素:
cyclomatic complexity) 也就是所述方法中存在多少决策路径:comp(m)。如果方法具有 100% 的覆盖率,则认为变更风险仅与方法的复杂性相同:C.R.A.P.(m) = comp(m)。
如果方法的覆盖率为 0%,那么在复杂性度量中,变更风险被认为是二级多项式(原因是,如果您无法测试代码路径的变更,则会增加损坏风险):@987654325 @
希望这会对您有所帮助。
我刚刚注意到我只提供了一半的答案(阅读部分)。如果您了解索引的推理,如何改进它应该很清楚。但是@edorian's answer给出了更清晰的解释。
简短的故事是:编写测试直到覆盖率接近 100%,然后重构方法以降低圈复杂度。您可以在进行测试之前尝试重构,但根据实际方法的复杂性,如果您无法推理(因为涉及的复杂性)您所做的更改的所有后果,您可能会引入破坏。
【讨论】:
function example() { $dep = new Dependency(); return $dep->someFunction(); } 比function crappy($param) { switch ($param) { // 30 different cases with if-elses } } 更难测试(模拟逻辑可能很可怕,尤其是PHP)。
@Toader Mihai offered a solid explanation.(来自我的+1)
编写不太复杂的代码或编写更好的测试代码。 (见下图)
更好的测试代码?
在这种情况下,这只是意味着:更高的代码覆盖率,通常会导致编写更多的测试。
更简单的代码?
例如:将您的方法重构为更小的方法:
// 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) {
}
}
(只是一个简单的例子,我相信你会找到更多资源)
首先让我提供一些额外的资源:
Creators blog post about the crap index
以防万一:Cyclomatic complexity explained。如果您想知道,PHP_CodeSniffer 和 PHPMD 等工具会告诉您该数字。
虽然由您来决定什么数字是“好的”,但一个经常建议的数字(即有点高恕我直言)是 30 的废话索引,导致如下图:
(您可以在此处获取 .ods 文件:https://www.dropbox.com/s/3bihb9thlp2fyg8/crap.ods?dl=1)
【讨论】: