Completed
Push — master ( 70f161...72dc5f )
by Julian
10s
created

ResultPrinter::printFeedback()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2.5

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 7
cts 14
cp 0.5
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 14
nc 2
nop 1
crap 2.5
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 27
    public function __construct(LogInterpreter $results)
106
    {
107 27
        $this->results = $results;
108 27
        $this->timer = new \PHP_Timer();
109 27
    }
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 2
    public function printResults()
176
    {
177 2
        print $this->getHeader();
178 2
        print $this->getErrors();
179 2
        print $this->getFailures();
180 2
        print $this->getWarnings();
181 2
        print $this->getFooter();
182 2
    }
183
184
    /**
185
     * Prints the individual "quick" feedback for run
186
     * tests, that is the ".EF" items
187
     *
188
     * @param ExecutableTest $test
189
     */
190 11
    public function printFeedback(ExecutableTest $test)
191
    {
192
        try {
193 11
            $reader = new Reader($test->getTempFile());
194 11
        } 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 11
        $this->results->addReader($reader);
205 11
        $this->processReaderFeedback($reader, $test->getTestCount());
206 11
        $this->printTestWarnings($test);
207 11
    }
208
209
    /**
210
     * Returns the header containing resource usage
211
     *
212
     * @return string
213
     */
214 3
    public function getHeader()
215
    {
216 3
        return "\n\n" . $this->timer->resourceUsage() . "\n\n";
217
    }
218
219
    /**
220
     * Add an array of warning strings. These cause the test run to be shown
221
     * as failed
222
     */
223
    public function addWarnings(array $warnings)
224
    {
225
        $this->warnings = array_merge($this->warnings, $warnings);
226
    }
227
228
    /**
229
     * Returns warning messages as a string
230
     */
231 2
    public function getWarnings()
232
    {
233 2
        return $this->getDefects($this->warnings, 'warning');
234
    }
235
236
    /**
237
     * Whether the test run is successful and has no warnings
238
     *
239
     * @return bool
240
     */
241 4
    public function isSuccessful()
242
    {
243 4
        return $this->results->isSuccessful() && count($this->warnings) == 0;
244
    }
245
246
    /**
247
     * Return the footer information reporting success
248
     * or failure
249
     *
250
     * @return string
251
     */
252 4
    public function getFooter()
253
    {
254 4
        return $this->isSuccessful()
255 4
                    ? $this->getSuccessFooter()
256 4
                    : $this->getFailedFooter();
257
    }
258
259
    /**
260
     * Returns the failure messages
261
     *
262
     * @return string
263
     */
264 3
    public function getFailures()
265
    {
266 3
        $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...
267
268 3
        return $this->getDefects($failures, 'failure');
269
    }
270
271
    /**
272
     * Returns error messages
273
     *
274
     * @return string
275
     */
276 4
    public function getErrors()
277
    {
278 4
        $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...
279
280 4
        return $this->getDefects($errors, 'error');
281
    }
282
283
    /**
284
     * Returns the total cases being printed
285
     *
286
     * @return int
287
     */
288 2
    public function getTotalCases()
289
    {
290 2
        return $this->totalCases;
291
    }
292
293
    /**
294
     * Process reader feedback and print it.
295
     *
296
     * @param  Reader $reader
297
     * @param  int    $expectedTestCount
298
     */
299 11
    protected function processReaderFeedback($reader, $expectedTestCount)
300
    {
301 11
        $feedbackItems = $reader->getFeedback();
302
303 11
        $actualTestCount = count($feedbackItems);
304
305 11
        $this->processTestOverhead($actualTestCount, $expectedTestCount);
306
307 11
        foreach ($feedbackItems as $item) {
308 11
            $this->printFeedbackItem($item);
309 11
        }
310
311 11
        if ($this->processSkipped) {
312 4
            $this->printSkippedAndIncomplete($actualTestCount, $expectedTestCount);
313 4
        }
314 11
    }
315
316
    /**
317
     * Prints test warnings.
318
     *
319
     * @param  ExecutableTest $test
320
     */
321 11
    protected function printTestWarnings($test)
322
    {
323 11
        $warnings = $test->getWarnings();
324 11
        if ($warnings) {
325
            $this->addWarnings($warnings);
326
            foreach ($warnings as $warning) {
327
                $this->printFeedbackItem('W');
328
            }
329
        }
330 11
    }
331
332
    /**
333
     * Is skipped/incomplete amount can be properly processed.
334
     *
335
     * @todo Skipped/Incomplete test tracking available only in functional mode for now
336
     *       or in regular mode but without group/exclude-group filters.
337
     *
338
     * @return boolean
339
     */
340 9
    protected function isSkippedIncompleTestCanBeTracked($options)
341
    {
342 9
        return $options->functional
343 9
            || (empty($options->groups) && empty($options->excludeGroups));
344
    }
345
346
    /**
347
     * Process test overhead.
348
     *
349
     * In some situations phpunit can return more tests then we expect and in that case
350
     * this method correct total amount of tests so paratest progress will be auto corrected.
351
     *
352
     * @todo May be we need to throw Exception here instead of silent correction.
353
     *
354
     * @param  int $actualTestCount
355
     * @param  int $expectedTestCount
356
     */
357 11
    protected function processTestOverhead($actualTestCount, $expectedTestCount)
358
    {
359 11
        $overhead = $actualTestCount - $expectedTestCount;
360 11
        if ($this->processSkipped) {
361 4
            if ($overhead > 0) {
362 1
                $this->totalCases += $overhead;
363 1
            } else {
364 3
                $this->totalSkippedOrIncomplete += -$overhead;
365
            }
366 4
        } else {
367 7
            $this->totalCases += $overhead;
368
        }
369 11
    }
370
371
    /**
372
     * Prints S for skipped and incomplete tests.
373
     *
374
     * If for some reason process return less tests than expected then we threat all remaining
375
     * as skipped or incomplete and print them as skipped (S letter)
376
     *
377
     * @param  int $actualTestCount
378
     * @param  int $expectedTestCount
379
     */
380 4
    protected function printSkippedAndIncomplete($actualTestCount, $expectedTestCount)
381
    {
382 4
        $overhead = $expectedTestCount - $actualTestCount;
383 4
        if ($overhead > 0) {
384
            for ($i = 0; $i < $overhead; $i++) {
385
                $this->printFeedbackItem("S");
386
            }
387
        }
388 4
    }
389
390
    /**
391
     * Prints a single "quick" feedback item and increments
392
     * the total number of processed cases and the column
393
     * position
394
     *
395
     * @param $item
396
     */
397 11
    protected function printFeedbackItem($item)
398
    {
399 11
        print $item;
400 11
        $this->column++;
401 11
        $this->casesProcessed++;
402 11
        if ($this->column == $this->maxColumn) {
403 2
            print $this->getProgress();
404 2
            $this->println();
405 2
        }
406 11
    }
407
408
    /**
409
     * Method that returns a formatted string
410
     * for a collection of errors or failures
411
     *
412
     * @param array $defects
413
     * @param $type
414
     * @return string
415
     */
416 5
    protected function getDefects(array $defects, $type)
417
    {
418 5
        $count = sizeof($defects);
419 5
        if ($count == 0) {
420 2
            return '';
421
        }
422 5
        $output = sprintf(
423 5
            "There %s %d %s%s:\n",
424 5
            ($count == 1) ? 'was' : 'were',
425 5
            $count,
426 5
            $type,
427 5
            ($count == 1) ? '' : 's'
428 5
        );
429
430 5
        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...
431 5
            $output .= sprintf("\n%d) %s\n", $i, $defects[$i - 1]);
432 5
        }
433
434 5
        return $output;
435
    }
436
437
    /**
438
     * Prints progress for large test collections
439
     */
440 9
    protected function getProgress()
441
    {
442 9
        return sprintf(
443 9
            ' %' . $this->numTestsWidth . 'd / %' . $this->numTestsWidth . 'd (%3s%%)',
444 9
            $this->casesProcessed,
445 9
            $this->totalCases,
446 9
            floor(($this->totalCases ? $this->casesProcessed / $this->totalCases : 0) * 100)
447 9
        );
448
    }
449
450
    /**
451
     * Get the footer for a test collection that had tests with
452
     * failures or errors
453
     *
454
     * @return string
455
     */
456 3
    private function getFailedFooter()
457
    {
458 3
        $formatString = "FAILURES!\nTests: %d, Assertions: %d, Failures: %d, Errors: %d.\n";
459
460 3
        return "\n" . $this->red(
461 3
            sprintf(
462 3
                $formatString,
463 3
                $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...
464 3
                $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...
465 3
                $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...
466 3
                $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...
467 3
            )
468 3
        );
469
    }
470
471
    /**
472
     * Get the footer for a test collection containing all successful
473
     * tests
474
     *
475
     * @return string
476
     */
477 1
    private function getSuccessFooter()
478
    {
479 1
        $tests = $this->totalCases;
480 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...
481
482 1
        if ($this->totalSkippedOrIncomplete > 0) {
483
            // phpunit 4.5 produce NOT plural version for test(s) and assertion(s) in that case
484
            // also it shows result in standard color scheme
485
            return sprintf(
486
                "OK, but incomplete, skipped, or risky tests!\n"
487
                . "Tests: %d, Assertions: %d, Incomplete: %d.\n",
488
                $tests,
489
                $asserts,
490
                $this->totalSkippedOrIncomplete
491
            );
492
        } else {
493
            // phpunit 4.5 produce plural version for test(s) and assertion(s) in that case
494
            // also it shows result as black text on green background
495 1
            return $this->green(sprintf(
496 1
                "OK (%d test%s, %d assertion%s)\n",
497 1
                $tests,
498 1
                ($tests == 1) ? '' : 's',
499 1
                $asserts,
500 1
                ($asserts == 1) ? '' : 's'
501 1
            ));
502
        }
503
    }
504
505 1
    private function green($text)
506
    {
507 1
        if ($this->colors) {
508
            return "\x1b[30;42m\x1b[2K"
509
                . $text
510
                . "\x1b[0m\x1b[2K";
511
        }
512 1
        return $text;
513
    }
514
515 3
    private function red($text)
516
    {
517 3
        if ($this->colors) {
518
            return "\x1b[37;41m\x1b[2K"
519
                . $text
520
                . "\x1b[0m\x1b[2K";
521
        }
522 3
        return $text;
523
    }
524
525
    /**
526
     * Deletes all the temporary log files for ExecutableTest objects
527
     * being printed
528
     */
529
    private function clearLogs()
530
    {
531
        foreach ($this->suites as $suite) {
532
            $suite->deleteFile();
533
        }
534
    }
535
}
536