Passed
Push — master ( 7a3d33...76fc3a )
by Siad
09:26
created

PHPUnitTestRunner9::run()   C

Complexity

Conditions 12
Paths 240

Size

Total Lines 53
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 21.7369

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 12
eloc 27
c 2
b 0
f 0
nc 240
nop 1
dl 0
loc 53
ccs 16
cts 27
cp 0.5926
crap 21.7369
rs 5.6333

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19
20
/**
21
 * Simple Testrunner for PHPUnit that runs all tests of a testsuite.
22
 *
23
 * @author  Blair Cooper <[email protected]>
24
 * @package phing.tasks.ext.phpunit
25
 */
26
class PHPUnitTestRunner9 implements \PHPUnit\Runner\TestHook, \PHPUnit\Framework\TestListener
0 ignored issues
show
Deprecated Code introduced by
The interface PHPUnit\Framework\TestListener has been deprecated: Use the `TestHook` interfaces instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

26
class PHPUnitTestRunner9 implements \PHPUnit\Runner\TestHook, /** @scrutinizer ignore-deprecated */ \PHPUnit\Framework\TestListener

This interface has been deprecated. The supplier of the interface has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the interface will be removed and what other interface to use instead.

Loading history...
27
{
28
    private $hasErrors = false;
29
    private $hasFailures = false;
30
    private $hasWarnings = false;
31
    private $hasIncomplete = false;
32
    private $hasSkipped = false;
33
    private $hasRisky = false;
34
    private $lastErrorMessage = '';
35
    private $lastFailureMessage = '';
36
    private $lastWarningMessage = '';
37
    private $lastIncompleteMessage = '';
38
    private $lastSkippedMessage = '';
39
    private $lastRiskyMessage = '';
40
    private $formatters = [];
41
42
    /**
43
     * @var \PHPUnit\Framework\TestListener[]
44
     */
45
    private $listeners = [];
46
47
    /**
48
     * @var \SebastianBergmann\CodeCoverage\CodeCoverage
49
     */
50
    private $codecoverage;
51
52
    /**
53
     * @var Project $project
54
     */
55
    private $project;
56
57
    private $groups = [];
58
    private $excludeGroups = [];
59
60
    private $processIsolation = false;
61
62
    private $useCustomErrorHandler = true;
63
64
    /**
65
     * @param Project $project
66
     * @param array $groups
67
     * @param array $excludeGroups
68
     * @param bool $processIsolation
69
     */
70 4
    public function __construct(
71
        Project $project,
72
        array $groups = [],
73
        array $excludeGroups = [],
74
        bool $processIsolation = false
75
    ) {
76 4
        $this->project = $project;
77 4
        $this->groups = $groups;
78 4
        $this->excludeGroups = $excludeGroups;
79 4
        $this->processIsolation = $processIsolation;
80 4
    }
81
82
    /**
83
     * @param $codecoverage
84
     */
85
    public function setCodecoverage(\SebastianBergmann\CodeCoverage\CodeCoverage $codecoverage): void
86
    {
87
        $this->codecoverage = $codecoverage;
88
    }
89
90
    /**
91
     * @param $useCustomErrorHandler
92
     */
93 4
    public function setUseCustomErrorHandler(bool $useCustomErrorHandler): void
94
    {
95 4
        $this->useCustomErrorHandler = $useCustomErrorHandler;
96 4
    }
97
98
    /**
99
     * @param $formatter
100
     */
101 2
    public function addFormatter(\PHPUnit\Framework\TestListener $formatter): void
102
    {
103 2
        $this->addListener($formatter);
104 2
        $this->formatters[] = $formatter;
105 2
    }
106
107 2
    public function addListener(\PHPUnit\Framework\TestListener $listener): void
108
    {
109 2
        $this->listeners[] = $listener;
110 2
    }
111
112
    /**
113
     * @param $level
114
     * @param $message
115
     * @param $file
116
     * @param $line
117
     * @return bool
118
     */
119 98
    public function handleError(int $level, string $message, string $file, int $line): bool
120
    {
121 98
        $invoke = new PHPUnit\Util\ErrorHandler(true, true, true, true);
122 98
        return $invoke($level, $message, $file, $line);
123
    }
124
125
    /**
126
     * Run a test
127
     *
128
     * @param  PHPUnit\Framework\TestSuite $suite
129
     * @throws \BuildException
130
     * @throws ReflectionException
131
     */
132 4
    public function run(PHPUnit\Framework\TestSuite $suite)
133
    {
134 4
        $res = new PHPUnit\Framework\TestResult();
135
136 4
        if ($this->codecoverage) {
137
            // Check if Phing coverage is being utlizied
138
            if ($this->project->getProperty('coverage.database')) {
139
                $whitelist = \Phing\Tasks\Ext\Coverage\CoverageMerger::getWhiteList($this->project);
140
                $filter = $this->codecoverage->filter();
141
142
                if (method_exists($filter, 'includeFiles')) {
143
                    $filter->includeFiles($whitelist);
144
                } else if (method_exists($filter, 'addFilesToWhiteList')) {
145
                    $filter->addFilesToWhiteList($whitelist);
146
                }
147
            }
148
149
            $res->setCodeCoverage($this->codecoverage);
150
        }
151
152
        // $res->addListener($this);
153
154 4
        foreach ($this->formatters as $formatter) {
155 2
            $res->addListener($formatter);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\TestResult::addListener() has been deprecated: Use the `TestHook` interfaces instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

155
            /** @scrutinizer ignore-deprecated */ $res->addListener($formatter);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
156
        }
157
158
        /* Set PHPUnit error handler */
159 4
        if ($this->useCustomErrorHandler) {
160 4
            set_error_handler([$this, 'handleError'], E_ALL | E_STRICT);
161
        }
162
163 4
        $this->injectFilters($suite);
164 4
        $suite->setRunTestInSeparateProcess($this->processIsolation);
165 4
        $suite->run($res);
166
167 4
        foreach ($this->formatters as $formatter) {
168 2
            $formatter->processResult($res);
169
        }
170
171
        /* Restore Phing error handler */
172 4
        if ($this->useCustomErrorHandler) {
173 4
            restore_error_handler();
174
        }
175
176
        // Check if Phing coverage is being utlizied
177 4
        if ($this->codecoverage && $this->project->getProperty('coverage.database')) {
178
            try {
179
                \Phing\Tasks\Ext\Coverage\CoverageMerger::merge($this->project, $this->codecoverage->getData());
180
            } catch (IOException $e) {
181
                throw new BuildException('Merging code coverage failed.', $e);
182
            }
183
        }
184 4
        $this->checkResult($res);
185 4
    }
186
187
    /**
188
     * @param PHPUnit\Framework\TestSuite $suite
189
     * @throws ReflectionException
190
     */
191 4
    private function injectFilters(PHPUnit\Framework\TestSuite $suite): void
192
    {
193 4
        $filterFactory = new PHPUnit\Runner\Filter\Factory();
194
195 4
        if (empty($this->excludeGroups) && empty($this->groups)) {
196 4
            return;
197
        }
198
199
        if (!empty($this->excludeGroups)) {
200
            $filterFactory->addFilter(
201
                new ReflectionClass(\PHPUnit\Runner\Filter\ExcludeGroupFilterIterator::class),
202
                $this->excludeGroups
203
            );
204
        }
205
206
        if (!empty($this->groups)) {
207
            $filterFactory->addFilter(
208
                new ReflectionClass(\PHPUnit\Runner\Filter\IncludeGroupFilterIterator::class),
209
                $this->groups
210
            );
211
        }
212
213
        $suite->injectFilter($filterFactory);
214
    }
215
216
    /**
217
     * @param \PHPUnit\Framework\TestResult $res
218
     */
219 4
    private function checkResult(\PHPUnit\Framework\TestResult $res): void
220
    {
221 4
        $this->hasSkipped = $res->skippedCount() > 0;
222 4
        $this->hasIncomplete = $res->notImplementedCount() > 0;
223 4
        $this->hasWarnings = $res->warningCount() > 0;
224 4
        $this->hasFailures = $res->failureCount() > 0;
225 4
        $this->hasErrors = $res->errorCount() > 0;
226 4
        $this->hasRisky = $res->riskyCount() > 0;
227 4
    }
228
229
    /**
230
     * @return boolean
231
     */
232 4
    public function hasErrors(): bool
233
    {
234 4
        return $this->hasErrors;
235
    }
236
237
    /**
238
     * @return boolean
239
     */
240 4
    public function hasFailures(): bool
241
    {
242 4
        return $this->hasFailures;
243
    }
244
245
    /**
246
     * @return boolean
247
     */
248 4
    public function hasWarnings(): bool
249
    {
250 4
        return $this->hasWarnings;
251
    }
252
253
    /**
254
     * @return boolean
255
     */
256 4
    public function hasIncomplete(): bool
257
    {
258 4
        return $this->hasIncomplete;
259
    }
260
261
    /**
262
     * @return boolean
263
     */
264 4
    public function hasSkipped(): bool
265
    {
266 4
        return $this->hasSkipped;
267
    }
268
269
    /**
270
     * @return boolean
271
     */
272 4
    public function hasRisky(): bool
273
    {
274 4
        return $this->hasRisky;
275
    }
276
277
    /**
278
     * @return string
279
     */
280
    public function getLastErrorMessage(): string
281
    {
282
        return $this->lastErrorMessage;
283
    }
284
285
    /**
286
     * @return string
287
     */
288 1
    public function getLastFailureMessage(): string
289
    {
290 1
        return $this->lastFailureMessage;
291
    }
292
293
    /**
294
     * @return string
295
     */
296
    public function getLastIncompleteMessage(): string
297
    {
298
        return $this->lastIncompleteMessage;
299
    }
300
301
    /**
302
     * @return string
303
     */
304
    public function getLastSkippedMessage(): string
305
    {
306
        return $this->lastSkippedMessage;
307
    }
308
309
    /**
310
     * @return string
311
     */
312
    public function getLastWarningMessage(): string
313
    {
314
        return $this->lastWarningMessage;
315
    }
316
317
    /**
318
     * @return string
319
     */
320
    public function getLastRiskyMessage(): string
321
    {
322
        return $this->lastRiskyMessage;
323
    }
324
325
    /**
326
     * An error occurred.
327
     *
328
     * @param PHPUnit\Framework\Test $test
329
     * @param Throwable $e
330
     * @param float $time
331
     */
332
    public function addError(PHPUnit\Framework\Test $test, Throwable $e, float $time): void
333
    {
334
        $this->lastErrorMessage = $this->composeMessage('ERROR', $test, $e);
335
    }
336
337
    /**
338
     * @param string $message
339
     * @param PHPUnit\Framework\Test $test
340
     * @param Throwable $e
341
     * @return string
342
     */
343
    protected function composeMessage(string $message, PHPUnit\Framework\Test $test, Throwable $e): string
344
    {
345
        $name = ($test instanceof \PHPUnit\Framework\TestCase ? $test->getName() : '');
346
        $message = "Test {$message} ({$name} in class " . get_class($test) . ' ' . $e->getFile()
347
            . ' on line ' . $e->getLine() . '): ' . $e->getMessage();
348
349
        if ($e instanceof PHPUnit\Framework\ExpectationFailedException && $e->getComparisonFailure()) {
350
            $message .= "\n" . $e->getComparisonFailure()->getDiff();
351
        }
352
353
        return $message;
354
    }
355
356
    /**
357
     * A failure occurred.
358
     *
359
     * @param PHPUnit\Framework\Test $test
360
     * @param PHPUnit\Framework\AssertionFailedError $e
361
     * @param float $time
362
     */
363
    public function addFailure(
364
        PHPUnit\Framework\Test $test,
365
        PHPUnit\Framework\AssertionFailedError $e,
366
        float $time
367
    ): void {
368
        $this->lastFailureMessage = $this->composeMessage('FAILURE', $test, $e);
369
    }
370
371
    /**
372
     * A failure occurred.
373
     *
374
     * @param PHPUnit\Framework\Test $test
375
     * @param PHPUnit\Framework\AssertionFailedError $e
376
     * @param float $time
377
     */
378
    public function addWarning(PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time): void
379
    {
380
        $this->lastWarningMessage = $this->composeMessage("WARNING", $test, $e);
381
    }
382
383
    /**
384
     * Incomplete test.
385
     *
386
     * @param PHPUnit\Framework\Test $test
387
     * @param Exception $e
388
     * @param float $time
389
     */
390
    public function addIncompleteTest(PHPUnit\Framework\Test $test, Throwable $e, float $time): void
391
    {
392
        $this->lastIncompleteMessage = $this->composeMessage("INCOMPLETE", $test, $e);
393
    }
394
395
    /**
396
     * Skipped test.
397
     *
398
     * @param PHPUnit\Framework\Test $test
399
     * @param Exception $e
400
     * @param float $time
401
     * @since Method available since Release 3.0.0
402
     */
403
    public function addSkippedTest(PHPUnit\Framework\Test $test, Throwable $e, float $time): void
404
    {
405
        $this->lastSkippedMessage = $this->composeMessage('SKIPPED', $test, $e);
406
    }
407
408
    /**
409
     * Risky test
410
     *
411
     * @param PHPUnit\Framework\Test $test
412
     * @param Throwable $e
413
     * @param float $time
414
     */
415
    public function addRiskyTest(PHPUnit\Framework\Test $test, Throwable $e, float $time): void
416
    {
417
        $this->lastRiskyMessage = $this->composeMessage('RISKY', $test, $e);
418
    }
419
420
    /**
421
     * A test suite started.
422
     *
423
     * @param PHPUnit\Framework\TestSuite $suite
424
     */
425
    public function startTestSuite(PHPUnit\Framework\TestSuite $suite): void
426
    {
427
    }
428
429
    /**
430
     * A test suite ended.
431
     *
432
     * @param PHPUnit\Framework\TestSuite $suite
433
     */
434
    public function endTestSuite(PHPUnit\Framework\TestSuite $suite): void
435
    {
436
    }
437
438
    /**
439
     * A test started.
440
     *
441
     * @param PHPUnit\Framework\Test $test
442
     */
443
    public function startTest(PHPUnit\Framework\Test $test): void
444
    {
445
    }
446
447
    /**
448
     * A test ended.
449
     *
450
     * @param PHPUnit\Framework\Test $test
451
     * @param float $time
452
     */
453
    public function endTest(PHPUnit\Framework\Test $test, float $time): void
454
    {
455
        if (($test instanceof PHPUnit\Framework\TestCase) && !$test->hasExpectationOnOutput()) {
456
            echo $test->getActualOutput();
457
        }
458
    }
459
460
    /**
461
     * Override to define how to handle a failed loading of
462
     * a test suite.
463
     *
464
     * @param  string $message
465
     * @throws BuildException
466
     */
467
    protected function runFailed($message): void
468
    {
469
        throw new BuildException($message);
470
    }
471
}
472