Skip to content

Commit 33429dd

Browse files
authored
Merge pull request #201 from PHPCSStandards/feature/filter-add-tests-for-gitmodified-gitstaged
Filters: add tests for GitModified and GitStaged filters + improve existing Filter test
2 parents 160eb6a + bea3903 commit 33429dd

File tree

6 files changed

+813
-51
lines changed

6 files changed

+813
-51
lines changed

src/Filters/GitModified.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ protected function getWhitelist()
3737
$modified = [];
3838

3939
$cmd = 'git ls-files -o -m --exclude-standard -- '.escapeshellarg($this->basedir);
40-
$output = [];
41-
exec($cmd, $output);
40+
$output = $this->exec($cmd);
4241

4342
$basedir = $this->basedir;
4443
if (is_dir($basedir) === false) {
@@ -63,4 +62,27 @@ protected function getWhitelist()
6362
}//end getWhitelist()
6463

6564

65+
/**
66+
* Execute an external command.
67+
*
68+
* {@internal This method is only needed to allow for mocking the return value
69+
* to test the class logic.}
70+
*
71+
* @param string $cmd Command.
72+
*
73+
* @return array
74+
*/
75+
protected function exec($cmd)
76+
{
77+
$output = [];
78+
$lastLine = exec($cmd, $output);
79+
if ($lastLine === false) {
80+
return [];
81+
}
82+
83+
return $output;
84+
85+
}//end exec()
86+
87+
6688
}//end class

src/Filters/GitStaged.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ protected function getWhitelist()
3939
$modified = [];
4040

4141
$cmd = 'git diff --cached --name-only -- '.escapeshellarg($this->basedir);
42-
$output = [];
43-
exec($cmd, $output);
42+
$output = $this->exec($cmd);
4443

4544
$basedir = $this->basedir;
4645
if (is_dir($basedir) === false) {
@@ -65,4 +64,27 @@ protected function getWhitelist()
6564
}//end getWhitelist()
6665

6766

67+
/**
68+
* Execute an external command.
69+
*
70+
* {@internal This method is only needed to allow for mocking the return value
71+
* to test the class logic.}
72+
*
73+
* @param string $cmd Command.
74+
*
75+
* @return array
76+
*/
77+
protected function exec($cmd)
78+
{
79+
$output = [];
80+
$lastLine = exec($cmd, $output);
81+
if ($lastLine === false) {
82+
return [];
83+
}
84+
85+
return $output;
86+
87+
}//end exec()
88+
89+
6890
}//end class
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
<?php
2+
/**
3+
* Tests for the \PHP_CodeSniffer\Filters\GitModified class.
4+
*
5+
* @author Juliette Reinders Folmer <phpcs_nospam@adviesenzo.nl>
6+
* @copyright 2023 PHPCSStandards Contributors
7+
* @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8+
*/
9+
10+
namespace PHP_CodeSniffer\Tests\Core\Filters;
11+
12+
use PHP_CodeSniffer\Config;
13+
use PHP_CodeSniffer\Filters\Filter;
14+
use PHP_CodeSniffer\Ruleset;
15+
use PHPUnit\Framework\TestCase;
16+
use RecursiveIteratorIterator;
17+
18+
/**
19+
* Base functionality and utilities for testing Filter classes.
20+
*/
21+
abstract class AbstractFilterTestCase extends TestCase
22+
{
23+
24+
/**
25+
* The Config object.
26+
*
27+
* @var \PHP_CodeSniffer\Config
28+
*/
29+
protected static $config;
30+
31+
/**
32+
* The Ruleset object.
33+
*
34+
* @var \PHP_CodeSniffer\Ruleset
35+
*/
36+
protected static $ruleset;
37+
38+
39+
/**
40+
* Initialize the config and ruleset objects.
41+
*
42+
* @beforeClass
43+
*
44+
* @return void
45+
*/
46+
public static function initializeConfigAndRuleset()
47+
{
48+
self::$config = new Config(['--standard=PSR1', '--extensions=php,inc/php,js,css', '--report-width=80']);
49+
self::$ruleset = new Ruleset(self::$config);
50+
51+
}//end initializeConfigAndRuleset()
52+
53+
54+
/**
55+
* Helper method to retrieve a mock object for a Filter class.
56+
*
57+
* The `setMethods()` method was silently deprecated in PHPUnit 9 and removed in PHPUnit 10.
58+
*
59+
* Note: direct access to the `getMockBuilder()` method is soft deprecated as of PHPUnit 10,
60+
* and expected to be hard deprecated in PHPUnit 11 and removed in PHPUnit 12.
61+
* Dealing with that is something for a later iteration of the test suite.
62+
*
63+
* @param string $className Fully qualified name of the class under test.
64+
* @param array<mixed> $constructorArgs Optional. Array of parameters to pass to the class constructor.
65+
* @param array<string>|null $methodsToMock Optional. The methods to mock in the class under test.
66+
* Needed for PHPUnit cross-version support as PHPUnit 4.x does
67+
* not have a `setMethodsExcept()` method yet.
68+
* If not passed, no methods will be replaced.
69+
*
70+
* @return \PHPUnit\Framework\MockObject\MockObject
71+
*/
72+
protected function getMockedClass($className, array $constructorArgs=[], $methodsToMock=null)
73+
{
74+
$mockedObj = $this->getMockBuilder($className);
75+
76+
if (\method_exists($mockedObj, 'onlyMethods') === true) {
77+
// PHPUnit 8+.
78+
if (is_array($methodsToMock) === true) {
79+
return $mockedObj
80+
->setConstructorArgs($constructorArgs)
81+
->onlyMethods($methodsToMock)
82+
->getMock();
83+
}
84+
85+
return $mockedObj->getMock()
86+
->setConstructorArgs($constructorArgs);
87+
}
88+
89+
// PHPUnit < 8.
90+
return $mockedObj
91+
->setConstructorArgs($constructorArgs)
92+
->setMethods($methodsToMock)
93+
->getMock();
94+
95+
}//end getMockedClass()
96+
97+
98+
/**
99+
* Retrieve an array of files which were accepted by a filter.
100+
*
101+
* @param \PHP_CodeSniffer\Filters\Filter $filter The Filter object under test.
102+
*
103+
* @return array<string>
104+
*/
105+
protected function getFilteredResultsAsArray(Filter $filter)
106+
{
107+
$iterator = new RecursiveIteratorIterator($filter);
108+
$files = [];
109+
foreach ($iterator as $file) {
110+
$files[] = $file;
111+
}
112+
113+
return $files;
114+
115+
}//end getFilteredResultsAsArray()
116+
117+
118+
/**
119+
* Retrieve the basedir to use for tests using the `getFakeFileList()` method.
120+
*
121+
* @return string
122+
*/
123+
protected static function getBaseDir()
124+
{
125+
return dirname(dirname(dirname(__DIR__)));
126+
127+
}//end getBaseDir()
128+
129+
130+
/**
131+
* Retrieve a file list containing a range of paths for testing purposes.
132+
*
133+
* This list **must** contain files which exist in this project (well, except for some which don't exist
134+
* purely for testing purposes), as `realpath()` is used in the logic under test and `realpath()` will
135+
* return `false` for any non-existent files, which will automatically filter them out before
136+
* we get to the code under test.
137+
*
138+
* Note this list does not include `.` and `..` as \PHP_CodeSniffer\Files\FileList uses `SKIP_DOTS`.
139+
*
140+
* @return array<string>
141+
*/
142+
protected static function getFakeFileList()
143+
{
144+
$basedir = self::getBaseDir();
145+
return [
146+
$basedir.'/.gitignore',
147+
$basedir.'/.yamllint.yml',
148+
$basedir.'/phpcs.xml',
149+
$basedir.'/phpcs.xml.dist',
150+
$basedir.'/autoload.php',
151+
$basedir.'/bin',
152+
$basedir.'/bin/phpcs',
153+
$basedir.'/bin/phpcs.bat',
154+
$basedir.'/scripts',
155+
$basedir.'/scripts/build-phar.php',
156+
$basedir.'/src',
157+
$basedir.'/src/WillNotExist.php',
158+
$basedir.'/src/WillNotExist.bak',
159+
$basedir.'/src/WillNotExist.orig',
160+
$basedir.'/src/Ruleset.php',
161+
$basedir.'/src/Generators',
162+
$basedir.'/src/Generators/Markdown.php',
163+
$basedir.'/src/Standards',
164+
$basedir.'/src/Standards/Generic',
165+
$basedir.'/src/Standards/Generic/Docs',
166+
$basedir.'/src/Standards/Generic/Docs/Classes',
167+
$basedir.'/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml',
168+
$basedir.'/src/Standards/Generic/Sniffs',
169+
$basedir.'/src/Standards/Generic/Sniffs/Classes',
170+
$basedir.'/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php',
171+
$basedir.'/src/Standards/Generic/Tests',
172+
$basedir.'/src/Standards/Generic/Tests/Classes',
173+
$basedir.'/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.1.inc',
174+
// Will rarely exist when running the tests.
175+
$basedir.'/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.1.inc.bak',
176+
$basedir.'/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.2.inc',
177+
$basedir.'/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.php',
178+
$basedir.'/src/Standards/Squiz',
179+
$basedir.'/src/Standards/Squiz/Docs',
180+
$basedir.'/src/Standards/Squiz/Docs/WhiteSpace',
181+
$basedir.'/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml',
182+
$basedir.'/src/Standards/Squiz/Sniffs',
183+
$basedir.'/src/Standards/Squiz/Sniffs/WhiteSpace',
184+
$basedir.'/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php',
185+
$basedir.'/src/Standards/Squiz/Tests',
186+
$basedir.'/src/Standards/Squiz/Tests/WhiteSpace',
187+
$basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc',
188+
$basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc.fixed',
189+
$basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js',
190+
$basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed',
191+
$basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php',
192+
];
193+
194+
}//end getFakeFileList()
195+
196+
197+
/**
198+
* Translate Linux paths to Windows paths, when necessary.
199+
*
200+
* These type of tests should be able to run and pass on both *nix as well as Windows
201+
* based dev systems. This method is a helper to allow for this.
202+
*
203+
* @param array<string|array> $paths A single or multi-dimensional array containing
204+
* file paths.
205+
*
206+
* @return array<string|array>
207+
*/
208+
protected static function mapPathsToRuntimeOs(array $paths)
209+
{
210+
if (DIRECTORY_SEPARATOR !== '\\') {
211+
return $paths;
212+
}
213+
214+
foreach ($paths as $key => $value) {
215+
if (is_string($value) === true) {
216+
$paths[$key] = strtr($value, '/', '\\\\');
217+
} else if (is_array($value) === true) {
218+
$paths[$key] = self::mapPathsToRuntimeOs($value);
219+
}
220+
}
221+
222+
return $paths;
223+
224+
}//end mapPathsToRuntimeOs()
225+
226+
227+
}//end class

0 commit comments

Comments
 (0)