Completed
Pull Request — master (#86)
by Alessandro
05:32
created

LogPrinter::startTestSuite()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 25
Code Lines 15

Duplication

Lines 3
Ratio 12 %

Code Coverage

Tests 14
CRAP Score 4.0047

Importance

Changes 0
Metric Value
dl 3
loc 25
ccs 14
cts 15
cp 0.9333
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 15
nc 3
nop 1
crap 4.0047
1
<?php
2
3
namespace Paraunit\Parser\JSON;
4
5
/**
6
 * This class comes from \PHPUnit_Util_Log_JSON.
7
 * It's copied and refactored here because it's deprecated in PHPUnit 5.7 and it will be dropped in PHPUnit 6
8
 *
9
 * Class LogPrinter
10
 * @package Paraunit\Parser\JSON
11
 */
12
class LogPrinter extends \PHPUnit_Util_Printer implements \PHPUnit_Framework_TestListener
13
{
14
    /** @var string */
15
    private $logDirectory;
16
17
    /** @var int */
18
    private $testSuiteLevel;
19
20
    /**
21
     * LogPrinter constructor.
22
     * @param mixed $out
23
     */
24 10
    public function __construct($out = null)
25
    {
26 10
        if (substr($out, -1) !== DIRECTORY_SEPARATOR) {
27 10
            $out .= DIRECTORY_SEPARATOR;
28
        }
29
30 10
        $this->logDirectory = $out;
31 10
        $this->testSuiteLevel = 0;
32 10
    }
33
34
    /**
35
     * An error occurred.
36
     *
37
     * @param \PHPUnit_Framework_Test $test
38
     * @param \Exception              $e
39
     * @param float                   $time
40
     */
41 1 View Code Duplication
    public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
42
    {
43 1
        $this->writeCase(
44 1
            'error',
45
            $time,
46 1
            \PHPUnit_Util_Filter::getFilteredStacktrace($e, false),
0 ignored issues
show
Bug introduced by
It seems like \PHPUnit_Util_Filter::ge...edStacktrace($e, false) targeting PHPUnit_Util_Filter::getFilteredStacktrace() can also be of type string; however, Paraunit\Parser\JSON\LogPrinter::writeCase() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
47 1
            \PHPUnit_Framework_TestFailure::exceptionToString($e),
48
            $test
0 ignored issues
show
Documentation introduced by
$test is of type object<PHPUnit_Framework_Test>, but the function expects a object<PHPUnit_Framework_TestCase>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
49
        );
50
51 1
        $this->currentTestPass = false;
0 ignored issues
show
Bug introduced by
The property currentTestPass does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
52 1
    }
53
54
    /**
55
     * A warning occurred.
56
     *
57
     * @param \PHPUnit_Framework_Test    $test
58
     * @param \PHPUnit_Framework_Warning $e
59
     * @param float                      $time
60
     */
61 1 View Code Duplication
    public function addWarning(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_Warning $e, $time)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
62
    {
63 1
        $this->writeCase(
64 1
            'warning',
65
            $time,
66 1
            \PHPUnit_Util_Filter::getFilteredStacktrace($e, false),
0 ignored issues
show
Bug introduced by
It seems like \PHPUnit_Util_Filter::ge...edStacktrace($e, false) targeting PHPUnit_Util_Filter::getFilteredStacktrace() can also be of type string; however, Paraunit\Parser\JSON\LogPrinter::writeCase() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
67 1
            \PHPUnit_Framework_TestFailure::exceptionToString($e),
68
            $test
0 ignored issues
show
Documentation introduced by
$test is of type object<PHPUnit_Framework_Test>, but the function expects a object<PHPUnit_Framework_TestCase>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
69
        );
70
71 1
        $this->currentTestPass = false;
72 1
    }
73
74
    /**
75
     * A failure occurred.
76
     *
77
     * @param \PHPUnit_Framework_Test                 $test
78
     * @param \PHPUnit_Framework_AssertionFailedError $e
79
     * @param float                                   $time
80
     */
81 1 View Code Duplication
    public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
82
    {
83 1
        $this->writeCase(
84 1
            'fail',
85
            $time,
86 1
            \PHPUnit_Util_Filter::getFilteredStacktrace($e, false),
0 ignored issues
show
Bug introduced by
It seems like \PHPUnit_Util_Filter::ge...edStacktrace($e, false) targeting PHPUnit_Util_Filter::getFilteredStacktrace() can also be of type string; however, Paraunit\Parser\JSON\LogPrinter::writeCase() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
87 1
            \PHPUnit_Framework_TestFailure::exceptionToString($e),
88
            $test
0 ignored issues
show
Documentation introduced by
$test is of type object<PHPUnit_Framework_Test>, but the function expects a object<PHPUnit_Framework_TestCase>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
89
        );
90
91 1
        $this->currentTestPass = false;
92 1
    }
93
94
    /**
95
     * Incomplete test.
96
     *
97
     * @param \PHPUnit_Framework_Test $test
98
     * @param \Exception              $e
99
     * @param float                   $time
100
     */
101 1 View Code Duplication
    public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
102
    {
103 1
        $this->writeCase(
104 1
            'error',
105
            $time,
106 1
            \PHPUnit_Util_Filter::getFilteredStacktrace($e, false),
0 ignored issues
show
Bug introduced by
It seems like \PHPUnit_Util_Filter::ge...edStacktrace($e, false) targeting PHPUnit_Util_Filter::getFilteredStacktrace() can also be of type string; however, Paraunit\Parser\JSON\LogPrinter::writeCase() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
107 1
            'Incomplete Test: ' . $e->getMessage(),
108
            $test
0 ignored issues
show
Documentation introduced by
$test is of type object<PHPUnit_Framework_Test>, but the function expects a object<PHPUnit_Framework_TestCase>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
109
        );
110
111 1
        $this->currentTestPass = false;
112 1
    }
113
114
    /**
115
     * Risky test.
116
     *
117
     * @param \PHPUnit_Framework_Test $test
118
     * @param \Exception              $e
119
     * @param float                   $time
120
     */
121 1 View Code Duplication
    public function addRiskyTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
122
    {
123 1
        $this->writeCase(
124 1
            'error',
125
            $time,
126 1
            \PHPUnit_Util_Filter::getFilteredStacktrace($e, false),
0 ignored issues
show
Bug introduced by
It seems like \PHPUnit_Util_Filter::ge...edStacktrace($e, false) targeting PHPUnit_Util_Filter::getFilteredStacktrace() can also be of type string; however, Paraunit\Parser\JSON\LogPrinter::writeCase() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
127 1
            'Risky Test: ' . $e->getMessage(),
128
            $test
0 ignored issues
show
Documentation introduced by
$test is of type object<PHPUnit_Framework_Test>, but the function expects a object<PHPUnit_Framework_TestCase>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
129
        );
130
131 1
        $this->currentTestPass = false;
132 1
    }
133
134
    /**
135
     * Skipped test.
136
     *
137
     * @param \PHPUnit_Framework_Test $test
138
     * @param \Exception              $e
139
     * @param float                   $time
140
     */
141 1 View Code Duplication
    public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
142
    {
143 1
        $this->writeCase(
144 1
            'error',
145
            $time,
146 1
            \PHPUnit_Util_Filter::getFilteredStacktrace($e, false),
0 ignored issues
show
Bug introduced by
It seems like \PHPUnit_Util_Filter::ge...edStacktrace($e, false) targeting PHPUnit_Util_Filter::getFilteredStacktrace() can also be of type string; however, Paraunit\Parser\JSON\LogPrinter::writeCase() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
147 1
            'Skipped Test: ' . $e->getMessage(),
148
            $test
0 ignored issues
show
Documentation introduced by
$test is of type object<PHPUnit_Framework_Test>, but the function expects a object<PHPUnit_Framework_TestCase>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
149
        );
150
151 1
        $this->currentTestPass = false;
152 1
    }
153
154
    /**
155
     * A testsuite started.
156
     *
157
     * @param \PHPUnit_Framework_TestSuite $suite
158
     */
159 9
    public function startTestSuite(\PHPUnit_Framework_TestSuite $suite)
160
    {
161 9
        if ($this->testSuiteLevel === 0) {
162 9
            $logFilename = $this->getLogFilename($suite);
163
164 9
            $logDir = dirname($logFilename);
165 9 View Code Duplication
            if (! @mkdir($logDir, 0777, true) && !is_dir($logDir)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
166
                throw new \RuntimeException('Cannot create folder for JSON logs');
167
            }
168
169 9
            $this->out = fopen($logFilename, 'wt');
170
        }
171
172 9
        $this->testSuiteLevel++;
173 9
        $this->currentTestSuiteName = $suite->getName();
0 ignored issues
show
Bug introduced by
The property currentTestSuiteName does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
174 9
        $this->currentTestName      = '';
0 ignored issues
show
Bug introduced by
The property currentTestName does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
175
176 9
        $this->write(
177
            array(
0 ignored issues
show
Documentation introduced by
array('event' => 'suiteS...ests' => count($suite)) is of type array<string,string|inte...ng","tests":"integer"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
178 9
                'event' => 'suiteStart',
179 9
                'suite' => $this->currentTestSuiteName,
180 9
                'tests' => count($suite)
181
            )
182
        );
183 9
    }
184
185
    /**
186
     * A testsuite ended.
187
     *
188
     * @param \PHPUnit_Framework_TestSuite $suite
189
     */
190 1
    public function endTestSuite(\PHPUnit_Framework_TestSuite $suite)
191
    {
192 1
        $this->testSuiteLevel--;
193 1
        $this->currentTestSuiteName = '';
194 1
        $this->currentTestName      = '';
195 1
    }
196
197
    /**
198
     * A test started.
199
     *
200
     * @param \PHPUnit_Framework_Test $test
201
     */
202 7
    public function startTest(\PHPUnit_Framework_Test $test)
203
    {
204 7
        $this->currentTestName = \PHPUnit_Util_Test::describe($test);
205 7
        $this->currentTestPass = true;
206
207 7
        $this->write(
208
            array(
0 ignored issues
show
Documentation introduced by
array('event' => 'testSt...$this->currentTestName) is of type array<string,*,{"event":...suite":"?","test":"*"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
209 7
                'event' => 'testStart',
210 7
                'suite' => $this->currentTestSuiteName,
211 7
                'test'  => $this->currentTestName
212
            )
213
        );
214 7
    }
215
216
    /**
217
     * A test ended.
218
     *
219
     * @param \PHPUnit_Framework_Test $test
220
     * @param float                  $time
221
     */
222 1
    public function endTest(\PHPUnit_Framework_Test $test, $time)
223
    {
224 1
        if ($this->currentTestPass) {
225 1
            $this->writeCase('pass', $time, array(), '', $test);
0 ignored issues
show
Documentation introduced by
$test is of type object<PHPUnit_Framework_Test>, but the function expects a object<PHPUnit_Framework_TestCase>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
226
        }
227 1
    }
228
229
    /**
230
     * @param string                           $status
231
     * @param float                            $time
232
     * @param array                            $trace
233
     * @param string                           $message
234
     * @param \PHPUnit_Framework_TestCase|null $test
235
     */
236 7
    protected function writeCase($status, $time, array $trace = array(), $message = '', $test = null)
237
    {
238 7
        $output = '';
239
        // take care of TestSuite producing error (e.g. by running into exception) as TestSuite doesn't have hasOutput
240 7
        if ($test !== null && method_exists($test, 'hasOutput') && $test->hasOutput()) {
241
            $output = $test->getActualOutput();
242
        }
243 7
        $this->write(
244
            array(
0 ignored issues
show
Documentation introduced by
array('event' => 'test',...), 'output' => $output) is of type array<string,?,{"event":...ng","output":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
245 7
                'event'   => 'test',
246 7
                'suite'   => $this->currentTestSuiteName,
247 7
                'test'    => $this->currentTestName,
248 7
                'status'  => $status,
249 7
                'time'    => $time,
250 7
                'trace'   => $trace,
251 7
                'message' => \PHPUnit_Util_String::convertToUtf8($message),
252 7
                'output'  => $output,
253
            )
254
        );
255 7
    }
256
257
    /**
258
     * @param string $buffer
259
     */
260
    public function write($buffer)
261
    {
262 9
        array_walk_recursive($buffer, function (&$input) {
263 9
            if (is_string($input)) {
264 9
                $input = \PHPUnit_Util_String::convertToUtf8($input);
265
            }
266 9
        });
267
268 9
        $flags = 0;
269
270 9
        if (defined('JSON_PRETTY_PRINT')) {
271 9
            $flags |= JSON_PRETTY_PRINT;
272
        }
273
274 9
        parent::write(json_encode($buffer, $flags));
275 9
    }
276
277
    /**
278
     * @param \PHPUnit_Framework_TestSuite $suite
279
     * @return string
280
     */
281 10
    private function getLogFilename(\PHPUnit_Framework_TestSuite $suite)
282
    {
283 10
        $testFilename = $this->getTestFilename($suite);
284
        
285 10
        return $this->logDirectory . md5($testFilename) . '.json.log';
286
    }
287
288
    /**
289
     * @param \PHPUnit_Framework_TestSuite $suite
290
     * @return string
291
     */
292 10
    private function getTestFilename(\PHPUnit_Framework_TestSuite $suite)
293
    {
294 10
        $reflection = new \ReflectionClass($suite->getName());
295
        
296 10
        return $reflection->getFileName();
297
    }
298
}
299