Completed
Branch feature/scrutinizer-run-tests (072b5a)
by Juliette
10:12
created

BaseSniffTest::assertNoViolation()   D

Complexity

Conditions 9
Paths 10

Size

Total Lines 38
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 38
rs 4.909
cc 9
eloc 20
nc 10
nop 2
1
<?php
2
/**
3
 * Base sniff test class file
4
 *
5
 * @package PHPCompatibility
6
 */
7
8
/**
9
 * BaseSniffTest
10
 *
11
 * Adds PHPCS sniffing logic and custom assertions for PHPCS errors and
12
 * warnings
13
 *
14
 * @uses PHPUnit_Framework_TestCase
15
 * @package PHPCompatibility
16
 * @author Jansen Price <[email protected]>
17
 */
18
class BaseSniffTest extends PHPUnit_Framework_TestCase
19
{
20
    /**
21
     * The PHP_CodeSniffer object used for testing.
22
     *
23
     * @var PHP_CodeSniffer
24
     */
25
    protected static $phpcs = null;
26
27
    /**
28
     * An array of PHPCS results by filename and PHP version.
29
     *
30
     * @var array
31
     */
32
    public static $sniffFiles = array();
33
34
    /**
35
     * Sets up this unit test.
36
     *
37
     * @return void
38
     */
39
    public static function setUpBeforeClass()
40
    {
41
        self::$sniffFiles = array();
42
    }
43
44
    /**
45
     * Sets up this unit test.
46
     *
47
     * @return void
48
     */
49
    protected function setUp()
50
    {
51
        if (self::$phpcs === null) {
52
            self::$phpcs = new PHP_CodeSniffer();
53
        }
54
55
        PHP_CodeSniffer::setConfigData('testVersion', null, true);
56
        if (method_exists('PHP_CodeSniffer_CLI', 'setCommandLineValues')) { // For PHPCS 2.x
57
            self::$phpcs->cli->setCommandLineValues(array('-pq', '--colors'));
58
        }
59
60
        self::$phpcs->process(array(), dirname( __FILE__ ) . '/../PHPCompatibility/');
61
        self::$phpcs->setIgnorePatterns(array());
62
    }
63
64
    /**
65
     * Tear down after each test
66
     *
67
     * @return void
68
     */
69
    public function tearDown()
70
    {
71
        // Reset any settingsStandard (targetPhpVersion)
72
        self::$phpcs->cli->settingsStandard = array();
73
    }
74
75
    /**
76
     * Tear down after each test
77
     *
78
     * @return void
79
     */
80
    public static function tearDownAfterClass()
81
    {
82
        self::$sniffFiles = array();
83
    }
84
85
    /**
86
     * Sniff a file and return resulting file object
87
     *
88
     * @param string $filename Filename to sniff
89
     * @param string $targetPhpVersion Value of 'testVersion' to set on PHPCS object
90
     * @return PHP_CodeSniffer_File File object|false
91
     */
92
    public function sniffFile($filename, $targetPhpVersion = null)
93
    {
94
        if ( isset(self::$sniffFiles[$filename][$targetPhpVersion])) {
95
            return self::$sniffFiles[$filename][$targetPhpVersion];
96
        }
97
98
        if (null !== $targetPhpVersion) {
99
            PHP_CodeSniffer::setConfigData('testVersion', $targetPhpVersion, true);
100
        }
101
102
        $pathToFile = realpath(dirname(__FILE__)) . DIRECTORY_SEPARATOR . $filename;
103
        try {
104
            self::$sniffFiles[$filename][$targetPhpVersion] = self::$phpcs->processFile($pathToFile);
105
        } catch (Exception $e) {
106
            $this->fail('An unexpected exception has been caught: ' . $e->getMessage());
107
            return false;
108
        }
109
110
        return self::$sniffFiles[$filename][$targetPhpVersion];
111
    }
112
113
    /**
114
     * Assert a PHPCS error on a particular line number
115
     *
116
     * @param PHP_CodeSniffer_File $file Codesniffer file object
117
     * @param int $lineNumber Line number
118
     * @param string $expectedMessage Expected error message (assertContains)
119
     * @return bool
120
     */
121
    public function assertError(PHP_CodeSniffer_File $file, $lineNumber, $expectedMessage)
122
    {
123
        $errors = $this->gatherErrors($file);
124
125
        return $this->assertForType($errors, 'error', $lineNumber, $expectedMessage);
126
    }
127
128
    /**
129
     * Assert a PHPCS warning on a particular line number
130
     *
131
     * @param PHP_CodeSniffer_File $file Codesniffer file object
132
     * @param int $lineNumber Line number
133
     * @param string $expectedMessage Expected message (assertContains)
134
     * @return bool
135
     */
136
    public function assertWarning(PHP_CodeSniffer_File $file, $lineNumber, $expectedMessage)
137
    {
138
        $warnings = $this->gatherWarnings($file);
139
140
        return $this->assertForType($warnings, 'warning', $lineNumber, $expectedMessage);
141
    }
142
143
    /**
144
     * Assert a PHPCS error or warning on a particular line number.
145
     *
146
     * @param array  $issues          Array of issues of a particular type.
147
     * @param string $type            The type of issues, either 'error' or 'warning'.
148
     * @param int    $lineNumber      Line number.
149
     * @param string $expectedMessage Expected message (assertContains).
150
     * @return bool
151
     */
152
    private function assertForType($issues, $type, $lineNumber, $expectedMessage)
153
    {
154
        if (!isset($issues[$lineNumber])) {
155
            throw new Exception("Expected $type '$expectedMessage' on line number $lineNumber, but none found.");
156
        }
157
158
        $insteadFoundMessages = array();
159
160
        // Concat any error messages so we can do an assertContains
161
        foreach ($issues[$lineNumber] as $issue) {
162
            $insteadFoundMessages[] = $issue['message'];
163
        }
164
165
        $insteadMessagesString = implode(', ', $insteadFoundMessages);
166
        return $this->assertContains(
167
            $expectedMessage, $insteadMessagesString,
168
            "Expected $type message '$expectedMessage' on line $lineNumber not found. Instead found: $insteadMessagesString."
169
        );
170
    }
171
172
    /**
173
     * Assert no violation (warning or error) on a given line number
174
     *
175
     * @param PHP_CodeSniffer_File $file Codesniffer File object
176
     * @param mixed $lineNumber Line number
177
     * @return bool
178
     */
179
    public function assertNoViolation(PHP_CodeSniffer_File $file, $lineNumber = 0)
180
    {
181
        $errors   = $this->gatherErrors($file);
182
        $warnings = $this->gatherWarnings($file);
183
184
        if (!count($errors) && !count($warnings)) {
185
            return $this->assertTrue(true);
186
        }
187
188
        if ($lineNumber == 0) {
189
            $allMessages = $errors + $warnings;
190
            // TODO: Update the fail message to give the tester some
191
            // indication of what the errors or warnings were
192
            return $this->assertEmpty($allMessages, 'Failed asserting no violations in file');
193
        }
194
195
        $encounteredMessages = array();
196
        if (isset($errors[$lineNumber])) {
197
            foreach ($errors[$lineNumber] as $error) {
198
                $encounteredMessages[] = 'ERROR: ' . $error['message'];
199
            }
200
        }
201
202
        if (isset($warnings[$lineNumber])) {
203
            foreach ($warnings[$lineNumber] as $warning) {
204
                $encounteredMessages[] = 'WARNING: ' . $warning['message'];
205
            }
206
        }
207
208
        if (!count($encounteredMessages)) {
209
            return $this->assertTrue(true);
210
        }
211
212
        $failMessage = "Failed asserting no standards violation on line $lineNumber: "
213
            . implode(', ', $encounteredMessages);
214
215
        $this->assertEmpty($encounteredMessages, $failMessage);
216
    }
217
218
    /**
219
     * Show violations in file by line number
220
     *
221
     * This is useful for debugging sniffs on a file
222
     *
223
     * @param PHP_CodeSniffer_File $file Codesniffer file object
224
     * @return void
225
     */
226
    public function showViolations(PHP_CodeSniffer_File $file)
227
    {
228
        $violations = array(
229
            'errors'   => $this->gatherErrors($file),
230
            'warnings' => $this->gatherWarnings($file),
231
        );
232
233
        return $violations;
234
    }
235
236
    /**
237
     * Gather all error messages by line number from phpcs file result
238
     *
239
     * @param PHP_CodeSniffer_File $file Codesniffer File object
240
     * @return array
241
     */
242
    public function gatherErrors(PHP_CodeSniffer_File $file)
243
    {
244
        $foundErrors = $file->getErrors();
245
246
        return $this->gatherIssues($foundErrors);
247
    }
248
249
    /**
250
     * Gather all warning messages by line number from phpcs file result
251
     *
252
     * @param PHP_CodeSniffer_File $file Codesniffer File object
253
     * @return array
254
     */
255
    public function gatherWarnings(PHP_CodeSniffer_File $file)
256
    {
257
        $foundWarnings = $file->getWarnings();
258
259
        return $this->gatherIssues($foundWarnings);
260
    }
261
    
262
    /**
263
     * Gather all messages or a particular type by line number.
264
     *
265
     * @param array $IssuesArray Array of a particular type of issues,
266
	 *                           i.e. errors or warnings.
267
     * @return array
268
     */
269
    private function gatherIssues($issuesArray)
270
    {
271
        $allIssues = array();
272
        foreach ($issuesArray as $line => $lineIssues) {
273
            foreach ($lineIssues as $column => $issues) {
274
                foreach ($issues as $issue) {
275
276
                    if (!isset($allIssues[$line])) {
277
                        $allIssues[$line] = array();
278
                    }
279
280
                    $allIssues[$line][] = $issue;
281
                }
282
            }
283
        }
284
285
        return $allIssues;
286
    }
287
}
288
289