diff --git a/.github/workflows/quicktest.yml b/.github/workflows/quicktest.yml index 6bee46b36a..7e6ab04c13 100644 --- a/.github/workflows/quicktest.yml +++ b/.github/workflows/quicktest.yml @@ -60,14 +60,14 @@ jobs: - name: 'PHPUnit: run the full test suite' if: ${{ matrix.os != 'windows-latest' }} - run: php "vendor/bin/phpunit" tests/AllTests.php --no-coverage + run: php "vendor/bin/phpunit" --no-coverage - name: 'PHPUnit: run tests which may have different outcomes on Windows' if: ${{ matrix.os == 'windows-latest' }} - run: php "vendor/bin/phpunit" tests/AllTests.php --group Windows --no-coverage + run: php "vendor/bin/phpunit" --group Windows --no-coverage - name: 'PHPUnit: run select tests in CBF mode' - run: php "vendor/bin/phpunit" tests/AllTests.php --group CBF --exclude-group nothing --no-coverage + run: php "vendor/bin/phpunit" --group CBF --exclude-group nothing --no-coverage env: PHP_CODESNIFFER_CBF: '1' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a09c8dd92f..8c0bbee159 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -204,11 +204,11 @@ jobs: - name: 'PHPUnit: run the full test suite without code coverage' if: ${{ matrix.skip_tests != true }} - run: php "vendor/bin/phpunit" tests/AllTests.php --no-coverage + run: php "vendor/bin/phpunit" --no-coverage - name: 'PHPUnit: run select tests in CBF mode' if: ${{ matrix.skip_tests != true }} - run: php "vendor/bin/phpunit" tests/AllTests.php --group CBF --exclude-group nothing --no-coverage + run: php "vendor/bin/phpunit" --group CBF --exclude-group nothing --no-coverage env: PHP_CODESNIFFER_CBF: '1' @@ -307,13 +307,13 @@ jobs: - name: "Run the unit tests with code coverage" if: ${{ matrix.os != 'windows-latest' }} run: > - php "vendor/bin/phpunit" tests/AllTests.php + php "vendor/bin/phpunit" ${{ steps.phpunit_version.outputs.VERSION >= '9.3' && '--coverage-cache ./build/phpunit-cache' || '' }} - name: "Run select tests in CBF mode with code coverage" if: ${{ matrix.os != 'windows-latest' }} run: > - php "vendor/bin/phpunit" tests/AllTests.php + php "vendor/bin/phpunit" ${{ steps.phpunit_version.outputs.VERSION >= '9.3' && '--coverage-cache ./build/phpunit-cache' || '' }} --group CBF --exclude-group nothing --coverage-clover build/logs/clover-cbf.xml env: @@ -322,7 +322,7 @@ jobs: - name: "Run the unit tests which may have different outcomes on Windows with code coverage" if: ${{ matrix.os == 'windows-latest' }} run: > - php "vendor/bin/phpunit" tests/AllTests.php --group Windows + php "vendor/bin/phpunit" --group Windows ${{ steps.phpunit_version.outputs.VERSION >= '9.3' && '--coverage-cache ./build/phpunit-cache' || '' }} - name: "Upload coverage results to Coveralls (normal run)" diff --git a/composer.json b/composer.json index a42168dc5f..3f00316224 100644 --- a/composer.json +++ b/composer.json @@ -59,15 +59,15 @@ ], "test": [ "Composer\\Config::disableProcessTimeout", - "@php ./vendor/phpunit/phpunit/phpunit tests/AllTests.php --no-coverage" + "@php ./vendor/phpunit/phpunit/phpunit --no-coverage" ], "coverage": [ "Composer\\Config::disableProcessTimeout", - "@php ./vendor/phpunit/phpunit/phpunit tests/AllTests.php -d max_execution_time=0" + "@php ./vendor/phpunit/phpunit/phpunit -d max_execution_time=0" ], "coverage-local": [ "Composer\\Config::disableProcessTimeout", - "@php ./vendor/phpunit/phpunit/phpunit tests/AllTests.php --coverage-html ./build/coverage-html -d max_execution_time=0" + "@php ./vendor/phpunit/phpunit/phpunit --coverage-html ./build/coverage-html -d max_execution_time=0" ], "build": [ "Composer\\Config::disableProcessTimeout", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index cf2b588c86..db04053844 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -13,8 +13,17 @@ forceCoversAnnotation="true" > - - tests/AllTests.php + + ./tests/Core/ + + + ./src/Standards/Generic/Tests/ + ./src/Standards/PEAR/Tests/ + ./src/Standards/PSR1/Tests/ + ./src/Standards/PSR2/Tests/ + ./src/Standards/PSR12/Tests/ + ./src/Standards/Squiz/Tests/ + ./src/Standards/Zend/Tests/ diff --git a/tests/AllTests.php b/tests/AllTests.php deleted file mode 100644 index 0002ab7daa..0000000000 --- a/tests/AllTests.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) - * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - */ - -namespace PHP_CodeSniffer\Tests; - -require_once 'Core/AllTests.php'; -require_once 'Standards/AllSniffs.php'; -require_once 'TestSuite.php'; - -class PHP_CodeSniffer_AllTests -{ - - - /** - * Add all PHP_CodeSniffer test suites into a single test suite. - * - * @return \PHPUnit\Framework\TestSuite - */ - public static function suite() - { - $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'] = []; - $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'] = []; - - // Use a special PHP_CodeSniffer test suite so that we can - // unset our autoload function after the run. - $suite = new TestSuite('PHP CodeSniffer'); - - $suite->addTest(Core\AllTests::suite()); - $suite->addTest(Standards\AllSniffs::suite()); - - return $suite; - - }//end suite() - - -}//end class diff --git a/tests/Core/AllTests.php b/tests/Core/AllTests.php deleted file mode 100644 index a5465f9878..0000000000 --- a/tests/Core/AllTests.php +++ /dev/null @@ -1,63 +0,0 @@ - - * @author Juliette Reinders Folmer - * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) - * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - */ - -namespace PHP_CodeSniffer\Tests\Core; - -use PHP_CodeSniffer\Tests\FileList; -use PHPUnit\Framework\TestSuite; -use PHPUnit\TextUI\TestRunner; - -class AllTests -{ - - - /** - * Prepare the test runner. - * - * @return void - */ - public static function main() - { - TestRunner::run(self::suite()); - - }//end main() - - - /** - * Add all core unit tests into a test suite. - * - * @return \PHPUnit\Framework\TestSuite - */ - public static function suite() - { - $suite = new TestSuite('PHP CodeSniffer Core'); - - $testFileIterator = new FileList(__DIR__, '', '`Test\.php$`Di'); - foreach ($testFileIterator->fileIterator as $file) { - if (strpos($file, 'AbstractMethodUnitTest.php') !== false) { - continue; - } - - include_once $file; - - $class = str_replace(__DIR__, '', $file); - $class = str_replace('.php', '', $class); - $class = str_replace('/', '\\', $class); - $class = 'PHP_CodeSniffer\Tests\Core'.$class; - - $suite->addTestSuite($class); - } - - return $suite; - - }//end suite() - - -}//end class diff --git a/tests/FileList.php b/tests/FileList.php deleted file mode 100644 index ac3c944f32..0000000000 --- a/tests/FileList.php +++ /dev/null @@ -1,98 +0,0 @@ - - * @copyright 2019 Juliette Reinders Folmer. All rights reserved. - * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - */ - -namespace PHP_CodeSniffer\Tests; - -use RecursiveDirectoryIterator; -use RecursiveIteratorIterator; -use RegexIterator; - -class FileList -{ - - /** - * The path to the project root directory. - * - * @var string - */ - protected $rootPath; - - /** - * Recursive directory iterator. - * - * @var \DirectoryIterator - */ - public $fileIterator; - - /** - * Base regex to use if no filter regex is provided. - * - * Matches based on: - * - File path starts with the project root (replacement done in constructor). - * - Don't match .git/ files. - * - Don't match dot files, i.e. "." or "..". - * - Don't match backup files. - * - Match everything else in a case-insensitive manner. - * - * @var string - */ - private $baseRegex = '`^%s(?!\.git/)(?!(.*/)?\.+$)(?!.*\.(bak|orig)).*$`Dix'; - - - /** - * Constructor. - * - * @param string $directory The directory to examine. - * @param string $rootPath Path to the project root. - * @param string $filter PCRE regular expression to filter the file list with. - */ - public function __construct($directory, $rootPath='', $filter='') - { - $this->rootPath = $rootPath; - - $directory = new RecursiveDirectoryIterator( - $directory, - RecursiveDirectoryIterator::UNIX_PATHS - ); - $flattened = new RecursiveIteratorIterator( - $directory, - RecursiveIteratorIterator::LEAVES_ONLY, - RecursiveIteratorIterator::CATCH_GET_CHILD - ); - - if ($filter === '') { - $filter = sprintf($this->baseRegex, preg_quote($this->rootPath)); - } - - $this->fileIterator = new RegexIterator($flattened, $filter); - - return $this; - - }//end __construct() - - - /** - * Retrieve the filtered file list as an array. - * - * @return array - */ - public function getList() - { - $fileList = []; - - foreach ($this->fileIterator as $file) { - $fileList[] = str_replace($this->rootPath, '', $file); - } - - return $fileList; - - }//end getList() - - -}//end class diff --git a/tests/Standards/AbstractSniffUnitTest.php b/tests/Standards/AbstractSniffUnitTest.php index a62374cf55..8b8f8a5dfb 100644 --- a/tests/Standards/AbstractSniffUnitTest.php +++ b/tests/Standards/AbstractSniffUnitTest.php @@ -20,53 +20,43 @@ use PHP_CodeSniffer\Tests\ConfigDouble; use PHP_CodeSniffer\Util\Common; use PHPUnit\Framework\TestCase; +use ReflectionClass; abstract class AbstractSniffUnitTest extends TestCase { /** - * Enable or disable the backup and restoration of the $GLOBALS array. - * Overwrite this attribute in a child class of TestCase. - * Setting this attribute in setUp() has no effect! + * Cache for the Config object. * - * @var boolean + * @var \PHP_CodeSniffer\Tests\ConfigDouble */ - protected $backupGlobals = false; + private static $config; /** - * The path to the standard's main directory. + * Cache for Ruleset objects. * - * @var string + * @var array */ - public $standardsDir = null; + private static $rulesets = []; /** - * The path to the standard's test directory. + * Extensions to disregard when gathering the test files. * - * @var string + * @var array */ - public $testsDir = null; - - - /** - * Sets up this unit test. - * - * @return void - */ - protected function setUp(): void - { - $class = get_class($this); - $this->standardsDir = $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'][$class]; - $this->testsDir = $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'][$class]; - - }//end setUp() + private $ignoreExtensions = [ + 'php' => 'php', + 'fixed' => 'fixed', + 'bak' => 'bak', + 'orig' => 'orig', + ]; /** * Get a list of all test files to check. * * These will have the same base as the sniff name but different extensions. - * We ignore the .php file as it is the class. + * We ignore the .php file as it is the test class. * * @param string $testFileBase The base path that the unit tests files will have. * @@ -76,13 +66,14 @@ protected function getTestFiles($testFileBase) { $testFiles = []; - $dir = substr($testFileBase, 0, strrpos($testFileBase, DIRECTORY_SEPARATOR)); + $dir = dirname($testFileBase); $di = new DirectoryIterator($dir); foreach ($di as $file) { $path = $file->getPathname(); if (substr($path, 0, strlen($testFileBase)) === $testFileBase) { - if ($path !== $testFileBase.'php' && substr($path, -5) !== 'fixed' && substr($path, -4) !== '.bak') { + $extension = $file->getExtension(); + if (isset($this->ignoreExtensions[$extension]) === false) { $testFiles[] = $path; } } @@ -121,39 +112,41 @@ final public function testSniff() $this->markTestSkipped(); } - $sniffCode = Common::getSniffCode(get_class($this)); - list($standardName, $categoryName, $sniffName) = explode('.', $sniffCode); + $sniffCode = Common::getSniffCode(get_class($this)); + $sniffCodeParts = explode('.', $sniffCode); + $standardName = $sniffCodeParts[0]; - $testFileBase = $this->testsDir.$categoryName.DIRECTORY_SEPARATOR.$sniffName.'UnitTest.'; + $testFileBase = (new ReflectionClass(static::class))->getFileName(); + $testFileBase = substr($testFileBase, 0, -3); // Get a list of all test files to check. $testFiles = $this->getTestFiles($testFileBase); - $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES'][] = $testFiles; - if (isset($GLOBALS['PHP_CODESNIFFER_CONFIG']) === true) { - $config = $GLOBALS['PHP_CODESNIFFER_CONFIG']; + if (isset(self::$config) === true) { + $config = self::$config; } else { $config = new ConfigDouble(); $config->cache = false; - $GLOBALS['PHP_CODESNIFFER_CONFIG'] = $config; + self::$config = $config; } $config->standards = [$standardName]; $config->sniffs = [$sniffCode]; $config->ignored = []; - if (isset($GLOBALS['PHP_CODESNIFFER_RULESETS']) === false) { - $GLOBALS['PHP_CODESNIFFER_RULESETS'] = []; - } - - if (isset($GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName]) === false) { + if (isset(self::$rulesets[$standardName]) === false) { $ruleset = new Ruleset($config); - $GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName] = $ruleset; + self::$rulesets[$standardName] = $ruleset; } - $ruleset = $GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName]; + $ruleset = self::$rulesets[$standardName]; - $sniffFile = $this->standardsDir.DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$categoryName.DIRECTORY_SEPARATOR.$sniffName.'Sniff.php'; + $sniffFile = preg_replace('`[/\\\\]Tests[/\\\\]`', DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR, $testFileBase); + $sniffFile = str_replace('UnitTest.', 'Sniff.php', $sniffFile); + + if (file_exists($sniffFile) === false) { + $this->fail(sprintf('ERROR: Sniff file %s for test %s does not appear to exist', $sniffFile, static::class)); + } $sniffClassName = substr(get_class($this), 0, -8).'Sniff'; $sniffClassName = str_replace('\Tests\\', '\Sniffs\\', $sniffClassName); @@ -269,17 +262,6 @@ public function generateFailureMessages(LocalFile $file) $errorsTemp = []; foreach ($errors as $foundError) { $errorsTemp[] = $foundError['message'].' ('.$foundError['source'].')'; - - $source = $foundError['source']; - if (in_array($source, $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'], true) === false) { - $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'][] = $source; - } - - if ($foundError['fixable'] === true - && in_array($source, $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'], true) === false - ) { - $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'][] = $source; - } } $allProblems[$line]['found_errors'] = array_merge($foundErrorsTemp, $errorsTemp); @@ -326,17 +308,6 @@ public function generateFailureMessages(LocalFile $file) $warningsTemp = []; foreach ($warnings as $warning) { $warningsTemp[] = $warning['message'].' ('.$warning['source'].')'; - - $source = $warning['source']; - if (in_array($source, $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'], true) === false) { - $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'][] = $source; - } - - if ($warning['fixable'] === true - && in_array($source, $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'], true) === false - ) { - $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'][] = $source; - } } $allProblems[$line]['found_warnings'] = array_merge($foundWarningsTemp, $warningsTemp); diff --git a/tests/Standards/AllSniffs.php b/tests/Standards/AllSniffs.php deleted file mode 100644 index 1e273e28eb..0000000000 --- a/tests/Standards/AllSniffs.php +++ /dev/null @@ -1,114 +0,0 @@ - - * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) - * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - */ - -namespace PHP_CodeSniffer\Tests\Standards; - -use PHP_CodeSniffer\Autoload; -use PHP_CodeSniffer\Util\Standards; -use PHPUnit\Framework\TestSuite; -use PHPUnit\TextUI\TestRunner; -use RecursiveDirectoryIterator; -use RecursiveIteratorIterator; - -class AllSniffs -{ - - - /** - * Prepare the test runner. - * - * @return void - */ - public static function main() - { - TestRunner::run(self::suite()); - - }//end main() - - - /** - * Add all sniff unit tests into a test suite. - * - * Sniff unit tests are found by recursing through the 'Tests' directory - * of each installed coding standard. - * - * @return \PHPUnit\Framework\TestSuite - */ - public static function suite() - { - $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'] = []; - $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'] = []; - $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES'] = []; - - $suite = new TestSuite('PHP CodeSniffer Standards'); - - // Optionally allow for ignoring the tests for one or more standards. - $ignoreTestsForStandards = getenv('PHPCS_IGNORE_TESTS'); - if ($ignoreTestsForStandards === false) { - $ignoreTestsForStandards = []; - } else { - $ignoreTestsForStandards = explode(',', $ignoreTestsForStandards); - } - - $installedStandards = self::getInstalledStandardDetails(); - - foreach ($installedStandards as $standard => $details) { - Autoload::addSearchPath($details['path'], $details['namespace']); - - if (in_array($standard, $ignoreTestsForStandards, true) === true) { - continue; - } - - $testsDir = $details['path'].DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR; - if (is_dir($testsDir) === false) { - // No tests for this standard. - continue; - } - - $di = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($testsDir)); - - foreach ($di as $file) { - // Skip hidden files. - if (substr($file->getFilename(), 0, 1) === '.') { - continue; - } - - // Tests must have the extension 'php'. - $parts = explode('.', $file); - $ext = array_pop($parts); - if ($ext !== 'php') { - continue; - } - - $className = Autoload::loadFile($file->getPathname()); - $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'][$className] = $details['path']; - $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'][$className] = $testsDir; - $suite->addTestSuite($className); - } - }//end foreach - - return $suite; - - }//end suite() - - - /** - * Get the details of all coding standards installed. - * - * @return array - * @see Standards::getInstalledStandardDetails() - */ - protected static function getInstalledStandardDetails() - { - return Standards::getInstalledStandardDetails(true); - - }//end getInstalledStandardDetails() - - -}//end class diff --git a/tests/TestSuite.php b/tests/TestSuite.php deleted file mode 100644 index ad0947c58f..0000000000 --- a/tests/TestSuite.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) - * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - */ - -namespace PHP_CodeSniffer\Tests; - -use PHPUnit\Framework\TestResult; -use PHPUnit\Framework\TestSuite as PHPUnit_TestSuite; - -class TestSuite extends PHPUnit_TestSuite -{ - - - /** - * Runs the tests and collects their result in a TestResult. - * - * @param \PHPUnit\Framework\TestResult|null $result A test result. - * - * @return \PHPUnit\Framework\TestResult - */ - public function run(?TestResult $result=null): TestResult - { - $result = parent::run($result); - printPHPCodeSnifferTestOutput(); - return $result; - - }//end run() - - -}//end class diff --git a/tests/bootstrap.php b/tests/bootstrap.php index f90d98c49f..e38bb1c4fa 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -7,6 +7,10 @@ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ +use PHP_CodeSniffer\Autoload; +use PHP_CodeSniffer\Util\Standards; +use PHP_CodeSniffer\Util\Tokens; + if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { define('PHP_CODESNIFFER_IN_TESTS', true); } @@ -40,43 +44,10 @@ require_once __DIR__.'/../autoload.php'; -$tokens = new \PHP_CodeSniffer\Util\Tokens(); - - -/** - * A global util function to help print unit test fixing data. - * - * @return void - */ -function printPHPCodeSnifferTestOutput() -{ - echo PHP_EOL.PHP_EOL; - - $output = 'The test files'; - $data = []; - - $codeCount = count($GLOBALS['PHP_CODESNIFFER_SNIFF_CODES']); - if (empty($GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES']) === false) { - $files = call_user_func_array('array_merge', $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES']); - $files = array_unique($files); - $fileCount = count($files); - - $output = '%d sniff test files'; - $data[] = $fileCount; - } - - $output .= ' generated %d unique error codes'; - $data[] = $codeCount; - - if ($codeCount > 0) { - $fixes = count($GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES']); - $percent = round(($fixes / $codeCount * 100), 2); - - $output .= '; %d were fixable (%d%%)'; - $data[] = $fixes; - $data[] = $percent; - } - - vprintf($output, $data); +// Make sure all installed standards are autoloadable. +$installedStandards = Standards::getInstalledStandardDetails(); +foreach ($installedStandards as $standardDetails) { + Autoload::addSearchPath($standardDetails['path'], $standardDetails['namespace']); +} -}//end printPHPCodeSnifferTestOutput() +$tokens = new Tokens();