Skip to content

Commit befd680

Browse files
committed
Aggregates report
1 parent e0b02ae commit befd680

File tree

6 files changed

+204
-68
lines changed

6 files changed

+204
-68
lines changed

src/CodeCoverage.php

+1-4
Original file line numberDiff line numberDiff line change
@@ -603,10 +603,7 @@ private function initializeFilesThatAreSeenTheFirstTime(array $data)
603603
}
604604

605605
foreach ($functionData['paths'] as $path) {
606-
$this->data[$file]['paths'][$functionName][] = [
607-
'path' => $path['path'],
608-
'tests' => []
609-
];
606+
$this->data[$file]['paths'][$functionName][] = $path;
610607
}
611608
}
612609
}

src/CodeCoverage/Report/Node.php

+29
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,21 @@ public function getLineExecutedPercent($asString = true)
206206
);
207207
}
208208

209+
/**
210+
* Returns the percentage of executed paths.
211+
*
212+
* @param bool $asString
213+
* @return int
214+
*/
215+
public function getPathExecutedPercent($asString = true)
216+
{
217+
return PHP_CodeCoverage_Util::percent(
218+
$this->getNumExecutedPaths(),
219+
$this->getNumExecutablePaths(),
220+
$asString
221+
);
222+
}
223+
209224
/**
210225
* Returns the number of classes and traits.
211226
*
@@ -281,6 +296,20 @@ abstract public function getNumExecutableLines();
281296
*/
282297
abstract public function getNumExecutedLines();
283298

299+
/**
300+
* Returns the number of executable paths.
301+
*
302+
* @return int
303+
*/
304+
abstract public function getNumExecutablePaths();
305+
306+
/**
307+
* Returns the number of executed paths.
308+
*
309+
* @return int
310+
*/
311+
abstract public function getNumExecutedPaths();
312+
284313
/**
285314
* Returns the number of classes.
286315
*

src/CodeCoverage/Report/Node/Directory.php

+48
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ class PHP_CodeCoverage_Report_Node_Directory extends PHP_CodeCoverage_Report_Nod
6565
*/
6666
protected $numExecutedLines = -1;
6767

68+
/**
69+
* @var int
70+
*/
71+
protected $numExecutablePaths = -1;
72+
73+
/**
74+
* @var int
75+
*/
76+
protected $numExecutedPaths = -1;
77+
6878
/**
6979
* @var int
7080
*/
@@ -177,6 +187,8 @@ public function addFile($name, array $coverageData, array $testData, $cacheToken
177187

178188
$this->numExecutableLines = -1;
179189
$this->numExecutedLines = -1;
190+
$this->numExecutablePaths = -1;
191+
$this->numExecutedPaths = -1;
180192

181193
return $file;
182194
}
@@ -332,6 +344,42 @@ public function getNumExecutedLines()
332344
return $this->numExecutedLines;
333345
}
334346

347+
/**
348+
* Returns the number of executable paths.
349+
*
350+
* @return int
351+
*/
352+
public function getNumExecutablePaths()
353+
{
354+
if ($this->numExecutablePaths == -1) {
355+
$this->numExecutablePaths = 0;
356+
357+
foreach ($this->children as $child) {
358+
$this->numExecutablePaths += $child->getNumExecutablePaths();
359+
}
360+
}
361+
362+
return $this->numExecutablePaths;
363+
}
364+
365+
/**
366+
* Returns the number of executed paths.
367+
*
368+
* @return int
369+
*/
370+
public function getNumExecutedPaths()
371+
{
372+
if ($this->numExecutedPaths == -1) {
373+
$this->numExecutedPaths = 0;
374+
375+
foreach ($this->children as $child) {
376+
$this->numExecutedPaths += $child->getNumExecutedPaths();
377+
}
378+
}
379+
380+
return $this->numExecutedPaths;
381+
}
382+
335383
/**
336384
* Returns the number of classes.
337385
*

src/CodeCoverage/Report/Node/File.php

+111-59
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
3535
*/
3636
protected $numExecutedLines = 0;
3737

38+
/**
39+
* @var int
40+
*/
41+
protected $numExecutablePaths = 0;
42+
43+
/**
44+
* @var int
45+
*/
46+
protected $numExecutedPaths = 0;
47+
3848
/**
3949
* @var array
4050
*/
@@ -213,6 +223,26 @@ public function getNumExecutedLines()
213223
return $this->numExecutedLines;
214224
}
215225

226+
/**
227+
* Returns the number of executable paths.
228+
*
229+
* @return int
230+
*/
231+
public function getNumExecutablePaths()
232+
{
233+
return $this->numExecutablePaths;
234+
}
235+
236+
/**
237+
* Returns the number of executed paths.
238+
*
239+
* @return int
240+
*/
241+
public function getNumExecutedPaths()
242+
{
243+
return $this->numExecutedPaths;
244+
}
245+
216246
/**
217247
* Returns the number of classes.
218248
*
@@ -461,72 +491,25 @@ protected function calculateStatistics()
461491
}
462492
}
463493

464-
foreach ($this->traits as &$trait) {
465-
foreach ($trait['methods'] as &$method) {
466-
if ($method['executableLines'] > 0) {
467-
$method['coverage'] = ($method['executedLines'] /
468-
$method['executableLines']) * 100;
469-
} else {
470-
$method['coverage'] = 100;
471-
}
472-
473-
$method['crap'] = $this->crap(
474-
$method['ccn'],
475-
$method['coverage']
476-
);
494+
foreach ($this->functions as &$function) {
495+
if (isset($this->coverageData['paths'][$function['functionName']])) {
496+
$functionPaths = $this->coverageData['paths'][$function['functionName']];
497+
$this->calcPathsAggregate($functionPaths, $numExecutablePaths, $numExecutedPaths);
477498

478-
$trait['ccn'] += $method['ccn'];
479-
}
480-
481-
if ($trait['executableLines'] > 0) {
482-
$trait['coverage'] = ($trait['executedLines'] /
483-
$trait['executableLines']) * 100;
484-
} else {
485-
$trait['coverage'] = 100;
486-
}
499+
$function['executablePaths'] = $numExecutablePaths;
500+
$this->numExecutablePaths += $numExecutablePaths;
487501

488-
if ($trait['coverage'] == 100) {
489-
$this->numTestedClasses++;
502+
$function['executedPaths'] = $numExecutedPaths;
503+
$this->numExecutedPaths += $numExecutedPaths;
490504
}
505+
}
491506

492-
$trait['crap'] = $this->crap(
493-
$trait['ccn'],
494-
$trait['coverage']
495-
);
507+
foreach ($this->traits as &$trait) {
508+
$this->calcAndApplyClassAggregate($trait, $trait['traitName']);
496509
}
497510

498511
foreach ($this->classes as &$class) {
499-
foreach ($class['methods'] as &$method) {
500-
if ($method['executableLines'] > 0) {
501-
$method['coverage'] = ($method['executedLines'] /
502-
$method['executableLines']) * 100;
503-
} else {
504-
$method['coverage'] = 100;
505-
}
506-
507-
$method['crap'] = $this->crap(
508-
$method['ccn'],
509-
$method['coverage']
510-
);
511-
512-
$class['ccn'] += $method['ccn'];
513-
}
514-
515-
if ($class['executableLines'] > 0) {
516-
$class['coverage'] = ($class['executedLines'] /
517-
$class['executableLines']) * 100;
518-
} else {
519-
$class['coverage'] = 100;
520-
}
521-
522-
if ($class['coverage'] == 100) {
523-
$this->numTestedClasses++;
524-
}
525-
526-
$class['crap'] = $this->crap(
527-
$class['ccn'],
528-
$class['coverage']
529-
);
512+
$this->calcAndApplyClassAggregate($class, $class['className']);
530513
}
531514
}
532515

@@ -547,6 +530,8 @@ protected function processClasses(PHP_Token_Stream $tokens)
547530
'startLine' => $class['startLine'],
548531
'executableLines' => 0,
549532
'executedLines' => 0,
533+
'executablePaths' => 0,
534+
'executedPaths' => 0,
550535
'ccn' => 0,
551536
'coverage' => 0,
552537
'crap' => 0,
@@ -583,6 +568,8 @@ protected function processTraits(PHP_Token_Stream $tokens)
583568
'startLine' => $trait['startLine'],
584569
'executableLines' => 0,
585570
'executedLines' => 0,
571+
'executablePaths' => 0,
572+
'executedPaths' => 0,
586573
'ccn' => 0,
587574
'coverage' => 0,
588575
'crap' => 0,
@@ -619,6 +606,8 @@ protected function processFunctions(PHP_Token_Stream $tokens)
619606
'startLine' => $function['startLine'],
620607
'executableLines' => 0,
621608
'executedLines' => 0,
609+
'executablePaths' => 0,
610+
'executedPaths' => 0,
622611
'ccn' => $function['ccn'],
623612
'coverage' => 0,
624613
'crap' => 0,
@@ -672,10 +661,73 @@ private function newMethod($methodName, array $method, $link)
672661
'endLine' => $method['endLine'],
673662
'executableLines' => 0,
674663
'executedLines' => 0,
664+
'executablePaths' => 0,
665+
'executedPaths' => 0,
675666
'ccn' => $method['ccn'],
676667
'coverage' => 0,
677668
'crap' => 0,
678669
'link' => $link . $method['startLine'],
679670
];
680671
}
672+
673+
/**
674+
* @param string $paths
675+
* @param int $functionExecutablePaths
676+
* @param int $functionExecutedPaths
677+
*/
678+
private function calcPathsAggregate($paths, &$functionExecutablePaths, &$functionExecutedPaths)
679+
{
680+
$functionExecutablePaths = count($paths);
681+
$functionExecutedPaths = array_reduce(
682+
$paths,
683+
function ($carry, $value) {
684+
return ($value['hit'] > 0) ? $carry + 1 : $carry;
685+
},
686+
0
687+
);
688+
}
689+
690+
/**
691+
* @param array $classOrTrait
692+
* @param string $classOrTraitName
693+
*/
694+
protected function calcAndApplyClassAggregate(&$classOrTrait, $classOrTraitName)
695+
{
696+
foreach ($classOrTrait['methods'] as &$method) {
697+
$methodCoveragePath = $classOrTraitName . '->' . $method['methodName'];
698+
if (isset($this->coverageData['paths'][$methodCoveragePath])) {
699+
$methodPaths = $this->coverageData['paths'][$methodCoveragePath];
700+
$this->calcPathsAggregate($methodPaths, $numExecutablePaths, $numExecutedPaths);
701+
702+
$method['executablePaths'] = $numExecutablePaths;
703+
$classOrTrait['executablePaths'] += $numExecutablePaths;
704+
$this->numExecutablePaths += $numExecutablePaths;
705+
706+
$method['executedPaths'] = $numExecutedPaths;
707+
$classOrTrait['executedPaths'] += $numExecutedPaths;
708+
$this->numExecutedPaths += $numExecutedPaths;
709+
}
710+
if ($method['executableLines'] > 0) {
711+
$method['coverage'] = ($method['executedLines'] / $method['executableLines']) * 100;
712+
} else {
713+
$method['coverage'] = 100;
714+
}
715+
716+
$method['crap'] = $this->crap($method['ccn'], $method['coverage']);
717+
718+
$classOrTrait['ccn'] += $method['ccn'];
719+
}
720+
721+
if ($classOrTrait['executableLines'] > 0) {
722+
$classOrTrait['coverage'] = ($classOrTrait['executedLines'] / $classOrTrait['executableLines']) * 100;
723+
} else {
724+
$classOrTrait['coverage'] = 100;
725+
}
726+
727+
if ($classOrTrait['coverage'] == 100) {
728+
$this->numTestedClasses++;
729+
}
730+
731+
$classOrTrait['crap'] = $this->crap($classOrTrait['ccn'], $classOrTrait['coverage']);
732+
}
681733
}

tests/PHP/CodeCoverage/Report/FactoryTest.php

+10
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ public function testSomething()
5757
'endLine' => 9,
5858
'executableLines' => 1,
5959
'executedLines' => 1,
60+
'executablePaths' => 1,
61+
'executedPaths' => 1,
6062
'ccn' => 1,
6163
'coverage' => 100,
6264
'crap' => '1',
@@ -70,6 +72,8 @@ public function testSomething()
7072
'endLine' => 18,
7173
'executableLines' => 5,
7274
'executedLines' => 0,
75+
'executablePaths' => 2,
76+
'executedPaths' => 0,
7377
'ccn' => 2,
7478
'coverage' => 0,
7579
'crap' => 6,
@@ -83,6 +87,8 @@ public function testSomething()
8387
'endLine' => 25,
8488
'executableLines' => 2,
8589
'executedLines' => 2,
90+
'executablePaths' => 1,
91+
'executedPaths' => 0,
8692
'ccn' => 1,
8793
'coverage' => 100,
8894
'crap' => '1',
@@ -96,6 +102,8 @@ public function testSomething()
96102
'endLine' => 32,
97103
'executableLines' => 2,
98104
'executedLines' => 2,
105+
'executablePaths' => 1,
106+
'executedPaths' => 0,
99107
'ccn' => 1,
100108
'coverage' => 100,
101109
'crap' => '1',
@@ -107,6 +115,8 @@ public function testSomething()
107115
'startLine' => 2,
108116
'executableLines' => 10,
109117
'executedLines' => 5,
118+
'executablePaths' => 5,
119+
'executedPaths' => 1,
110120
'ccn' => 5,
111121
'coverage' => 50,
112122
'crap' => '8.12',

0 commit comments

Comments
 (0)