annotate vendor/phpunit/php-code-coverage/src/Report/Text.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 1fec387a4317
children
rev   line source
Chris@14 1 <?php
Chris@14 2 /*
Chris@14 3 * This file is part of the php-code-coverage package.
Chris@14 4 *
Chris@14 5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
Chris@14 6 *
Chris@14 7 * For the full copyright and license information, please view the LICENSE
Chris@14 8 * file that was distributed with this source code.
Chris@14 9 */
Chris@14 10
Chris@14 11 namespace SebastianBergmann\CodeCoverage\Report;
Chris@14 12
Chris@14 13 use SebastianBergmann\CodeCoverage\CodeCoverage;
Chris@14 14 use SebastianBergmann\CodeCoverage\Node\File;
Chris@14 15 use SebastianBergmann\CodeCoverage\Util;
Chris@14 16
Chris@14 17 /**
Chris@14 18 * Generates human readable output from a code coverage object.
Chris@14 19 *
Chris@14 20 * The output gets put into a text file our written to the CLI.
Chris@14 21 */
Chris@14 22 class Text
Chris@14 23 {
Chris@14 24 private $lowUpperBound;
Chris@14 25 private $highLowerBound;
Chris@14 26 private $showUncoveredFiles;
Chris@14 27 private $showOnlySummary;
Chris@14 28
Chris@14 29 private $colors = [
Chris@14 30 'green' => "\x1b[30;42m",
Chris@14 31 'yellow' => "\x1b[30;43m",
Chris@14 32 'red' => "\x1b[37;41m",
Chris@14 33 'header' => "\x1b[1;37;40m",
Chris@14 34 'reset' => "\x1b[0m",
Chris@14 35 'eol' => "\x1b[2K",
Chris@14 36 ];
Chris@14 37
Chris@14 38 /**
Chris@14 39 * @param int $lowUpperBound
Chris@14 40 * @param int $highLowerBound
Chris@14 41 * @param bool $showUncoveredFiles
Chris@14 42 * @param bool $showOnlySummary
Chris@14 43 */
Chris@14 44 public function __construct($lowUpperBound = 50, $highLowerBound = 90, $showUncoveredFiles = false, $showOnlySummary = false)
Chris@14 45 {
Chris@14 46 $this->lowUpperBound = $lowUpperBound;
Chris@14 47 $this->highLowerBound = $highLowerBound;
Chris@14 48 $this->showUncoveredFiles = $showUncoveredFiles;
Chris@14 49 $this->showOnlySummary = $showOnlySummary;
Chris@14 50 }
Chris@14 51
Chris@14 52 /**
Chris@14 53 * @param CodeCoverage $coverage
Chris@14 54 * @param bool $showColors
Chris@14 55 *
Chris@14 56 * @return string
Chris@14 57 */
Chris@14 58 public function process(CodeCoverage $coverage, $showColors = false)
Chris@14 59 {
Chris@14 60 $output = PHP_EOL . PHP_EOL;
Chris@14 61 $report = $coverage->getReport();
Chris@14 62 unset($coverage);
Chris@14 63
Chris@14 64 $colors = [
Chris@14 65 'header' => '',
Chris@14 66 'classes' => '',
Chris@14 67 'methods' => '',
Chris@14 68 'lines' => '',
Chris@14 69 'reset' => '',
Chris@14 70 'eol' => ''
Chris@14 71 ];
Chris@14 72
Chris@14 73 if ($showColors) {
Chris@14 74 $colors['classes'] = $this->getCoverageColor(
Chris@14 75 $report->getNumTestedClassesAndTraits(),
Chris@14 76 $report->getNumClassesAndTraits()
Chris@14 77 );
Chris@14 78 $colors['methods'] = $this->getCoverageColor(
Chris@14 79 $report->getNumTestedMethods(),
Chris@14 80 $report->getNumMethods()
Chris@14 81 );
Chris@14 82 $colors['lines'] = $this->getCoverageColor(
Chris@14 83 $report->getNumExecutedLines(),
Chris@14 84 $report->getNumExecutableLines()
Chris@14 85 );
Chris@14 86 $colors['reset'] = $this->colors['reset'];
Chris@14 87 $colors['header'] = $this->colors['header'];
Chris@14 88 $colors['eol'] = $this->colors['eol'];
Chris@14 89 }
Chris@14 90
Chris@14 91 $classes = \sprintf(
Chris@14 92 ' Classes: %6s (%d/%d)',
Chris@14 93 Util::percent(
Chris@14 94 $report->getNumTestedClassesAndTraits(),
Chris@14 95 $report->getNumClassesAndTraits(),
Chris@14 96 true
Chris@14 97 ),
Chris@14 98 $report->getNumTestedClassesAndTraits(),
Chris@14 99 $report->getNumClassesAndTraits()
Chris@14 100 );
Chris@14 101
Chris@14 102 $methods = \sprintf(
Chris@14 103 ' Methods: %6s (%d/%d)',
Chris@14 104 Util::percent(
Chris@14 105 $report->getNumTestedMethods(),
Chris@14 106 $report->getNumMethods(),
Chris@14 107 true
Chris@14 108 ),
Chris@14 109 $report->getNumTestedMethods(),
Chris@14 110 $report->getNumMethods()
Chris@14 111 );
Chris@14 112
Chris@14 113 $lines = \sprintf(
Chris@14 114 ' Lines: %6s (%d/%d)',
Chris@14 115 Util::percent(
Chris@14 116 $report->getNumExecutedLines(),
Chris@14 117 $report->getNumExecutableLines(),
Chris@14 118 true
Chris@14 119 ),
Chris@14 120 $report->getNumExecutedLines(),
Chris@14 121 $report->getNumExecutableLines()
Chris@14 122 );
Chris@14 123
Chris@14 124 $padding = \max(\array_map('strlen', [$classes, $methods, $lines]));
Chris@14 125
Chris@14 126 if ($this->showOnlySummary) {
Chris@14 127 $title = 'Code Coverage Report Summary:';
Chris@14 128 $padding = \max($padding, \strlen($title));
Chris@14 129
Chris@14 130 $output .= $this->format($colors['header'], $padding, $title);
Chris@14 131 } else {
Chris@14 132 $date = \date(' Y-m-d H:i:s', $_SERVER['REQUEST_TIME']);
Chris@14 133 $title = 'Code Coverage Report:';
Chris@14 134
Chris@14 135 $output .= $this->format($colors['header'], $padding, $title);
Chris@14 136 $output .= $this->format($colors['header'], $padding, $date);
Chris@14 137 $output .= $this->format($colors['header'], $padding, '');
Chris@14 138 $output .= $this->format($colors['header'], $padding, ' Summary:');
Chris@14 139 }
Chris@14 140
Chris@14 141 $output .= $this->format($colors['classes'], $padding, $classes);
Chris@14 142 $output .= $this->format($colors['methods'], $padding, $methods);
Chris@14 143 $output .= $this->format($colors['lines'], $padding, $lines);
Chris@14 144
Chris@14 145 if ($this->showOnlySummary) {
Chris@14 146 return $output . PHP_EOL;
Chris@14 147 }
Chris@14 148
Chris@14 149 $classCoverage = [];
Chris@14 150
Chris@14 151 foreach ($report as $item) {
Chris@14 152 if (!$item instanceof File) {
Chris@14 153 continue;
Chris@14 154 }
Chris@14 155
Chris@14 156 $classes = $item->getClassesAndTraits();
Chris@14 157
Chris@14 158 foreach ($classes as $className => $class) {
Chris@14 159 $classStatements = 0;
Chris@14 160 $coveredClassStatements = 0;
Chris@14 161 $coveredMethods = 0;
Chris@14 162 $classMethods = 0;
Chris@14 163
Chris@14 164 foreach ($class['methods'] as $method) {
Chris@14 165 if ($method['executableLines'] == 0) {
Chris@14 166 continue;
Chris@14 167 }
Chris@14 168
Chris@14 169 $classMethods++;
Chris@14 170 $classStatements += $method['executableLines'];
Chris@14 171 $coveredClassStatements += $method['executedLines'];
Chris@14 172 if ($method['coverage'] == 100) {
Chris@14 173 $coveredMethods++;
Chris@14 174 }
Chris@14 175 }
Chris@14 176
Chris@14 177 if (!empty($class['package']['namespace'])) {
Chris@14 178 $namespace = '\\' . $class['package']['namespace'] . '::';
Chris@14 179 } elseif (!empty($class['package']['fullPackage'])) {
Chris@14 180 $namespace = '@' . $class['package']['fullPackage'] . '::';
Chris@14 181 } else {
Chris@14 182 $namespace = '';
Chris@14 183 }
Chris@14 184
Chris@14 185 $classCoverage[$namespace . $className] = [
Chris@14 186 'namespace' => $namespace,
Chris@14 187 'className ' => $className,
Chris@14 188 'methodsCovered' => $coveredMethods,
Chris@14 189 'methodCount' => $classMethods,
Chris@14 190 'statementsCovered' => $coveredClassStatements,
Chris@14 191 'statementCount' => $classStatements,
Chris@14 192 ];
Chris@14 193 }
Chris@14 194 }
Chris@14 195
Chris@14 196 \ksort($classCoverage);
Chris@14 197
Chris@14 198 $methodColor = '';
Chris@14 199 $linesColor = '';
Chris@14 200 $resetColor = '';
Chris@14 201
Chris@14 202 foreach ($classCoverage as $fullQualifiedPath => $classInfo) {
Chris@14 203 if ($classInfo['statementsCovered'] != 0 ||
Chris@14 204 $this->showUncoveredFiles) {
Chris@14 205 if ($showColors) {
Chris@14 206 $methodColor = $this->getCoverageColor($classInfo['methodsCovered'], $classInfo['methodCount']);
Chris@14 207 $linesColor = $this->getCoverageColor($classInfo['statementsCovered'], $classInfo['statementCount']);
Chris@14 208 $resetColor = $colors['reset'];
Chris@14 209 }
Chris@14 210
Chris@14 211 $output .= PHP_EOL . $fullQualifiedPath . PHP_EOL
Chris@14 212 . ' ' . $methodColor . 'Methods: ' . $this->printCoverageCounts($classInfo['methodsCovered'], $classInfo['methodCount'], 2) . $resetColor . ' '
Chris@14 213 . ' ' . $linesColor . 'Lines: ' . $this->printCoverageCounts($classInfo['statementsCovered'], $classInfo['statementCount'], 3) . $resetColor
Chris@14 214 ;
Chris@14 215 }
Chris@14 216 }
Chris@14 217
Chris@14 218 return $output . PHP_EOL;
Chris@14 219 }
Chris@14 220
Chris@14 221 protected function getCoverageColor($numberOfCoveredElements, $totalNumberOfElements)
Chris@14 222 {
Chris@14 223 $coverage = Util::percent(
Chris@14 224 $numberOfCoveredElements,
Chris@14 225 $totalNumberOfElements
Chris@14 226 );
Chris@14 227
Chris@14 228 if ($coverage >= $this->highLowerBound) {
Chris@14 229 return $this->colors['green'];
Chris@14 230 } elseif ($coverage > $this->lowUpperBound) {
Chris@14 231 return $this->colors['yellow'];
Chris@14 232 }
Chris@14 233
Chris@14 234 return $this->colors['red'];
Chris@14 235 }
Chris@14 236
Chris@14 237 protected function printCoverageCounts($numberOfCoveredElements, $totalNumberOfElements, $precision)
Chris@14 238 {
Chris@14 239 $format = '%' . $precision . 's';
Chris@14 240
Chris@14 241 return Util::percent(
Chris@14 242 $numberOfCoveredElements,
Chris@14 243 $totalNumberOfElements,
Chris@14 244 true,
Chris@14 245 true
Chris@14 246 ) .
Chris@14 247 ' (' . \sprintf($format, $numberOfCoveredElements) . '/' .
Chris@14 248 \sprintf($format, $totalNumberOfElements) . ')';
Chris@14 249 }
Chris@14 250
Chris@14 251 private function format($color, $padding, $string)
Chris@14 252 {
Chris@14 253 $reset = $color ? $this->colors['reset'] : '';
Chris@14 254
Chris@14 255 return $color . \str_pad($string, $padding) . $reset . PHP_EOL;
Chris@14 256 }
Chris@14 257 }