Completed
Push — master ( 743834...4ffa9b )
by Julian
12s
created

ResultPrinter   C

Complexity

Total Complexity 58

Size/Duplication

Total Lines 530
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 82.18%

Importance

Changes 0
Metric Value
wmc 58
lcom 1
cbo 5
dl 0
loc 530
ccs 143
cts 174
cp 0.8218
rs 6.3005
c 0
b 0
f 0

28 Methods

Rating   Name   Duplication   Size   Complexity  
A addTest() 0 8 1
B start() 0 20 5
A println() 0 5 1
A flush() 0 5 1
A printResults() 0 8 1
A printFeedback() 0 18 2
A getHeader() 0 4 1
A addWarnings() 0 4 1
A getWarnings() 0 4 1
A isSuccessful() 0 4 2
A getFooter() 0 6 2
A getFailures() 0 6 1
A getErrors() 0 6 1
A getTotalCases() 0 4 1
A processReaderFeedback() 0 19 4
A printTestWarnings() 0 10 3
A __construct() 0 5 1
A isSkippedIncompleTestCanBeTracked() 0 5 3
A processTestOverhead() 0 13 3
A printSkippedAndIncomplete() 0 9 3
A printFeedbackItem() 0 10 2
A getProgress() 0 9 2
A green() 0 10 2
A red() 0 10 2
A clearLogs() 0 6 2
B getDefects() 0 20 5
A getFailedFooter() 0 14 1
B getSuccessFooter() 0 26 4

How to fix   Complexity   

Complex Class

Complex classes like ResultPrinter often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ResultPrinter, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace ParaTest\Runners\PHPUnit;
4
5
use ParaTest\Logging\JUnit\Reader;
6
use ParaTest\Logging\LogInterpreter;
7
8
/**
9
 * Class ResultPrinter.
10
 *
11
 * Used for outputing ParaTest results
12
 */
13
class ResultPrinter
14
{
15
    /**
16
     * A collection of ExecutableTest objects.
17
     *
18
     * @var array
19
     */
20
    protected $suites = [];
21
22
    /**
23
     * @var \ParaTest\Logging\LogInterpreter
24
     */
25
    protected $results;
26
27
    /**
28
     * The number of tests results currently printed.
29
     * Used to determine when to tally current results
30
     * and start a new row.
31
     *
32
     * @var int
33
     */
34
    protected $numTestsWidth;
35
36
    /**
37
     * Used for formatting results to a given width.
38
     *
39
     * @var int
40
     */
41
    protected $maxColumn;
42
43
    /**
44
     * The total number of cases to be run.
45
     *
46
     * @var int
47
     */
48
    protected $totalCases = 0;
49
50
    /**
51
     * The current column being printed to.
52
     *
53
     * @var int
54
     */
55
    protected $column = 0;
56
57
    /**
58
     * @var \PHP_Timer
59
     */
60
    protected $timer;
61
62
    /**
63
     * The total number of cases printed so far.
64
     *
65
     * @var int
66
     */
67
    protected $casesProcessed = 0;
68
69
    /**
70
     * Whether to display a red or green bar.
71
     *
72
     * @var bool
73
     */
74
    protected $colors;
75
76
    /**
77
     * Warnings generated by the cases.
78
     *
79
     * @var array
80
     */
81
    protected $warnings = [];
82
83
    /**
84
     * Number of columns.
85
     *
86
     * @var int
87
     */
88
    protected $numberOfColumns = 80;
89
90
    /**
91
     * Number of skipped or incomplete tests.
92
     *
93
     * @var int
94
     */
95
    protected $totalSkippedOrIncomplete = 0;
96
97
    /**
98
     * Do we need to try to process skipped/incompleted tests.
99
     *
100
     * @var bool
101
     */
102
    protected $processSkipped = false;
103
104 27
    public function __construct(LogInterpreter $results)
105
    {
106 27
        $this->results = $results;
107 27
        $this->timer = new \PHP_Timer();
108 27
    }
109
110
    /**
111
     * Adds an ExecutableTest to the tracked results.
112
     *
113
     * @param ExecutableTest $suite
114
     *
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
        );
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
        }
148 9
        $this->timer->start();
149 9
        $this->colors = $options->colors;
0 ignored issues
show
Documentation introduced by
The property $colors 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...
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
        echo "$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
        echo $this->getHeader();
178 2
        echo $this->getErrors();
179 2
        echo $this->getFailures();
180 2
        echo $this->getWarnings();
181 2
        echo $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
        } 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 1
                    ? $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
            if ($item === 'S') {
310 11
                ++$this->totalSkippedOrIncomplete;
311
            }
312
        }
313
314 11
        if ($this->processSkipped) {
315 4
            $this->printSkippedAndIncomplete($actualTestCount, $expectedTestCount);
316
        }
317 11
    }
318
319
    /**
320
     * Prints test warnings.
321
     *
322
     * @param ExecutableTest $test
323
     */
324 11
    protected function printTestWarnings($test)
325
    {
326 11
        $warnings = $test->getWarnings();
327 11
        if ($warnings) {
328
            $this->addWarnings($warnings);
329
            foreach ($warnings as $warning) {
330
                $this->printFeedbackItem('W');
331
            }
332
        }
333 11
    }
334
335
    /**
336
     * Is skipped/incomplete amount can be properly processed.
337
     *
338
     * @todo Skipped/Incomplete test tracking available only in functional mode for now
339
     *       or in regular mode but without group/exclude-group filters.
340
     *
341
     * @param mixed $options
342
     *
343
     * @return bool
344
     */
345 9
    protected function isSkippedIncompleTestCanBeTracked($options)
346
    {
347 9
        return $options->functional
348 9
            || (empty($options->groups) && empty($options->excludeGroups));
349
    }
350
351
    /**
352
     * Process test overhead.
353
     *
354
     * In some situations phpunit can return more tests then we expect and in that case
355
     * this method correct total amount of tests so paratest progress will be auto corrected.
356
     *
357
     * @todo May be we need to throw Exception here instead of silent correction.
358
     *
359
     * @param int $actualTestCount
360
     * @param int $expectedTestCount
361
     */
362 11
    protected function processTestOverhead($actualTestCount, $expectedTestCount)
363
    {
364 11
        $overhead = $actualTestCount - $expectedTestCount;
365 11
        if ($this->processSkipped) {
366 4
            if ($overhead > 0) {
367 1
                $this->totalCases += $overhead;
368
            } else {
369 4
                $this->totalSkippedOrIncomplete += -$overhead;
370
            }
371
        } else {
372 7
            $this->totalCases += $overhead;
373
        }
374 11
    }
375
376
    /**
377
     * Prints S for skipped and incomplete tests.
378
     *
379
     * If for some reason process return less tests than expected then we threat all remaining
380
     * as skipped or incomplete and print them as skipped (S letter)
381
     *
382
     * @param int $actualTestCount
383
     * @param int $expectedTestCount
384
     */
385 4
    protected function printSkippedAndIncomplete($actualTestCount, $expectedTestCount)
386
    {
387 4
        $overhead = $expectedTestCount - $actualTestCount;
388 4
        if ($overhead > 0) {
389
            for ($i = 0; $i < $overhead; ++$i) {
390
                $this->printFeedbackItem('S');
391
            }
392
        }
393 4
    }
394
395
    /**
396
     * Prints a single "quick" feedback item and increments
397
     * the total number of processed cases and the column
398
     * position.
399
     *
400
     * @param $item
401
     */
402 11
    protected function printFeedbackItem($item)
403
    {
404 11
        echo $item;
405 11
        ++$this->column;
406 11
        ++$this->casesProcessed;
407 11
        if ($this->column === $this->maxColumn) {
408 2
            echo $this->getProgress();
409 2
            $this->println();
410
        }
411 11
    }
412
413
    /**
414
     * Method that returns a formatted string
415
     * for a collection of errors or failures.
416
     *
417
     * @param array $defects
418
     * @param $type
419
     *
420
     * @return string
421
     */
422 5
    protected function getDefects(array $defects, $type)
423
    {
424 5
        $count = count($defects);
425 5
        if ($count === 0) {
426 2
            return '';
427
        }
428 5
        $output = sprintf(
429 5
            "There %s %d %s%s:\n",
430 5
            ($count === 1) ? 'was' : 'were',
431 5
            $count,
432 5
            $type,
433 5
            ($count === 1) ? '' : 's'
434
        );
435
436 5
        for ($i = 1; $i <= count($defects); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() 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...
437 5
            $output .= sprintf("\n%d) %s\n", $i, $defects[$i - 1]);
438
        }
439
440 5
        return $output;
441
    }
442
443
    /**
444
     * Prints progress for large test collections.
445
     */
446 9
    protected function getProgress()
447
    {
448 9
        return sprintf(
449 9
            ' %' . $this->numTestsWidth . 'd / %' . $this->numTestsWidth . 'd (%3s%%)',
450 9
            $this->casesProcessed,
451 9
            $this->totalCases,
452 9
            floor(($this->totalCases ? $this->casesProcessed / $this->totalCases : 0) * 100)
453
        );
454
    }
455
456
    /**
457
     * Get the footer for a test collection that had tests with
458
     * failures or errors.
459
     *
460
     * @return string
461
     */
462 3
    private function getFailedFooter()
463
    {
464 3
        $formatString = "FAILURES!\nTests: %d, Assertions: %d, Failures: %d, Errors: %d.\n";
465
466 3
        return "\n" . $this->red(
467 3
            sprintf(
468 3
                $formatString,
469 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...
470 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...
471 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...
472 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...
473
            )
474
        );
475
    }
476
477
    /**
478
     * Get the footer for a test collection containing all successful
479
     * tests.
480
     *
481
     * @return string
482
     */
483 1
    private function getSuccessFooter()
484
    {
485 1
        $tests = $this->totalCases;
486 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...
487
488 1
        if ($this->totalSkippedOrIncomplete > 0) {
489
            // phpunit 4.5 produce NOT plural version for test(s) and assertion(s) in that case
490
            // also it shows result in standard color scheme
491
            return sprintf(
492
                "OK, but incomplete, skipped, or risky tests!\n"
493
                . "Tests: %d, Assertions: %d, Incomplete: %d.\n",
494
                $tests,
495
                $asserts,
496
                $this->totalSkippedOrIncomplete
497
            );
498
        }
499
            // phpunit 4.5 produce plural version for test(s) and assertion(s) in that case
500
            // also it shows result as black text on green background
501 1
            return $this->green(sprintf(
502 1
                "OK (%d test%s, %d assertion%s)\n",
503 1
                $tests,
504 1
                ($tests === 1) ? '' : 's',
505 1
                $asserts,
506 1
                ($asserts === 1) ? '' : 's'
507
            ));
508
    }
509
510 1
    private function green($text)
511
    {
512 1
        if ($this->colors) {
513
            return "\x1b[30;42m\x1b[2K"
514
                . $text
515
                . "\x1b[0m\x1b[2K";
516
        }
517
518 1
        return $text;
519
    }
520
521 3
    private function red($text)
522
    {
523 3
        if ($this->colors) {
524
            return "\x1b[37;41m\x1b[2K"
525
                . $text
526
                . "\x1b[0m\x1b[2K";
527
        }
528
529 3
        return $text;
530
    }
531
532
    /**
533
     * Deletes all the temporary log files for ExecutableTest objects
534
     * being printed.
535
     */
536
    private function clearLogs()
537
    {
538
        foreach ($this->suites as $suite) {
539
            $suite->deleteFile();
540
        }
541
    }
542
}
543