comparison vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.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\Html;
12
13 use SebastianBergmann\CodeCoverage\Node\AbstractNode;
14 use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
15
16 /**
17 * Renders the dashboard for a directory node.
18 */
19 class Dashboard extends Renderer
20 {
21 /**
22 * @param DirectoryNode $node
23 * @param string $file
24 *
25 * @throws \InvalidArgumentException
26 */
27 public function render(DirectoryNode $node, $file)
28 {
29 $classes = $node->getClassesAndTraits();
30 $template = new \Text_Template(
31 $this->templatePath . 'dashboard.html',
32 '{{',
33 '}}'
34 );
35
36 $this->setCommonTemplateVariables($template, $node);
37
38 $baseLink = $node->getId() . '/';
39 $complexity = $this->complexity($classes, $baseLink);
40 $coverageDistribution = $this->coverageDistribution($classes);
41 $insufficientCoverage = $this->insufficientCoverage($classes, $baseLink);
42 $projectRisks = $this->projectRisks($classes, $baseLink);
43
44 $template->setVar(
45 [
46 'insufficient_coverage_classes' => $insufficientCoverage['class'],
47 'insufficient_coverage_methods' => $insufficientCoverage['method'],
48 'project_risks_classes' => $projectRisks['class'],
49 'project_risks_methods' => $projectRisks['method'],
50 'complexity_class' => $complexity['class'],
51 'complexity_method' => $complexity['method'],
52 'class_coverage_distribution' => $coverageDistribution['class'],
53 'method_coverage_distribution' => $coverageDistribution['method']
54 ]
55 );
56
57 $template->renderTo($file);
58 }
59
60 /**
61 * Returns the data for the Class/Method Complexity charts.
62 *
63 * @param array $classes
64 * @param string $baseLink
65 *
66 * @return array
67 */
68 protected function complexity(array $classes, $baseLink)
69 {
70 $result = ['class' => [], 'method' => []];
71
72 foreach ($classes as $className => $class) {
73 foreach ($class['methods'] as $methodName => $method) {
74 if ($className !== '*') {
75 $methodName = $className . '::' . $methodName;
76 }
77
78 $result['method'][] = [
79 $method['coverage'],
80 $method['ccn'],
81 \sprintf(
82 '<a href="%s">%s</a>',
83 \str_replace($baseLink, '', $method['link']),
84 $methodName
85 )
86 ];
87 }
88
89 $result['class'][] = [
90 $class['coverage'],
91 $class['ccn'],
92 \sprintf(
93 '<a href="%s">%s</a>',
94 \str_replace($baseLink, '', $class['link']),
95 $className
96 )
97 ];
98 }
99
100 return [
101 'class' => \json_encode($result['class']),
102 'method' => \json_encode($result['method'])
103 ];
104 }
105
106 /**
107 * Returns the data for the Class / Method Coverage Distribution chart.
108 *
109 * @param array $classes
110 *
111 * @return array
112 */
113 protected function coverageDistribution(array $classes)
114 {
115 $result = [
116 'class' => [
117 '0%' => 0,
118 '0-10%' => 0,
119 '10-20%' => 0,
120 '20-30%' => 0,
121 '30-40%' => 0,
122 '40-50%' => 0,
123 '50-60%' => 0,
124 '60-70%' => 0,
125 '70-80%' => 0,
126 '80-90%' => 0,
127 '90-100%' => 0,
128 '100%' => 0
129 ],
130 'method' => [
131 '0%' => 0,
132 '0-10%' => 0,
133 '10-20%' => 0,
134 '20-30%' => 0,
135 '30-40%' => 0,
136 '40-50%' => 0,
137 '50-60%' => 0,
138 '60-70%' => 0,
139 '70-80%' => 0,
140 '80-90%' => 0,
141 '90-100%' => 0,
142 '100%' => 0
143 ]
144 ];
145
146 foreach ($classes as $class) {
147 foreach ($class['methods'] as $methodName => $method) {
148 if ($method['coverage'] === 0) {
149 $result['method']['0%']++;
150 } elseif ($method['coverage'] === 100) {
151 $result['method']['100%']++;
152 } else {
153 $key = \floor($method['coverage'] / 10) * 10;
154 $key = $key . '-' . ($key + 10) . '%';
155 $result['method'][$key]++;
156 }
157 }
158
159 if ($class['coverage'] === 0) {
160 $result['class']['0%']++;
161 } elseif ($class['coverage'] === 100) {
162 $result['class']['100%']++;
163 } else {
164 $key = \floor($class['coverage'] / 10) * 10;
165 $key = $key . '-' . ($key + 10) . '%';
166 $result['class'][$key]++;
167 }
168 }
169
170 return [
171 'class' => \json_encode(\array_values($result['class'])),
172 'method' => \json_encode(\array_values($result['method']))
173 ];
174 }
175
176 /**
177 * Returns the classes / methods with insufficient coverage.
178 *
179 * @param array $classes
180 * @param string $baseLink
181 *
182 * @return array
183 */
184 protected function insufficientCoverage(array $classes, $baseLink)
185 {
186 $leastTestedClasses = [];
187 $leastTestedMethods = [];
188 $result = ['class' => '', 'method' => ''];
189
190 foreach ($classes as $className => $class) {
191 foreach ($class['methods'] as $methodName => $method) {
192 if ($method['coverage'] < $this->highLowerBound) {
193 $key = $methodName;
194
195 if ($className !== '*') {
196 $key = $className . '::' . $methodName;
197 }
198
199 $leastTestedMethods[$key] = $method['coverage'];
200 }
201 }
202
203 if ($class['coverage'] < $this->highLowerBound) {
204 $leastTestedClasses[$className] = $class['coverage'];
205 }
206 }
207
208 \asort($leastTestedClasses);
209 \asort($leastTestedMethods);
210
211 foreach ($leastTestedClasses as $className => $coverage) {
212 $result['class'] .= \sprintf(
213 ' <tr><td><a href="%s">%s</a></td><td class="text-right">%d%%</td></tr>' . "\n",
214 \str_replace($baseLink, '', $classes[$className]['link']),
215 $className,
216 $coverage
217 );
218 }
219
220 foreach ($leastTestedMethods as $methodName => $coverage) {
221 list($class, $method) = \explode('::', $methodName);
222
223 $result['method'] .= \sprintf(
224 ' <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d%%</td></tr>' . "\n",
225 \str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']),
226 $methodName,
227 $method,
228 $coverage
229 );
230 }
231
232 return $result;
233 }
234
235 /**
236 * Returns the project risks according to the CRAP index.
237 *
238 * @param array $classes
239 * @param string $baseLink
240 *
241 * @return array
242 */
243 protected function projectRisks(array $classes, $baseLink)
244 {
245 $classRisks = [];
246 $methodRisks = [];
247 $result = ['class' => '', 'method' => ''];
248
249 foreach ($classes as $className => $class) {
250 foreach ($class['methods'] as $methodName => $method) {
251 if ($method['coverage'] < $this->highLowerBound &&
252 $method['ccn'] > 1) {
253 if ($className !== '*') {
254 $key = $className . '::' . $methodName;
255 } else {
256 $key = $methodName;
257 }
258
259 $methodRisks[$key] = $method['crap'];
260 }
261 }
262
263 if ($class['coverage'] < $this->highLowerBound &&
264 $class['ccn'] > \count($class['methods'])) {
265 $classRisks[$className] = $class['crap'];
266 }
267 }
268
269 \arsort($classRisks);
270 \arsort($methodRisks);
271
272 foreach ($classRisks as $className => $crap) {
273 $result['class'] .= \sprintf(
274 ' <tr><td><a href="%s">%s</a></td><td class="text-right">%d</td></tr>' . "\n",
275 \str_replace($baseLink, '', $classes[$className]['link']),
276 $className,
277 $crap
278 );
279 }
280
281 foreach ($methodRisks as $methodName => $crap) {
282 list($class, $method) = \explode('::', $methodName);
283
284 $result['method'] .= \sprintf(
285 ' <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d</td></tr>' . "\n",
286 \str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']),
287 $methodName,
288 $method,
289 $crap
290 );
291 }
292
293 return $result;
294 }
295
296 protected function getActiveBreadcrumb(AbstractNode $node)
297 {
298 return \sprintf(
299 ' <li><a href="index.html">%s</a></li>' . "\n" .
300 ' <li class="active">(Dashboard)</li>' . "\n",
301 $node->getName()
302 );
303 }
304 }