1 | <?php |
||
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 |