Test Failed
Push — stable ( 52f02e...8e9716 )
by Nuno
04:37
created

Listener::endTestSuite()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
dl 0
loc 38
ccs 0
cts 23
cp 0
rs 8.6897
c 0
b 0
f 0
cc 6
nc 7
nop 1
crap 42
1
<?php
2
3
/**
4
 * This file is part of Collision.
5
 *
6
 * (c) Nuno Maduro <[email protected]>
7
 *
8
 *  For the full copyright and license information, please view the LICENSE
9
 *  file that was distributed with this source code.
10
 */
11
12
namespace NunoMaduro\Collision\Adapters\Phpunit;
13
14
use NunoMaduro\Collision\Exceptions\ShouldNotHappen;
15
use PHPUnit\Framework\AssertionFailedError;
16
use PHPUnit\Framework\Test;
17
use PHPUnit\Framework\TestCase;
18
use PHPUnit\Framework\TestListener;
19
use PHPUnit\Framework\TestSuite;
20
use PHPUnit\Framework\Warning;
21
use PHPUnit\Util\Printer;
22
use ReflectionObject;
23
use Symfony\Component\Console\Input\ArgvInput;
24
use Symfony\Component\Console\Input\InputInterface;
25
use Symfony\Component\Console\Output\ConsoleOutput;
26
use Throwable;
27
28
/**
29
 * This `if` condition exists because phpunit
30
 * is not a direct dependency of Collision.
31
 */
32
if (class_exists(\PHPUnit\Runner\Version::class) && intval(substr(\PHPUnit\Runner\Version::id(), 0, 1)) >= 8) {
33
34
    /**
35
     * This is an Collision Phpunit Adapter implementation.
36
     *
37
     * @internal
38
     */
39
    final class Listener extends Printer implements TestListener
0 ignored issues
show
Deprecated Code introduced by
The interface PHPUnit\Framework\TestListener has been deprecated with message: Use the `TestHook` interfaces instead

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

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

Loading history...
40
    {
41
        /**
42
         * Holds an instance of the console input.
43
         *
44
         * @var InputInterface
45
         */
46
        private $input;
47
48
        /**
49
         * Holds an instance of the console input.
50
         *
51
         * @var ConsoleOutput
52
         */
53
        private $output;
54
55
        /**
56
         * Holds an instance of Section.
57
         *
58
         * @var Section
59
         */
60
        private $section;
61
62
        /**
63
         * The timer.
64
         *
65
         * @var Timer
66
         */
67
        private $timer;
68
69
        /**
70
         * The number of total tests.
71
         *
72
         * @var int|null
73
         */
74
        private $totalTests;
75
76
        /**
77
         * Indicates that the method `end`
78
         * was called already.
79
         *
80
         * @var bool
81
         */
82
        private $sectionEnded = false;
83
84
        /**
85
         * The current test number.
86
         *
87
         * @var int
88
         */
89
        private $currentTestNumber = 0;
90
91
        /**
92
         * The number of passed tests.
93
         *
94
         * @var int
95
         */
96
        private $passedTests = 0;
97
98
        /**
99
         * The number of skipped tests.
100
         *
101
         * @var int
102
         */
103
        private $skippedTests = 0;
104
105
        /**
106
         * The number of warning tests.
107
         *
108
         * @var int
109
         */
110
        private $warningsTests = 0;
111
112
        /**
113
         * The number of incomplete tests.
114
         *
115
         * @var int
116
         */
117
        private $incompleteTests = 0;
118
119
        /**
120
         * The number of risky tests.
121
         *
122
         * @var int
123
         */
124
        private $riskyTests = 0;
125
126
        /**
127
         * Creates a new instance of the listener.
128
         *
129
         * @param  InputInterface  $input
130
         * @param  ConsoleOutput  $output
131
         *
132
         * @throws \ReflectionException
133
         */
134 3
        public function __construct(InputInterface $input = null, ConsoleOutput $output = null)
135
        {
136 3
            parent::__construct();
137
138 3
            $this->input = $input ?? new ArgvInput();
139 3
            $this->output = $output ?? new ConsoleOutput();
140 3
            ConfigureIO::of($this->input, $this->output);
141 3
            $this->section = new Section($this->output);
142
143
            /**
144
             * Starts the timer.
145
             */
146 3
            $this->timer = Timer::start();
147 3
        }
148
149
        /**
150
         * {@inheritdoc}
151
         */
152
        public function addError(Test $test, \Throwable $throwable, float $time): void
153
        {
154
            $this->section->fail();
155
156
            OnError::display($this->output, $throwable);
157
        }
158
159
        /**
160
         * {@inheritdoc}
161
         */
162
        public function addWarning(Test $test, Warning $warning, float $time): void
163
        {
164
            $this->warningsTests++;
165
166
            $this->section->warn($warning);
167
        }
168
169
        /**
170
         * {@inheritdoc}
171
         */
172
        public function addFailure(Test $test, AssertionFailedError $error, float $time): void
173
        {
174
            $this->section->fail();
175
176
            $reflector = new ReflectionObject($error);
177
178
            if ($reflector->hasProperty('message')) {
179
                $message = trim((string) preg_replace("/\r|\n/", ' ', $error->getMessage()));
180
                $property = $reflector->getProperty('message');
181
                $property->setAccessible(true);
182
                $property->setValue($error, $message);
183
            }
184
185
            OnError::display($this->output, $error);
186
        }
187
188
        /**
189
         * {@inheritdoc}
190
         */
191
        public function addIncompleteTest(Test $test, \Throwable $t, float $time): void
192
        {
193
            $this->incompleteTests++;
194
            $this->section->incomplete($t);
195
        }
196
197
        /**
198
         * {@inheritdoc}
199
         */
200
        public function addRiskyTest(Test $test, \Throwable $t, float $time): void
201
        {
202
            $this->riskyTests++;
203
            $this->section->risky();
204
        }
205
206
        /**
207
         * {@inheritdoc}
208
         */
209
        public function addSkippedTest(Test $test, Throwable $t, float $time): void
210
        {
211
            $this->skippedTests++;
212
            $this->section->skipped($t);
213
        }
214
215
        /**
216
         * {@inheritdoc}
217
         */
218
        public function startTestSuite(TestSuite $suite): void
219
        {
220
            if ($this->totalTests === null) {
221
                $this->totalTests = $suite->count();
222
            }
223
        }
224
225
        /**
226
         * {@inheritdoc}
227
         */
228
        public function endTestSuite(TestSuite $suite): void
229
        {
230
            if (! $this->sectionEnded && $this->totalTests === $this->currentTestNumber) {
231
                $this->sectionEnded = true;
232
                $this->section->end();
233
                $this->output->writeln('');
234
235
                $tests = [];
236
237
                foreach (['warnings', 'risky', 'incomplete', 'skipped'] as $countName) {
238
                    if ($countTests = $this->{$countName . 'Tests'}) {
239
                        $tests[] = "<fg=yellow;options=bold>$countTests $countName</>";
240
                    }
241
                }
242
243
                if ($passedTests = $this->passedTests) {
244
                    $tests[] = "<fg=green;options=bold>$passedTests passed</>";
245
                }
246
247
                $totalTests = $this->totalTests;
248
                $tests[] = "$totalTests total";
249
250
                $this->output->writeln(
251
                    sprintf(
252
                        '  <fg=white;options=bold>Tests:  </><fg=default>%s</>',
253
                        implode(', ', $tests)
254
                    )
255
                );
256
257
                $timeElapsed = number_format($this->timer->result(), 2, '.', '');
258
                $this->output->writeln(
259
                    sprintf(
260
                        '  <fg=white;options=bold>Time:   </><fg=default>%ss</>',
261
                        $timeElapsed
262
                    )
263
                );
264
            }
265
        }
266
267
        /**
268
         * {@inheritdoc}
269
         */
270 1
        public function startTest(Test $test): void
271
        {
272 1
            if (! $test instanceof TestCase) {
273 1
                throw new ShouldNotHappen();
274
            }
275
276
            $this->currentTestNumber++;
277
278
            $this->section->runs($test);
279
        }
280
281
        /**
282
         * {@inheritdoc}
283
         */
284
        public function endTest(Test $test, float $time): void
285
        {
286
            if ($this->section->shouldPass) {
287
                $this->passedTests++;
288
                $this->section->pass();
289
            }
290
        }
291
292
        /**
293
         * Intencionally left blank as we
294
         * output things on events of the
295
         * listener.
296
         *
297
         * @param  string  $content
298
         *
299
         * @return  void
300
         */
301
        public function write(string $content): void
302
        {
303
            //
304
        }
305
    }
306
}
307