Completed
Pull Request — master (#217)
by
unknown
03:02
created

ResultPrinter::getDefects()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5.0073

Importance

Changes 2
Bugs 2 Features 0
Metric Value
c 2
b 2
f 0
dl 0
loc 20
ccs 14
cts 15
cp 0.9333
rs 8.8571
cc 5
eloc 13
nc 3
nop 2
crap 5.0073
1
<?php
2
namespace ParaTest\Runners\PHPUnit;
3
4
use ParaTest\Logging\LogInterpreter;
5
use ParaTest\Logging\JUnit\Reader;
6
7
/**
8
 * Class ResultPrinter
9
 *
10
 * Used for outputing ParaTest results
11
 *
12
 * @package ParaTest\Runners\PHPUnit
13
 */
14
class ResultPrinter
15
{
16
    /**
17
     * A collection of ExecutableTest objects
18
     *
19
     * @var array
20
     */
21
    protected $suites = array();
22
23
    /**
24
     * @var \ParaTest\Logging\LogInterpreter
25
     */
26
    protected $results;
27
28
    /**
29
     * The number of tests results currently printed.
30
     * Used to determine when to tally current results
31
     * and start a new row
32
     *
33
     * @var int
34
     */
35
    protected $numTestsWidth;
36
37
    /**
38
     * Used for formatting results to a given width
39
     *
40
     * @var int
41
     */
42
    protected $maxColumn;
43
44
    /**
45
     * The total number of cases to be run
46
     *
47
     * @var int
48
     */
49
    protected $totalCases = 0;
50
51
    /**
52
     * The current column being printed to
53
     *
54
     * @var int
55
     */
56
    protected $column = 0;
57
58
    /**
59
     * @var \PHP_Timer
60
     */
61
    protected $timer;
62
63
    /**
64
     * The total number of cases printed so far
65
     *
66
     * @var int
67
     */
68
    protected $casesProcessed = 0;
69
70
    /**
71
     * Whether to display a red or green bar
72
     *
73
     * @var bool
74
     */
75
    protected $colors;
76
77
    /**
78
     * Warnings generated by the cases
79
     *
80
     * @var array
81
     */
82
    protected $warnings = array();
83
84
    /**
85
     * Number of columns
86
     *
87
     * @var integer
88
     */
89
    protected $numberOfColumns = 80;
90
91
    /**
92
     * Number of skipped or incomplete tests
93
     *
94
     * @var integer
95
     */
96
    protected $totalSkippedOrIncomplete = 0;
97
98
    /**
99
     * Do we need to try to process skipped/incompleted tests.
100
     *
101
     * @var boolean
102
     */
103
    protected $processSkipped = false;
104
105 28
    public function __construct(LogInterpreter $results)
106
    {
107 28
        $this->results = $results;
108 28
        $this->timer = new \PHP_Timer();
109 28
    }
110
111
    /**
112
     * Adds an ExecutableTest to the tracked results
113
     *
114
     * @param ExecutableTest $suite
115
     * @return $this
116
     */
117 16
    public function addTest(ExecutableTest $suite)
118
    {
119 16
        $this->suites[] = $suite;
120 16
        $increment = $suite->getTestCount();
121 16
        $this->totalCases = $this->totalCases + $increment;
122
123 16
        return $this;
124
    }
125
126
    /**
127
     * Initializes printing constraints, prints header
128
     * information and starts the test timer
129
     *
130
     * @param Options $options
131
     */
132 9
    public function start(Options $options)
133
    {
134 9
        $this->numTestsWidth = strlen((string) $this->totalCases);
135 9
        $this->maxColumn = $this->numberOfColumns
136 9
                         + (DIRECTORY_SEPARATOR == "\\" ? -1 : 0) // fix windows blank lines
137 9
                         - strlen($this->getProgress());
138 9
        printf(
139 9
            "\nRunning phpunit in %d process%s with %s%s\n\n",
140 9
            $options->processes,
0 ignored issues
show
Documentation introduced by
The property $processes is declared protected in ParaTest\Runners\PHPUnit\Options. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
141 9
            $options->processes > 1 ? 'es' : '',
0 ignored issues
show
Documentation introduced by
The property $processes is declared protected in ParaTest\Runners\PHPUnit\Options. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
142 9
            $options->phpunit,
0 ignored issues
show
Documentation introduced by
The property $phpunit is declared protected in ParaTest\Runners\PHPUnit\Options. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
143 9
            $options->functional ? '. Functional mode is ON.' : ''
0 ignored issues
show
Documentation introduced by
The property $functional is declared protected in ParaTest\Runners\PHPUnit\Options. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
144 9
        );
145 9
        if (isset($options->filtered['configuration'])) {
0 ignored issues
show
Documentation introduced by
The property $filtered is declared protected in ParaTest\Runners\PHPUnit\Options. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
146 9
            printf("Configuration read from %s\n\n", $options->filtered['configuration']->getPath());
0 ignored issues
show
Documentation introduced by
The property $filtered is declared protected in ParaTest\Runners\PHPUnit\Options. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
147 9
        }
148 9
        $this->timer->start();
149 9
        $this->colors = $options->colors;
150 9
        $this->processSkipped = $this->isSkippedIncompleTestCanBeTracked($options);
151 9
    }
152
153
    /**
154
     * @param string $string
155
     */
156 2
    public function println($string = "")
157
    {
158 2
        $this->column = 0;
159 2
        print("$string\n");
160 2
    }
161
162
    /**
163
     * Prints all results and removes any log files
164
     * used for aggregating results
165
     */
166
    public function flush()
167
    {
168
        $this->printResults();
169
        $this->clearLogs();
170
    }
171
172
    /**
173
     * Print final results
174
     */
175
    public function printResults()
176
    {
177
        print $this->getHeader();
178
        print $this->getErrors();
179
        print $this->getFailures();
180
        print $this->getWarnings();
181
        print $this->getFooter();
182
    }
183
184
    /**
185
     * Prints the individual "quick" feedback for run
186
     * tests, that is the ".EF" items
187
     *
188
     * @param ExecutableTest $test
189
     */
190 12
    public function printFeedback(ExecutableTest $test)
191
    {
192
        try {
193 12
            $reader = new Reader($test->getTempFile());
194 12
        } catch (\InvalidArgumentException $e) {
195
            throw new \RuntimeException(sprintf(
196
                "%s\n" .
197
                "The process: %s\n" .
198
                "This means a PHPUnit process was unable to run \"%s\"\n" ,
199
                $e->getMessage(),
200
                $test->getLastCommand(),
201
                $test->getPath()
202
            ));
203
        }
204 12
        if (!$reader->hasResults()) {
205 1
            throw new \RuntimeException(sprintf(
206
                "The process: %s\nLog file \"%s\" is empty.\n" .
207 1
                "This means a PHPUnit process was unable to run \"%s\"\n" .
208 1
                "Maybe there is more than one class in this file.",
209 1
                $test->getLastCommand(),
210 1
                $test->getTempFile(),
211 1
                $test->getPath()
212 1
            ));
213
        }
214 11
        $this->results->addReader($reader);
215 11
        $this->processReaderFeedback($reader, $test->getTestCount());
216 11
        $this->printTestWarnings($test);
217 11
    }
218
219
    /**
220
     * Returns the header containing resource usage
221
     *
222
     * @return string
223
     */
224 1
    public function getHeader()
225
    {
226 1
        return "\n\n" . $this->timer->resourceUsage() . "\n\n";
227
    }
228
229
    /**
230
     * Add an array of warning strings. These cause the test run to be shown
231
     * as failed
232
     */
233
    public function addWarnings(array $warnings)
234
    {
235
        $this->warnings = array_merge($this->warnings, $warnings);
236
    }
237
238
    /**
239
     * Returns warning messages as a string
240
     */
241
    public function getWarnings()
242
    {
243
        return $this->getDefects($this->warnings, 'warning');
244
    }
245
246
    /**
247
     * Whether the test run is successful and has no warnings
248
     *
249
     * @return bool
250
     */
251 2
    public function isSuccessful()
252
    {
253 2
        return $this->results->isSuccessful() && count($this->warnings) == 0;
254
    }
255
256
    /**
257
     * Return the footer information reporting success
258
     * or failure
259
     *
260
     * @return string
261
     */
262 2
    public function getFooter()
263
    {
264 2
        return $this->isSuccessful()
265 2
                    ? $this->getSuccessFooter()
266 2
                    : $this->getFailedFooter();
267
    }
268
269
    /**
270
     * Returns the failure messages
271
     *
272
     * @return string
273
     */
274 1
    public function getFailures()
275
    {
276 1
        $failures = $this->results->getFailures();
0 ignored issues
show
Documentation Bug introduced by
The method getFailures does not exist on object<ParaTest\Logging\LogInterpreter>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
277
278 1
        return $this->getDefects($failures, 'failure');
279
    }
280
281
    /**
282
     * Returns error messages
283
     *
284
     * @return string
285
     */
286 2
    public function getErrors()
287
    {
288 2
        $errors = $this->results->getErrors();
0 ignored issues
show
Documentation Bug introduced by
The method getErrors does not exist on object<ParaTest\Logging\LogInterpreter>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
289
290 2
        return $this->getDefects($errors, 'error');
291
    }
292
293
    /**
294
     * Returns the total cases being printed
295
     *
296
     * @return int
297
     */
298 2
    public function getTotalCases()
299
    {
300 2
        return $this->totalCases;
301
    }
302
303
    /**
304
     * Process reader feedback and print it.
305
     *
306
     * @param  Reader $reader
307
     * @param  int    $expectedTestCount
308
     */
309 11
    protected function processReaderFeedback($reader, $expectedTestCount)
310
    {
311 11
        $feedbackItems = $reader->getFeedback();
312
313 11
        $actualTestCount = count($feedbackItems);
314
315 11
        $this->processTestOverhead($actualTestCount, $expectedTestCount);
316
317 11
        foreach ($feedbackItems as $item) {
318 11
            $this->printFeedbackItem($item);
319 11
        }
320
321 11
        if ($this->processSkipped) {
322 4
            $this->printSkippedAndIncomplete($actualTestCount, $expectedTestCount);
323 4
        }
324 11
    }
325
326
    /**
327
     * Prints test warnings.
328
     *
329
     * @param  ExecutableTest $test
330
     */
331 11
    protected function printTestWarnings($test)
332
    {
333 11
        $warnings = $test->getWarnings();
334 11
        if ($warnings) {
335
            $this->addWarnings($warnings);
336
            foreach ($warnings as $warning) {
337
                $this->printFeedbackItem('W');
338
            }
339
        }
340 11
    }
341
342
    /**
343
     * Is skipped/incomplete amount can be properly processed.
344
     *
345
     * @todo Skipped/Incomplete test tracking available only in functional mode for now
346
     *       or in regular mode but without group/exclude-group filters.
347
     *
348
     * @return boolean
349
     */
350 9
    protected function isSkippedIncompleTestCanBeTracked($options)
351
    {
352 9
        return $options->functional
353 9
            || (empty($options->groups) && empty($options->excludeGroups));
354
    }
355
356
    /**
357
     * Process test overhead.
358
     *
359
     * In some situations phpunit can return more tests then we expect and in that case
360
     * this method correct total amount of tests so paratest progress will be auto corrected.
361
     *
362
     * @todo May be we need to throw Exception here instead of silent correction.
363
     *
364
     * @param  int $actualTestCount
365
     * @param  int $expectedTestCount
366
     */
367 11
    protected function processTestOverhead($actualTestCount, $expectedTestCount)
368
    {
369 11
        $overhead = $actualTestCount - $expectedTestCount;
370 11
        if ($this->processSkipped) {
371 4
            if ($overhead > 0) {
372 1
                $this->totalCases += $overhead;
373 1
            } else {
374 3
                $this->totalSkippedOrIncomplete += -$overhead;
375
            }
376 4
        } else {
377 7
            $this->totalCases += $overhead;
378
        }
379 11
    }
380
381
    /**
382
     * Prints S for skipped and incomplete tests.
383
     *
384
     * If for some reason process return less tests than expected then we threat all remaining
385
     * as skipped or incomplete and print them as skipped (S letter)
386
     *
387
     * @param  int $actualTestCount
388
     * @param  int $expectedTestCount
389
     */
390 4
    protected function printSkippedAndIncomplete($actualTestCount, $expectedTestCount)
391
    {
392 4
        $overhead = $expectedTestCount - $actualTestCount;
393 4
        if ($overhead > 0) {
394
            for ($i = 0; $i < $overhead; $i++) {
395
                $this->printFeedbackItem("S");
396
            }
397
        }
398 4
    }
399
400
    /**
401
     * Prints a single "quick" feedback item and increments
402
     * the total number of processed cases and the column
403
     * position
404
     *
405
     * @param $item
406
     */
407 11
    protected function printFeedbackItem($item)
408
    {
409 11
        print $item;
410 11
        $this->column++;
411 11
        $this->casesProcessed++;
412 11
        if ($this->column == $this->maxColumn) {
413 2
            print $this->getProgress();
414 2
            $this->println();
415 2
        }
416 11
    }
417
418
    /**
419
     * Method that returns a formatted string
420
     * for a collection of errors or failures
421
     *
422
     * @param array $defects
423
     * @param $type
424
     * @return string
425
     */
426 3
    protected function getDefects(array $defects, $type)
427
    {
428 3
        $count = sizeof($defects);
429 3
        if ($count == 0) {
430
            return '';
431
        }
432 3
        $output = sprintf(
433 3
            "There %s %d %s%s:\n",
434 3
            ($count == 1) ? 'was' : 'were',
435 3
            $count,
436 3
            $type,
437 3
            ($count == 1) ? '' : 's'
438 3
        );
439
440 3
        for ($i = 1; $i <= sizeof($defects); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
441 3
            $output .= sprintf("\n%d) %s\n", $i, $defects[$i - 1]);
442 3
        }
443
444 3
        return $output;
445
    }
446
447
    /**
448
     * Prints progress for large test collections
449
     */
450 9
    protected function getProgress()
451
    {
452 9
        return sprintf(
453 9
            ' %' . $this->numTestsWidth . 'd / %' . $this->numTestsWidth . 'd (%3s%%)',
454 9
            $this->casesProcessed,
455 9
            $this->totalCases,
456 9
            floor(($this->totalCases ? $this->casesProcessed / $this->totalCases : 0) * 100)
457 9
        );
458
    }
459
460
    /**
461
     * Get the footer for a test collection that had tests with
462
     * failures or errors
463
     *
464
     * @return string
465
     */
466 1
    private function getFailedFooter()
467
    {
468 1
        $formatString = "FAILURES!\nTests: %d, Assertions: %d, Failures: %d, Errors: %d.\n";
469
470 1
        return "\n" . $this->red(
471 1
            sprintf(
472 1
                $formatString,
473 1
                $this->results->getTotalTests(),
0 ignored issues
show
Documentation Bug introduced by
The method getTotalTests does not exist on object<ParaTest\Logging\LogInterpreter>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
474 1
                $this->results->getTotalAssertions(),
0 ignored issues
show
Documentation Bug introduced by
The method getTotalAssertions does not exist on object<ParaTest\Logging\LogInterpreter>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
475 1
                $this->results->getTotalFailures(),
0 ignored issues
show
Documentation Bug introduced by
The method getTotalFailures does not exist on object<ParaTest\Logging\LogInterpreter>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
476 1
                $this->results->getTotalErrors()
0 ignored issues
show
Documentation Bug introduced by
The method getTotalErrors does not exist on object<ParaTest\Logging\LogInterpreter>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
477 1
            )
478 1
        );
479
    }
480
481
    /**
482
     * Get the footer for a test collection containing all successful
483
     * tests
484
     *
485
     * @return string
486
     */
487 1
    private function getSuccessFooter()
488
    {
489 1
        $tests = $this->totalCases;
490 1
        $asserts = $this->results->getTotalAssertions();
0 ignored issues
show
Documentation Bug introduced by
The method getTotalAssertions does not exist on object<ParaTest\Logging\LogInterpreter>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
491
492 1
        if ($this->totalSkippedOrIncomplete > 0) {
493
            // phpunit 4.5 produce NOT plural version for test(s) and assertion(s) in that case
494
            // also it shows result in standard color scheme
495
            return sprintf(
496
                "OK, but incomplete, skipped, or risky tests!\n"
497
                . "Tests: %d, Assertions: %d, Incomplete: %d.\n",
498
                $tests,
499
                $asserts,
500
                $this->totalSkippedOrIncomplete
501
            );
502
        } else {
503
            // phpunit 4.5 produce plural version for test(s) and assertion(s) in that case
504
            // also it shows result as black text on green background
505 1
            return $this->green(sprintf(
506 1
                "OK (%d test%s, %d assertion%s)\n",
507 1
                $tests,
508 1
                ($tests == 1) ? '' : 's',
509 1
                $asserts,
510 1
                ($asserts == 1) ? '' : 's'
511 1
            ));
512
        }
513
    }
514
515 1
    private function green($text)
516
    {
517 1
        if ($this->colors) {
518
            return "\x1b[30;42m\x1b[2K"
519
                . $text
520
                . "\x1b[0m\x1b[2K";
521
        }
522 1
        return $text;
523
    }
524
525 1
    private function red($text)
526
    {
527 1
        if ($this->colors) {
528
            return "\x1b[37;41m\x1b[2K"
529
                . $text
530
                . "\x1b[0m\x1b[2K";
531
        }
532 1
        return $text;
533
    }
534
535
    /**
536
     * Deletes all the temporary log files for ExecutableTest objects
537
     * being printed
538
     */
539
    private function clearLogs()
540
    {
541
        foreach ($this->suites as $suite) {
542
            $suite->deleteFile();
543
        }
544
    }
545
}
546