-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #88 from Yoast/JRF/sniff-check-placement-testdoubles
New sniff to check that test double/mock classes are in the correct directory
- Loading branch information
Showing
14 changed files
with
321 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
<?php | ||
/** | ||
* YoastCS\Yoast\Sniffs\Files\TestDoublesSniff. | ||
* | ||
* @package Yoast\YoastCS | ||
* @author Juliette Reinders Folmer | ||
* @license https://opensource.org/licenses/MIT MIT | ||
*/ | ||
|
||
namespace YoastCS\Yoast\Sniffs\Files; | ||
|
||
use PHP_CodeSniffer\Sniffs\Sniff; | ||
use PHP_CodeSniffer\Files\File; | ||
|
||
/** | ||
* Check that all mock/doubles classes are in their own file and in a `doubles` directory. | ||
* | ||
* @package Yoast\YoastCS | ||
* | ||
* @since 1.0.0 | ||
*/ | ||
class TestDoublesSniff implements Sniff { | ||
|
||
/** | ||
* Relative path to the directory where the test doubles/mocks should be placed. | ||
* | ||
* The path should be relative to the root/basepath of the project and can be | ||
* customized from within a custom ruleset. | ||
* | ||
* @var string | ||
*/ | ||
public $doubles_path = '/tests/doubles'; | ||
|
||
/** | ||
* Target path for test double/mock classes or false if the intended | ||
* target directory doesn't exist. | ||
* | ||
* @var string|bool | ||
*/ | ||
protected $target_path; | ||
|
||
/** | ||
* Returns an array of tokens this test wants to listen for. | ||
* | ||
* @return array | ||
*/ | ||
public function register() { | ||
return array( | ||
T_CLASS, | ||
T_INTERFACE, | ||
T_TRAIT, | ||
); | ||
} | ||
|
||
/** | ||
* Processes this test, when one of its tokens is encountered. | ||
* | ||
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. | ||
* @param int $stackPtr The position of the current | ||
* in the stack passed in $tokens. | ||
* | ||
* @return void|int Void or StackPtr to the end of the file if no basepath was set. | ||
*/ | ||
public function process( File $phpcsFile, $stackPtr ) { | ||
// Stripping potential quotes to ensure `stdin_path` passed by IDEs does not include quotes. | ||
$file = preg_replace( '`^([\'"])(.*)\1$`Ds', '$2', $phpcsFile->getFileName() ); | ||
|
||
if ( 'STDIN' === $file ) { | ||
return; | ||
} | ||
|
||
$object_name = $phpcsFile->getDeclarationName( $stackPtr ); | ||
if ( empty( $object_name ) ) { | ||
return; | ||
} | ||
|
||
if ( stripos( $object_name, 'mock' ) === false && stripos( $object_name, 'double' ) === false ) { | ||
return; | ||
} | ||
|
||
if ( ! isset( $phpcsFile->config->basepath ) ) { | ||
$phpcsFile->addWarning( | ||
'For the TestDoubles sniff to be able to function, the --basepath needs to be set.', | ||
0, | ||
'MissingBasePath' | ||
); | ||
|
||
return ( $phpcsFile->numTokens + 1 ); | ||
} | ||
|
||
$base_path = $this->normalize_directory_separators( $phpcsFile->config->basepath ); | ||
if ( ! isset( $this->target_path ) || defined( 'PHP_CODESNIFFER_IN_TESTS' ) ) { | ||
$target_path = $base_path . '/'; | ||
$target_path .= ltrim( $this->normalize_directory_separators( $this->doubles_path ), '/' ); | ||
|
||
$this->target_path = false; | ||
if ( file_exists( $target_path ) && is_dir( $target_path ) ) { | ||
$this->target_path = strtolower( $target_path ); | ||
} | ||
} | ||
|
||
if ( false === $this->target_path ) { | ||
// Non-existent target path. | ||
$phpcsFile->addError( | ||
'Double/Mock test helper class detected, but no "%s" sub-directory found in "%s". Please create the sub-directory.', | ||
$stackPtr, | ||
'NoDoublesDirectory', | ||
array( | ||
$this->doubles_path, | ||
$base_path, | ||
) | ||
); | ||
} | ||
|
||
$path_info = pathinfo( $file ); | ||
if ( empty( $path_info['dirname'] ) ) { | ||
return; | ||
} | ||
|
||
$tokens = $phpcsFile->getTokens(); | ||
$dirname = $this->normalize_directory_separators( $path_info['dirname'] ); | ||
if ( false === $this->target_path || stripos( $dirname, $this->target_path ) === false ) { | ||
$phpcsFile->addError( | ||
'Double/Mock test helper classes should be placed in the "%s" sub-directory. Found %s: %s', | ||
$stackPtr, | ||
'WrongDirectory', | ||
array( | ||
$this->doubles_path, | ||
$tokens[ $stackPtr ]['content'], | ||
$object_name, | ||
) | ||
); | ||
} | ||
|
||
$more_objects_in_file = $phpcsFile->findNext( $this->register(), ( $stackPtr + 1 ) ); | ||
if ( false !== $more_objects_in_file ) { | ||
$phpcsFile->addError( | ||
'Double/Mock test helper classes should be in their own file. Found %s: %s', | ||
$stackPtr, | ||
'OneObjectPerFile', | ||
array( | ||
$tokens[ $stackPtr ]['content'], | ||
$object_name, | ||
) | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* Normalize all directory separators to be a forward slash. | ||
* | ||
* @param string $path Path to normalize. | ||
* | ||
* @return string | ||
*/ | ||
private function normalize_directory_separators( $path ) { | ||
return strtr( $path, '\\', '/' ); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<?php |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
<?php | ||
/** | ||
* Unit test class for Yoast Coding Standard. | ||
* | ||
* @package Yoast\YoastCS | ||
* @author Juliette Reinders Folmer | ||
* @license https://opensource.org/licenses/MIT MIT | ||
*/ | ||
|
||
namespace YoastCS\Yoast\Tests\Files; | ||
|
||
use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; | ||
|
||
/** | ||
* Unit test class for the TestDoubles sniff. | ||
* | ||
* @package Yoast\YoastCS | ||
* | ||
* @since 1.0.0 | ||
*/ | ||
class TestDoublesUnitTest extends AbstractSniffUnitTest { | ||
|
||
/** | ||
* Set CLI values before the file is tested. | ||
* | ||
* @param string $testFile The name of the file being tested. | ||
* @param \PHP_CodeSniffer\Config $config The config data for the test run. | ||
* | ||
* @return void | ||
*/ | ||
public function setCliValues( $testFile, $config ) { | ||
if ( $testFile === 'no-basepath.inc' ) { | ||
return; | ||
} | ||
|
||
$config->basepath = __DIR__ . DIRECTORY_SEPARATOR . 'TestDoublesUnitTests'; | ||
} | ||
|
||
/** | ||
* Get a list of all test files to check. | ||
* | ||
* @param string $testFileBase The base path that the unit tests files will have. | ||
* | ||
* @return string[] | ||
*/ | ||
protected function getTestFiles( $testFileBase ) { | ||
$sep = DIRECTORY_SEPARATOR; | ||
$test_files = glob( dirname( $testFileBase ) . $sep . 'TestDoublesUnitTests{' . $sep . ',' . $sep . '*' . $sep . '}*.inc', GLOB_BRACE ); | ||
|
||
if ( ! empty( $test_files ) ) { | ||
return $test_files; | ||
} | ||
|
||
return array( $testFileBase . '.inc' ); | ||
} | ||
|
||
/** | ||
* Returns the lines where errors should occur. | ||
* | ||
* @param string $testFile The name of the file being tested. | ||
* | ||
* @return array <int line number> => <int number of errors> | ||
*/ | ||
public function getErrorList( $testFile = '' ) { | ||
|
||
switch ( $testFile ) { | ||
// In tests/. | ||
case 'mock-not-in-correct-dir.inc': | ||
return array( | ||
3 => 1, | ||
); | ||
|
||
case 'multiple-objects-in-file.inc': | ||
return array( | ||
5 => 2, | ||
); | ||
|
||
case 'not-in-correct-custom-dir.inc': | ||
return array( | ||
4 => 2, | ||
); | ||
|
||
case 'not-in-correct-dir-double.inc': | ||
return array( | ||
3 => 1, | ||
); | ||
|
||
case 'not-in-correct-dir-mock.inc': | ||
return array( | ||
3 => 1, | ||
); | ||
|
||
case 'not-double-or-mock.inc': // In tests. | ||
case 'correct-dir-double.inc': // In tests/doubles. | ||
case 'correct-dir-mock.inc': // In tests/doubles. | ||
case 'correct-custom-dir.inc': // In tests/mocks. | ||
default: | ||
return array(); | ||
} | ||
} | ||
|
||
/** | ||
* Returns the lines where warnings should occur. | ||
* | ||
* @param string $testFile The name of the file being tested. | ||
* | ||
* @return array <int line number> => <int number of warnings> | ||
*/ | ||
public function getWarningList( $testFile = '' ) { | ||
if ( $testFile === 'no-basepath.inc' ) { | ||
return array( | ||
1 => 1, | ||
); | ||
} | ||
|
||
return array(); | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
Yoast/Tests/Files/TestDoublesUnitTests/tests/doubles/correct-dir-double.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<?php | ||
|
||
class Prefix_ClassName_Double {} |
3 changes: 3 additions & 0 deletions
3
Yoast/Tests/Files/TestDoublesUnitTests/tests/doubles/correct-dir-mock.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<?php | ||
|
||
class Prefix_ClassName_Mock {} |
3 changes: 3 additions & 0 deletions
3
Yoast/Tests/Files/TestDoublesUnitTests/tests/mock-not-in-correct-dir.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<?php | ||
|
||
class Mock_Prefix_ClassName {} |
6 changes: 6 additions & 0 deletions
6
Yoast/Tests/Files/TestDoublesUnitTests/tests/mocks/correct-custom-dir.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
@codingStandardsChangeSetting Yoast.Files.TestDoubles doubles_path /tests/mocks | ||
<?php | ||
|
||
class Prefix_ClassName_Double {} | ||
|
||
// @codingStandardsChangeSetting Yoast.Files.TestDoubles doubles_path /tests/doubles |
7 changes: 7 additions & 0 deletions
7
Yoast/Tests/Files/TestDoublesUnitTests/tests/multiple-objects-in-file.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?php | ||
|
||
use PHPUnit\Framework\TestCase; | ||
|
||
class Prefix_ClassName_Double {} | ||
|
||
class Test_ClassName extends extends TestCase {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<?php | ||
|
||
class Prefix_ClassName_Double {} |
3 changes: 3 additions & 0 deletions
3
Yoast/Tests/Files/TestDoublesUnitTests/tests/not-double-or-mock.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<?php | ||
|
||
class Prefix_ClassName {} |
6 changes: 6 additions & 0 deletions
6
Yoast/Tests/Files/TestDoublesUnitTests/tests/not-in-correct-custom-dir.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
@codingStandardsChangeSetting Yoast.Files.TestDoubles doubles_path /tests/assets | ||
<?php | ||
|
||
class Prefix_ClassName_Double {} | ||
|
||
// @codingStandardsChangeSetting Yoast.Files.TestDoubles doubles_path /tests/doubles |
3 changes: 3 additions & 0 deletions
3
Yoast/Tests/Files/TestDoublesUnitTests/tests/not-in-correct-dir-double.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<?php | ||
|
||
class Prefix_ClassName_Double {} |
3 changes: 3 additions & 0 deletions
3
Yoast/Tests/Files/TestDoublesUnitTests/tests/not-in-correct-dir-mock.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<?php | ||
|
||
class Prefix_ClassName_Mock {} |