comparison vendor/phpunit/php-code-coverage/src/Report/Text.php @ 14:1fec387a4317

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