Completed
Push — master ( 7afaf7...0cfaa3 )
by Michiel
25:17
created

PHPUnitTask::handlePHPUnitConfiguration()   B

Complexity

Conditions 11
Paths 25

Size

Total Lines 65
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 132

Importance

Changes 0
Metric Value
cc 11
eloc 31
nc 25
nop 1
dl 0
loc 65
ccs 0
cts 34
cp 0
crap 132
rs 7.3166
c 0
b 0
f 0

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
 * Runs PHPUnit tests.
22
 *
23
 * @author  Michiel Rook <[email protected]>
24
 * @package phing.tasks.ext.phpunit
25
 * @see     BatchTest
26
 * @since   2.1.0
27
 */
28
class PHPUnitTask extends Task
29
{
30
    private $batchtests = [];
31
    /**
32
     * @var FormatterElement[] $formatters
33
     */
34
    private $formatters = [];
35
    private $bootstrap = "";
36
    private $haltonerror = false;
37
    private $haltonfailure = false;
38
    private $haltonincomplete = false;
39
    private $haltonskipped = false;
40
    private $errorproperty;
41
    private $failureproperty;
42
    private $incompleteproperty;
43
    private $skippedproperty;
44
    private $printsummary = false;
45
    private $testfailed = false;
46
    private $testfailuremessage = "";
47
    private $codecoverage = null;
48
    private $groups = [];
49
    private $excludeGroups = [];
50
    private $processIsolation = false;
51
    private $usecustomerrorhandler = true;
52
    private $listeners = [];
53
54
    /**
55
     * @var string
56
     */
57
    private $pharLocation = "";
58
59
    /**
60
     * @var PhingFile
61
     */
62
    private $configuration = null;
63
64
    /**
65
     * Initialize Task.
66
     * This method includes any necessary PHPUnit libraries and triggers
67
     * appropriate error if they cannot be found.  This is not done in header
68
     * because we may want this class to be loaded w/o triggering an error.
69
     */
70 4
    public function init()
71
    {
72 4
    }
73
74 4
    private function loadPHPUnit()
75
    {
76
        /**
77
         * Determine PHPUnit version number, try
78
         * PEAR old-style, then composer, then PHAR
79
         */
80 4
        @include_once 'PHPUnit/Runner/Version.php';
81 4
        if (!class_exists('PHPUnit_Runner_Version')) {
82 4
            @include_once 'phpunit/Runner/Version.php';
83
        }
84 4
        if (!empty($this->pharLocation)) {
85
            $GLOBALS['_SERVER']['SCRIPT_NAME'] = '-';
86
            ob_start();
87
            @include $this->pharLocation;
88
            ob_end_clean();
89
        }
90
91 4
        @include_once 'PHPUnit/Autoload.php';
92 4
        if (!class_exists('PHPUnit\Runner\Version')) {
93
            throw new BuildException("PHPUnitTask requires PHPUnit to be installed", $this->getLocation());
94
        }
95 4
    }
96
97
    /**
98
     * Sets the name of a bootstrap file that is run before
99
     * executing the tests
100
     *
101
     * @param string $bootstrap the name of the bootstrap file
102
     */
103 1
    public function setBootstrap($bootstrap)
104
    {
105 1
        $this->bootstrap = $bootstrap;
106 1
    }
107
108
    /**
109
     * @param $value
110
     */
111
    public function setErrorproperty($value)
112
    {
113
        $this->errorproperty = $value;
114
    }
115
116
    /**
117
     * @param $value
118
     */
119
    public function setFailureproperty($value)
120
    {
121
        $this->failureproperty = $value;
122
    }
123
124
    /**
125
     * @param $value
126
     */
127
    public function setIncompleteproperty($value)
128
    {
129
        $this->incompleteproperty = $value;
130
    }
131
132
    /**
133
     * @param $value
134
     */
135
    public function setSkippedproperty($value)
136
    {
137
        $this->skippedproperty = $value;
138
    }
139
140
    /**
141
     * @param $value
142
     */
143 3
    public function setHaltonerror($value)
144
    {
145 3
        $this->haltonerror = $value;
146 3
    }
147
148
    /**
149
     * @param $value
150
     */
151 3
    public function setHaltonfailure($value)
152
    {
153 3
        $this->haltonfailure = $value;
154 3
    }
155
156
    /**
157
     * @return bool
158
     */
159
    public function getHaltonfailure()
160
    {
161
        return $this->haltonfailure;
162
    }
163
164
    /**
165
     * @param $value
166
     */
167
    public function setHaltonincomplete($value)
168
    {
169
        $this->haltonincomplete = $value;
170
    }
171
172
    /**
173
     * @return bool
174
     */
175 1
    public function getHaltonincomplete()
176
    {
177 1
        return $this->haltonincomplete;
178
    }
179
180
    /**
181
     * @param $value
182
     */
183
    public function setHaltonskipped($value)
184
    {
185
        $this->haltonskipped = $value;
186
    }
187
188
    /**
189
     * @return bool
190
     */
191 1
    public function getHaltonskipped()
192
    {
193 1
        return $this->haltonskipped;
194
    }
195
196
    /**
197
     * @param $printsummary
198
     */
199 1
    public function setPrintsummary($printsummary)
200
    {
201 1
        $this->printsummary = $printsummary;
202 1
    }
203
204
    /**
205
     * @param $codecoverage
206
     */
207 1
    public function setCodecoverage($codecoverage)
208
    {
209 1
        $this->codecoverage = $codecoverage;
210 1
    }
211
212
    /**
213
     * @param $processIsolation
214
     */
215
    public function setProcessIsolation($processIsolation)
216
    {
217
        $this->processIsolation = $processIsolation;
218
    }
219
220
    /**
221
     * @param $usecustomerrorhandler
222
     */
223
    public function setUseCustomErrorHandler($usecustomerrorhandler)
224
    {
225
        $this->usecustomerrorhandler = $usecustomerrorhandler;
226
    }
227
228
    /**
229
     * @param $groups
230
     */
231
    public function setGroups($groups)
232
    {
233
        $token = ' ,;';
234
        $this->groups = [];
235
        $tok = strtok($groups, $token);
236
        while ($tok !== false) {
237
            $this->groups[] = $tok;
238
            $tok = strtok($token);
239
        }
240
    }
241
242
    /**
243
     * @param $excludeGroups
244
     */
245
    public function setExcludeGroups($excludeGroups)
246
    {
247
        $token = ' ,;';
248
        $this->excludeGroups = [];
249
        $tok = strtok($excludeGroups, $token);
250
        while ($tok !== false) {
251
            $this->excludeGroups[] = $tok;
252
            $tok = strtok($token);
253
        }
254
    }
255
256
    /**
257
     * Add a new formatter to all tests of this task.
258
     *
259
     * @param FormatterElement $fe formatter element
260
     */
261 2
    public function addFormatter(FormatterElement $fe)
262
    {
263 2
        $fe->setParent($this);
264 2
        $this->formatters[] = $fe;
265 2
    }
266
267
    /**
268
     * Add a new listener to all tests of this taks
269
     *
270
     * @param $listener
271
     */
272
    private function addListener($listener)
273
    {
274
        $this->listeners[] = $listener;
275
    }
276
277
    /**
278
     * @param PhingFile $configuration
279
     */
280
    public function setConfiguration(PhingFile $configuration)
281
    {
282
        $this->configuration = $configuration;
283
    }
284
285
    /**
286
     * @param string $pharLocation
287
     */
288
    public function setPharLocation($pharLocation)
289
    {
290
        $this->pharLocation = $pharLocation;
291
    }
292
293
    /**
294
     * Load and processes the PHPUnit configuration
295
     *
296
     * @param  $configuration
297
     * @return array
298
     * @throws ReflectionException
299
     * @throws BuildException
300
     */
301
    protected function handlePHPUnitConfiguration(PhingFile $configuration)
302
    {
303
        if (!$configuration->exists()) {
304
            throw new BuildException("Unable to find PHPUnit configuration file '" . (string) $configuration . "'");
305
        }
306
307
        $config = \PHPUnit\TextUI\Configuration\Registry::getInstance()->get($configuration->getAbsolutePath());
308
309
        if (empty($config)) {
310
            return [];
311
        }
312
313
        $phpunit = $config->phpunit();
314
315
        if (empty($phpunit)) {
316
            return [];
317
        }
318
319
        if ($phpunit->hasBootstrap()) {
320
            $this->setBootstrap($phpunit->bootstrap());
321
        }
322
        $this->setHaltonfailure($phpunit->stopOnFailure());
323
        $this->setHaltonerror($phpunit->stopOnError());
324
        $this->setHaltonskipped($phpunit->stopOnSkipped());
325
        $this->setHaltonincomplete($phpunit->stopOnIncomplete());
326
        $this->setProcessIsolation($phpunit->processIsolation());
327
328
        foreach ($config->listeners() as $listener) {
329
            if (
330
                !class_exists($listener->className(), false)
331
                && $listener->hasSourceFile()
332
            ) {
333
                include_once $listener->sourceFile();
334
            }
335
336
            if (class_exists($listener->className())) {
337
                if ($listener->hasArguments()) {
338
                    $listener = (new $listener->className())();
339
                } else {
340
                    $listenerClass = new ReflectionClass(
341
                        $listener->className()
342
                    );
343
                    $listener = $listenerClass->newInstanceArgs(
344
                        $listener->arguments()
345
                    );
346
                }
347
348
                if ($listener instanceof \PHPUnit\Framework\TestListener) {
349
                    $this->addListener($listener);
350
                }
351
            }
352
        }
353
354
/*        if (method_exists($config, 'getSeleniumBrowserConfiguration')) {
355
            $browsers = $config->getSeleniumBrowserConfiguration();
356
357
            if (
358
                !empty($browsers)
359
                && class_exists('PHPUnit_Extensions_SeleniumTestCase')
360
            ) {
361
                PHPUnit_Extensions_SeleniumTestCase::$browsers = $browsers;
362
            }
363
        } */
364
365
        return $phpunit;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $phpunit returns the type PHPUnit\TextUI\Configuration\PHPUnit which is incompatible with the documented return type array.
Loading history...
366
    }
367
368
    /**
369
     * The main entry point
370
     *
371
     * @throws BuildException
372
     */
373
    public function main()
374
    {
375
        if ($this->codecoverage && !extension_loaded('xdebug')) {
376
            throw new BuildException("PHPUnitTask depends on Xdebug being installed to gather code coverage information.");
377
        }
378
379
        $this->loadPHPUnit();
380
        $suite = new \PHPUnit\Framework\TestSuite('AllTests');
381
        $autoloadSave = spl_autoload_functions();
382
383
        if ($this->bootstrap) {
384
            include $this->bootstrap;
385
        }
386
387
        if ($this->configuration) {
388
            $phpunit = $this->handlePHPUnitConfiguration($this->configuration);
389
390 4
            if ($phpunit->backupGlobals() === false) {
391
                $suite->setBackupGlobals(false);
392 4
            }
393
394
            if ($phpunit->backupStaticAttributes() === true) {
395
                $suite->setBackupStaticAttributes(true);
396 4
            }
397 4
        }
398 4
399
        if ($this->printsummary) {
400 4
            $fe = new FormatterElement();
401 1
            $fe->setParent($this);
402
            $fe->setType("summary");
403
            $fe->setUseFile(false);
404 4
            $this->formatters[] = $fe;
405
        }
406
407
        foreach ($this->batchtests as $batchTest) {
408
            $this->appendBatchTestToTestSuite($batchTest, $suite);
409
        }
410
411
        $this->execute($suite);
412
413
        if ($this->testfailed) {
414
            throw new BuildException($this->testfailuremessage);
415
        }
416 4
417 1
        $autoloadNew = spl_autoload_functions();
418 1
        if (is_array($autoloadNew)) {
0 ignored issues
show
introduced by
The condition is_array($autoloadNew) is always true.
Loading history...
419 1
            foreach ($autoloadNew as $autoload) {
420 1
                spl_autoload_unregister($autoload);
421 1
            }
422
        }
423
424 4
        if (is_array($autoloadSave)) {
425 4
            foreach ($autoloadSave as $autoload) {
426
                spl_autoload_register($autoload);
427
            }
428 4
        }
429
    }
430 4
431 1
    /**
432
     * @param $suite
433
     * @throws BuildException
434 3
     * @throws ReflectionException
435 3
     */
436 3
    protected function execute($suite)
437 3
    {
438
        if (
439
            class_exists('\PHPUnit\Runner\Version', false) &&
440
            version_compare(\PHPUnit\Runner\Version::id(), '8.0.0', '<')
441 3
        ) {
442 3
            $runner = new PHPUnitTestRunner7(
443 3
                $this->project,
444
                $this->groups,
445
                $this->excludeGroups,
446 3
                $this->processIsolation
447
            );
448
        } else {
449
            $runner = new PHPUnitTestRunner8(
450
                $this->project,
451
                $this->groups,
452
                $this->excludeGroups,
453 4
                $this->processIsolation
454
            );
455
        }
456 4
457 4
        if ($this->codecoverage) {
458
            /**
459
             * Add some defaults to the PHPUnit filter
460
             */
461
            $pwd = __DIR__;
462
            $path = realpath($pwd . '/../../../');
463
464
            if (class_exists('\SebastianBergmann\CodeCoverage\Filter')) {
465
                $filter = new \SebastianBergmann\CodeCoverage\Filter();
466 4
                if (method_exists($filter, 'addDirectoryToBlacklist')) {
467 4
                    $filter->addDirectoryToBlacklist($path);
468 4
                }
469 4
                if (class_exists('\SebastianBergmann\CodeCoverage\CodeCoverage')) {
470 4
                    $codeCoverage = new \SebastianBergmann\CodeCoverage\CodeCoverage(null, $filter);
471
                    $runner->setCodecoverage($codeCoverage);
472
                }
473
            }
474 4
        }
475
476
        $runner->setUseCustomErrorHandler($this->usecustomerrorhandler);
477
478
        foreach ($this->listeners as $listener) {
479
            $runner->addListener($listener);
480
        }
481
482
        foreach ($this->formatters as $fe) {
483
            $formatter = $fe->getFormatter();
484
485
            if ($fe->getUseFile()) {
486
                try {
487
                    $destFile = new PhingFile($fe->getToDir(), $fe->getOutfile());
488
                } catch (Exception $e) {
489
                    throw new BuildException('Unable to create destination.', $e);
490
                }
491
492
                $writer = new FileWriter($destFile->getAbsolutePath());
493 4
494
                $formatter->setOutput($writer);
495 4
            } else {
496
                $formatter->setOutput($this->getDefaultOutput());
497
            }
498
499 4
            $runner->addFormatter($formatter);
500 2
501
            $formatter->startTestRun();
502 2
        }
503
504
        $runner->run($suite);
505
506
        foreach ($this->formatters as $fe) {
507
            $formatter = $fe->getFormatter();
508
            $formatter->endTestRun();
509
        }
510
511
        if ($runner->hasErrors()) {
512
            if ($this->errorproperty) {
513 2
                $this->project->setNewProperty($this->errorproperty, true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $value of Project::setNewProperty(). ( Ignorable by Annotation )

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

513
                $this->project->setNewProperty($this->errorproperty, /** @scrutinizer ignore-type */ true);
Loading history...
514
            }
515
            if ($this->haltonerror) {
516 2
                $this->testfailed = true;
517
                $this->testfailuremessage = $runner->getLastErrorMessage();
518 2
            }
519
        }
520
521 4
        if ($runner->hasFailures()) {
522
            if ($this->failureproperty) {
523 4
                $this->project->setNewProperty($this->failureproperty, true);
524 2
            }
525 2
526
            if ($this->haltonfailure) {
527
                $this->testfailed = true;
528 4
                $this->testfailuremessage = $runner->getLastFailureMessage();
529 2
            }
530
        }
531
532 2
        if ($runner->hasIncomplete()) {
533
            if ($this->incompleteproperty) {
534
                $this->project->setNewProperty($this->incompleteproperty, true);
535
            }
536
537
            if ($this->haltonincomplete) {
538 4
                $this->testfailed = true;
539 3
                $this->testfailuremessage = $runner->getLastIncompleteMessage();
540
            }
541
        }
542
543 3
        if ($runner->hasSkipped()) {
544 1
            if ($this->skippedproperty) {
545 1
                $this->project->setNewProperty($this->skippedproperty, true);
546
            }
547
548
            if ($this->haltonskipped) {
549 4
                $this->testfailed = true;
550
                $this->testfailuremessage = $runner->getLastSkippedMessage();
551
            }
552
        }
553
    }
554
555
    /**
556
     * Add the tests in this batchtest to a test suite
557
     *
558
     * @param BatchTest $batchTest
559
     * @param PHPUnit\Framework\TestSuite $suite
560 4
     * @throws BuildException
561
     * @throws ReflectionException
562
     */
563
    protected function appendBatchTestToTestSuite(BatchTest $batchTest, $suite)
564
    {
565
        foreach ($batchTest->elements() as $element) {
566
            $testClass = new $element();
567
            if (!($testClass instanceof PHPUnit\Framework\TestSuite)) {
568
                $testClass = new ReflectionClass($element);
569
            }
570 4
            try {
571
                $suite->addTestSuite($testClass);
572
            } catch (\PHPUnit\Framework\Exception $e) {
573
                throw new BuildException('Unable to add TestSuite ' . get_class($testClass), $e);
574
            }
575
        }
576
    }
577
578
    /**
579
     * @return LogWriter
580 4
     */
581
    protected function getDefaultOutput()
582 4
    {
583 4
        return new LogWriter($this);
584 4
    }
585 4
586
    /**
587
     * Adds a set of tests based on pattern matching.
588 4
     *
589
     * @return BatchTest a new instance of a batch test.
590
     */
591
    public function createBatchTest()
592
    {
593 4
        $batchtest = new BatchTest($this->getProject());
594
595
        $this->batchtests[] = $batchtest;
596
597
        return $batchtest;
598 2
    }
599
}
600