diff options
Diffstat (limited to 'core')
18 files changed, 115 insertions, 966 deletions
diff --git a/core/.phpunit-next.xml b/core/.phpunit-next.xml deleted file mode 100644 index 944ec9dfadd..00000000000 --- a/core/.phpunit-next.xml +++ /dev/null @@ -1,164 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - - -<!-- This is a near-copy of phpunit.xml.dist, used to test with upcoming - PHPUnit versions. - - Current differences: - * for PHPUnit 11: removed duplicate directories from <testsuites>, - required in PHPUnit 10, but that cause duplication warnings in - PHPUnit 11. ---> - - -<!-- For how to customize PHPUnit configuration, see core/tests/README.md. --> -<!-- TODO set checkForUnintentionallyCoveredCode="true" once https://www.drupal.org/node/2626832 is resolved. --> -<!-- PHPUnit expects functional tests to be run with either a privileged user - or your current system user. See core/tests/README.md and - https://www.drupal.org/node/2116263 for details. ---> -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - bootstrap="tests/bootstrap.php" - colors="true" - beStrictAboutTestsThatDoNotTestAnything="true" - beStrictAboutOutputDuringTests="true" - beStrictAboutChangesToGlobalState="true" - failOnRisky="true" - failOnWarning="true" - displayDetailsOnTestsThatTriggerErrors="true" - displayDetailsOnTestsThatTriggerWarnings="true" - displayDetailsOnTestsThatTriggerDeprecations="true" - cacheResult="false" - xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" - cacheDirectory=".phpunit.cache"> - <php> - <!-- Set error reporting to E_ALL. --> - <ini name="error_reporting" value="32767"/> - <!-- Do not limit the amount of memory tests take to run. --> - <ini name="memory_limit" value="-1"/> - <!-- Example SIMPLETEST_BASE_URL value: http://localhost --> - <env name="SIMPLETEST_BASE_URL" value=""/> - <!-- Example SIMPLETEST_DB value: mysql://username:password@localhost/database_name#table_prefix --> - <env name="SIMPLETEST_DB" value=""/> - <!-- By default, browser tests will output links that use the base URL set - in SIMPLETEST_BASE_URL. However, if your SIMPLETEST_BASE_URL is an internal - path (such as may be the case in a virtual or Docker-based environment), - you can set the base URL used in the browser test output links to something - reachable from your host machine here. This will allow you to follow them - directly and view the output. --> - <env name="BROWSERTEST_OUTPUT_BASE_URL" value=""/> - <!-- The environment variable SYMFONY_DEPRECATIONS_HELPER is used to configure - the behavior of the deprecation tests. - Drupal core's testing framework is setting this variable to its defaults. - Projects with their own requirements need to manage this variable - explicitly. - --> - <!-- To disable deprecation testing completely uncomment the next line. --> - <!-- <env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"/> --> - <!-- Deprecation errors can be selectively ignored by specifying a file of - regular expression patterns for exclusion. - Uncomment the line below to specify a custom deprecations ignore file. - NOTE: it may be required to specify the full path to the file to run tests - correctly. - --> - <!-- <env name="SYMFONY_DEPRECATIONS_HELPER" value="ignoreFile=.deprecation-ignore.txt"/> --> - <!-- Example for changing the driver class for mink tests MINK_DRIVER_CLASS value: 'Drupal\FunctionalJavascriptTests\DrupalSelenium2Driver' --> - <env name="MINK_DRIVER_CLASS" value=""/> - <!-- Example for changing the driver args to mink tests MINK_DRIVER_ARGS value: '["http://127.0.0.1:8510"]' --> - <env name="MINK_DRIVER_ARGS" value=""/> - <!-- Example for changing the driver args to webdriver tests MINK_DRIVER_ARGS_WEBDRIVER value: '["chrome", { "goog:chromeOptions": { "w3c": false } }, "http://localhost:4444/wd/hub"]' For using the Firefox browser, replace "chrome" with "firefox" --> - <env name="MINK_DRIVER_ARGS_WEBDRIVER" value=""/> - </php> - <extensions> - <!-- Functional tests HTML output logging. --> - <bootstrap class="Drupal\TestTools\Extension\HtmlLogging\HtmlOutputLogger"> - <!-- The directory where the browser output will be stored. If a relative - path is specified, it will be relative to the current working directory - of the process running the PHPUnit CLI. In CI environments, this can be - overridden by the value set for the "BROWSERTEST_OUTPUT_DIRECTORY" - environment variable. - --> - <parameter name="outputDirectory" value="sites/simpletest/browser_output"/> - <!-- By default browser tests print the individual links in the test run - report. To avoid overcrowding the output in CI environments, you can - set the "verbose" parameter or the "BROWSERTEST_OUTPUT_VERBOSE" - environment variable to "false". In GitLabCI, the output is saved - anyway as an artifact that can be browsed or downloaded from Gitlab. - --> - <parameter name="verbose" value="true"/> - </bootstrap> - <!-- Debug dump() printer. --> - <bootstrap class="Drupal\TestTools\Extension\Dump\DebugDump"> - <parameter name="colors" value="true"/> - <parameter name="printCaller" value="true"/> - </bootstrap> - </extensions> - <testsuites> - <testsuite name="unit-component"> - <directory>tests/Drupal/Tests/Component</directory> - </testsuite> - <testsuite name="unit"> - <directory>tests/Drupal/Tests</directory> - <exclude>tests/Drupal/Tests/Component</exclude> - <directory>modules/**/tests/src/Unit</directory> - <directory>profiles/**/tests/src/Unit</directory> - <directory>themes/**/tests/src/Unit</directory> - <directory>../modules/**/tests/src/Unit</directory> - <directory>../profiles/**/tests/src/Unit</directory> - <directory>../themes/**/tests/src/Unit</directory> - </testsuite> - <testsuite name="kernel"> - <directory>tests/Drupal/KernelTests</directory> - <directory>modules/**/tests/src/Kernel</directory> - <directory>recipes/*/tests/src/Kernel</directory> - <directory>profiles/**/tests/src/Kernel</directory> - <directory>themes/**/tests/src/Kernel</directory> - <directory>../modules/**/tests/src/Kernel</directory> - <directory>../profiles/**/tests/src/Kernel</directory> - <directory>../themes/**/tests/src/Kernel</directory> - </testsuite> - <testsuite name="functional"> - <directory>tests/Drupal/FunctionalTests</directory> - <directory>modules/**/tests/src/Functional</directory> - <directory>profiles/**/tests/src/Functional</directory> - <directory>recipes/*/tests/src/Functional</directory> - <directory>themes/**/tests/src/Functional</directory> - <directory>../modules/**/tests/src/Functional</directory> - <directory>../profiles/**/tests/src/Functional</directory> - <directory>../themes/**/tests/src/Functional</directory> - </testsuite> - <testsuite name="functional-javascript"> - <directory>tests/Drupal/FunctionalJavascriptTests</directory> - <directory>modules/**/tests/src/FunctionalJavascript</directory> - <directory>recipes/*/tests/src/FunctionalJavascript</directory> - <directory>profiles/**/tests/src/FunctionalJavascript</directory> - <directory>themes/**/tests/src/FunctionalJavascript</directory> - <directory>../modules/**/tests/src/FunctionalJavascript</directory> - <directory>../profiles/**/tests/src/FunctionalJavascript</directory> - <directory>../themes/**/tests/src/FunctionalJavascript</directory> - </testsuite> - <testsuite name="build"> - <directory>tests/Drupal/BuildTests</directory> - <directory>modules/**/tests/src/Build</directory> - </testsuite> - </testsuites> - <!-- Settings for coverage reports. --> - <source ignoreSuppressionOfDeprecations="true"> - <include> - <directory>./includes</directory> - <directory>./lib</directory> - <directory>./modules</directory> - <directory>../modules</directory> - <directory>../sites</directory> - </include> - <exclude> - <directory>./lib/Drupal/Component</directory> - <directory>./modules/*/src/Tests</directory> - <directory>./modules/*/tests</directory> - <directory>../modules/*/src/Tests</directory> - <directory>../modules/*/tests</directory> - <directory>../modules/*/*/src/Tests</directory> - <directory>../modules/*/*/tests</directory> - </exclude> - </source> -</phpunit> diff --git a/core/lib/Drupal/Core/Test/PhpUnitTestDiscovery.php b/core/lib/Drupal/Core/Test/PhpUnitTestDiscovery.php deleted file mode 100644 index d9737028821..00000000000 --- a/core/lib/Drupal/Core/Test/PhpUnitTestDiscovery.php +++ /dev/null @@ -1,346 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Drupal\Core\Test; - -use Drupal\Core\Test\Exception\MissingGroupException; -use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion; -use PHPUnit\Framework\DataProviderTestSuite; -use PHPUnit\Framework\Test; -use PHPUnit\Framework\TestCase; -use PHPUnit\Framework\TestSuite; -use PHPUnit\TextUI\Configuration\Builder; -use PHPUnit\TextUI\Configuration\TestSuiteBuilder; - -/** - * Discovers available tests using the PHPUnit API. - * - * @internal - */ -class PhpUnitTestDiscovery { - - /** - * The map of legacy test suite identifiers to phpunit.xml ones. - * - * @var array<string,string> - */ - private array $map = [ - 'PHPUnit-FunctionalJavascript' => 'functional-javascript', - 'PHPUnit-Functional' => 'functional', - 'PHPUnit-Kernel' => 'kernel', - 'PHPUnit-Unit' => 'unit', - 'PHPUnit-Unit-Component' => 'unit-component', - 'PHPUnit-Build' => 'build', - ]; - - /** - * The reverse map of legacy test suite identifiers to phpunit.xml ones. - * - * @var array<string,string> - */ - private array $reverseMap; - - /** - * The warnings generated during the discovery. - * - * @var list<string> - */ - private array $warnings = []; - - public function __construct( - private string $configurationFilePath, - ) { - $this->reverseMap = array_flip($this->map); - } - - /** - * Discovers available tests. - * - * @param string|null $extension - * (optional) The name of an extension to limit discovery to; e.g., 'node'. - * @param list<string> $testSuites - * (optional) An array of PHPUnit test suites to filter the discovery for. - * @param string|null $directory - * (optional) Limit discovered tests to a specific directory. - * - * @return array<string<array<class-string, array{name: class-string, description: string, group: string|int, groups: list<string|int>, type: string, file: string, tests_count: positive-int}>>> - * An array of test groups keyed by the group name. Each test group is an - * array of test class information arrays as returned by - * ::getTestClassInfo(), keyed by test class. If a test class belongs to - * multiple groups, it will appear under all group keys it belongs to. - */ - public function getTestClasses(?string $extension = NULL, array $testSuites = [], ?string $directory = NULL): array { - $this->warnings = []; - - $args = ['--configuration', $this->configurationFilePath]; - - if (!empty($testSuites)) { - // Convert $testSuites from Drupal's legacy syntax to the syntax used in - // phpunit.xml, that is necessary to PHPUnit to be able to apply the - // test suite filter. For example, 'PHPUnit-Unit' to 'unit'. - $tmp = []; - foreach ($testSuites as $i) { - if (!is_string($i)) { - throw new \InvalidArgumentException("Test suite must be a string"); - } - if (str_contains($i, ' ')) { - throw new \InvalidArgumentException("Test suite name '{$i}' is invalid"); - } - $tmp[] = $this->map[$i] ?? $i; - } - $args[] = '--testsuite=' . implode(',', $tmp); - } - - if ($directory !== NULL) { - $args[] = $directory; - } - - $phpUnitConfiguration = (new Builder())->build($args); - - // TestSuiteBuilder calls the test data providers during the discovery. - // Data providers may be changing the Drupal service container, which leads - // to potential issues. We save the current container before running the - // discovery, and in case a change is detected, reset it and raise - // warnings so that developers can tune their data provider code. - if (\Drupal::hasContainer()) { - $container = \Drupal::getContainer(); - $containerObjectId = spl_object_id($container); - } - $phpUnitTestSuite = (new TestSuiteBuilder())->build($phpUnitConfiguration); - if (isset($containerObjectId) && $containerObjectId !== spl_object_id(\Drupal::getContainer())) { - $this->warnings[] = '*** The service container was changed during the test discovery ***'; - $this->warnings[] = 'Probably a test data provider method called \\Drupal::setContainer.'; - $this->warnings[] = 'Ensure that all the data providers restore the original container before returning data.'; - assert(isset($container)); - \Drupal::setContainer($container); - } - - $list = $directory === NULL ? - $this->getTestList($phpUnitTestSuite, $extension) : - $this->getTestListLimitedToDirectory($phpUnitTestSuite, $extension, $testSuites); - - // Sort the groups and tests within the groups by name. - uksort($list, 'strnatcasecmp'); - foreach ($list as &$tests) { - uksort($tests, 'strnatcasecmp'); - } - - return $list; - } - - /** - * Discovers all class files in all available extensions. - * - * @param string|null $extension - * (optional) The name of an extension to limit discovery to; e.g., 'node'. - * @param string|null $directory - * (optional) Limit discovered tests to a specific directory. - * - * @return array - * A classmap containing all discovered class files; i.e., a map of - * fully-qualified classnames to path names. - */ - public function findAllClassFiles(?string $extension = NULL, ?string $directory = NULL): array { - $testClasses = $this->getTestClasses($extension, [], $directory); - $classMap = []; - foreach ($testClasses as $group) { - foreach ($group as $className => $info) { - $classMap[$className] = $info['file']; - } - } - return $classMap; - } - - /** - * Returns the warnings generated during the discovery. - * - * @return list<string> - * The warnings. - */ - public function getWarnings(): array { - return $this->warnings; - } - - /** - * Returns a list of tests from a TestSuite object. - * - * @param \PHPUnit\Framework\TestSuite $phpUnitTestSuite - * The TestSuite object returned by PHPUnit test discovery. - * @param string|null $extension - * The name of an extension to limit discovery to; e.g., 'node'. - * - * @return array<string<array<class-string, array{name: class-string, description: string, group: string|int, groups: list<string|int>, type: string, file: string, tests_count: positive-int}>>> - * An array of test groups keyed by the group name. Each test group is an - * array of test class information arrays as returned by - * ::getTestClassInfo(), keyed by test class. If a test class belongs to - * multiple groups, it will appear under all group keys it belongs to. - */ - private function getTestList(TestSuite $phpUnitTestSuite, ?string $extension): array { - $list = []; - foreach ($phpUnitTestSuite->tests() as $testSuite) { - foreach ($testSuite->tests() as $testClass) { - if ($extension !== NULL && !str_starts_with($testClass->name(), "Drupal\\Tests\\{$extension}\\")) { - continue; - } - - $item = $this->getTestClassInfo( - $testClass, - $this->reverseMap[$testSuite->name()] ?? $testSuite->name(), - ); - - foreach ($item['groups'] as $group) { - $list[$group][$item['name']] = $item; - } - } - } - return $list; - } - - /** - * Returns a list of tests from a TestSuite object limited to a directory. - * - * @param \PHPUnit\Framework\TestSuite $phpUnitTestSuite - * The TestSuite object returned by PHPUnit test discovery. - * @param string|null $extension - * The name of an extension to limit discovery to; e.g., 'node'. - * @param list<string> $testSuites - * An array of PHPUnit test suites to filter the discovery for. - * - * @return array<string<array<class-string, array{name: class-string, description: string, group: string|int, groups: list<string|int>, type: string, file: string, tests_count: positive-int}>>> - * An array of test groups keyed by the group name. Each test group is an - * array of test class information arrays as returned by - * ::getTestClassInfo(), keyed by test class. If a test class belongs to - * multiple groups, it will appear under all group keys it belongs to. - */ - private function getTestListLimitedToDirectory(TestSuite $phpUnitTestSuite, ?string $extension, array $testSuites): array { - $list = []; - - // In this case, PHPUnit found a single test class to run tests for. - if ($phpUnitTestSuite->isForTestClass()) { - if ($extension !== NULL && !str_starts_with($phpUnitTestSuite->name(), "Drupal\\Tests\\{$extension}\\")) { - return []; - } - - // Take the test suite name from the class namespace. - $testSuite = 'PHPUnit-' . TestDiscovery::getPhpunitTestSuite($phpUnitTestSuite->name()); - if (!empty($testSuites) && !in_array($testSuite, $testSuites, TRUE)) { - return []; - } - - $item = $this->getTestClassInfo($phpUnitTestSuite, $testSuite); - - foreach ($item['groups'] as $group) { - $list[$group][$item['name']] = $item; - } - return $list; - } - - // Multiple test classes were found. - $list = []; - foreach ($phpUnitTestSuite->tests() as $testClass) { - if ($extension !== NULL && !str_starts_with($testClass->name(), "Drupal\\Tests\\{$extension}\\")) { - continue; - } - - // Take the test suite name from the class namespace. - $testSuite = 'PHPUnit-' . TestDiscovery::getPhpunitTestSuite($testClass->name()); - if (!empty($testSuites) && !in_array($testSuite, $testSuites, TRUE)) { - continue; - } - - $item = $this->getTestClassInfo($testClass, $testSuite); - - foreach ($item['groups'] as $group) { - $list[$group][$item['name']] = $item; - } - } - return $list; - - } - - /** - * Returns the test class information. - * - * @param \PHPUnit\Framework\Test $testClass - * The test class. - * @param string $testSuite - * The test suite of this test class. - * - * @return array{name: class-string, description: string, group: string|int, groups: list<string|int>, type: string, file: string, tests_count: positive-int} - * The test class information. - */ - private function getTestClassInfo(Test $testClass, string $testSuite): array { - $reflection = new \ReflectionClass($testClass->name()); - - // Let PHPUnit API return the groups, as it will deal transparently with - // annotations or attributes, but skip groups generated by PHPUnit - // internally and starting with a double underscore prefix. - if (RunnerVersion::getMajor() < 11) { - $groups = array_filter($testClass->groups(), function (string $value): bool { - return !str_starts_with($value, '__phpunit'); - }); - } - else { - // In PHPUnit 11+, we need to coalesce the groups from individual tests - // as they may not be available from the test class level (when tests are - // backed by data providers). - $tmp = []; - foreach ($testClass as $test) { - if ($test instanceof DataProviderTestSuite) { - foreach ($test as $testWithData) { - $tmp = array_merge($tmp, $testWithData->groups()); - } - } - else { - $tmp = array_merge($tmp, $test->groups()); - } - } - $groups = array_filter(array_unique($tmp), function (string $value): bool { - return !str_starts_with($value, '__phpunit'); - }); - } - if (empty($groups)) { - throw new MissingGroupException(sprintf('Missing group metadata in test class %s', $testClass->name())); - } - - // Let PHPUnit API return the class coverage information. - $test = $testClass; - while (!$test instanceof TestCase) { - $test = $test->tests()[0]; - } - if (($metadata = $test->valueObjectForEvents()->metadata()->isCoversClass()) && $metadata->isNotEmpty()) { - $description = sprintf('Tests %s.', $metadata->asArray()[0]->className()); - } - elseif (($metadata = $test->valueObjectForEvents()->metadata()->isCoversDefaultClass()) && $metadata->isNotEmpty()) { - $description = sprintf('Tests %s.', $metadata->asArray()[0]->className()); - } - else { - $description = TestDiscovery::parseTestClassSummary($reflection->getDocComment()); - } - - // Find the test cases count. - $count = 0; - foreach ($testClass->tests() as $testCase) { - if ($testCase instanceof TestCase) { - // If it's a straight test method, counts 1. - $count++; - } - else { - // It's a data provider test suite, count 1 per data set provided. - $count += count($testCase->tests()); - } - } - - return [ - 'name' => $testClass->name(), - 'group' => $groups[0], - 'groups' => $groups, - 'type' => $testSuite, - 'description' => $description, - 'file' => $reflection->getFileName(), - 'tests_count' => $count, - ]; - } - -} diff --git a/core/lib/Drupal/Core/Test/RunTests/TestFileParser.php b/core/lib/Drupal/Core/Test/RunTests/TestFileParser.php index 8ab5260aa66..12aa757e57e 100644 --- a/core/lib/Drupal/Core/Test/RunTests/TestFileParser.php +++ b/core/lib/Drupal/Core/Test/RunTests/TestFileParser.php @@ -4,16 +4,9 @@ namespace Drupal\Core\Test\RunTests; use PHPUnit\Framework\TestCase; -@trigger_error('Drupal\Core\Test\RunTests\TestFileParser is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. See https://www.drupal.org/node/3447698', E_USER_DEPRECATED); - /** * Parses class names from PHP files without loading them. * - * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no - * replacement. - * - * @see https://www.drupal.org/node/3447698 - * * @internal */ class TestFileParser { diff --git a/core/lib/Drupal/Core/Test/TestDiscovery.php b/core/lib/Drupal/Core/Test/TestDiscovery.php index 468256779b3..1347d0c583f 100644 --- a/core/lib/Drupal/Core/Test/TestDiscovery.php +++ b/core/lib/Drupal/Core/Test/TestDiscovery.php @@ -7,7 +7,6 @@ use Drupal\Component\Annotation\Reflection\MockFileFinder; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Extension\ExtensionDiscovery; use Drupal\Core\Test\Exception\MissingGroupException; -use PHPUnit\Framework\Attributes\Group; /** * Discovers available tests. @@ -27,11 +26,6 @@ class TestDiscovery { * Statically cached list of test classes. * * @var array - * - * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is - * no replacement. - * - * @see https://www.drupal.org/node/3447698 */ protected $testClasses; @@ -155,14 +149,8 @@ class TestDiscovery { * * @todo Remove singular grouping; retain list of groups in 'group' key. * @see https://www.drupal.org/node/2296615 - * - * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Use - * PhpUnitTestDiscovery::getTestClasses() instead. - * - * @see https://www.drupal.org/node/3447698 */ public function getTestClasses($extension = NULL, array $types = [], ?string $directory = NULL) { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Use PhpUnitTestDiscovery::getTestClasses() instead. See https://www.drupal.org/node/3447698', E_USER_DEPRECATED); if (!isset($extension) && empty($types)) { if (!empty($this->testClasses)) { return $this->testClasses; @@ -187,15 +175,6 @@ class TestDiscovery { catch (MissingGroupException $e) { // If the class name ends in Test and is not a migrate table dump. if (str_ends_with($classname, 'Test') && !str_contains($classname, 'migrate_drupal\Tests\Table')) { - $reflection = new \ReflectionClass($classname); - $groupAttributes = $reflection->getAttributes(Group::class, \ReflectionAttribute::IS_INSTANCEOF); - if (!empty($groupAttributes)) { - $group = '##no-group-annotations'; - $info['group'] = $group; - $info['groups'] = [$group]; - $list[$group][$classname] = $info; - continue; - } throw $e; } // If the class is @group annotation just skip it. Most likely it is an @@ -237,14 +216,8 @@ class TestDiscovery { * @return array * A classmap containing all discovered class files; i.e., a map of * fully-qualified classnames to path names. - * - * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Use - * PhpUnitTestDiscovery::findAllClassFiles() instead. - * - * @see https://www.drupal.org/node/3447698 */ public function findAllClassFiles($extension = NULL, ?string $directory = NULL) { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Use PhpUnitTestDiscovery::findAllClassFiles() instead. See https://www.drupal.org/node/3447698', E_USER_DEPRECATED); $classmap = []; $namespaces = $this->registerTestNamespaces(); if (isset($extension)) { @@ -283,14 +256,8 @@ class TestDiscovery { * * @todo Limit to '*Test.php' files (~10% less files to reflect/introspect). * @see https://www.drupal.org/node/2296635 - * - * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is - * no replacement. - * - * @see https://www.drupal.org/node/3447698 */ public static function scanDirectory($namespace_prefix, $path) { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. See https://www.drupal.org/node/3447698', E_USER_DEPRECATED); if (!str_ends_with($namespace_prefix, '\\')) { throw new \InvalidArgumentException("Namespace prefix for $path must contain a trailing namespace separator."); } @@ -345,14 +312,8 @@ class TestDiscovery { * * @throws \Drupal\Core\Test\Exception\MissingGroupException * If the class does not have a @group annotation. - * - * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is - * no replacement. - * - * @see https://www.drupal.org/node/3447698 */ public static function getTestInfo($classname, $doc_comment = NULL) { - @trigger_error(__METHOD__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. See https://www.drupal.org/node/3447698', E_USER_DEPRECATED); if ($doc_comment === NULL) { $reflection = new \ReflectionClass($classname); $doc_comment = $reflection->getDocComment(); @@ -389,7 +350,7 @@ class TestDiscovery { $info['type'] = 'PHPUnit-' . static::getPhpunitTestSuite($classname); if (!empty($annotations['coversDefaultClass'])) { - $info['description'] = 'Tests ' . ltrim($annotations['coversDefaultClass']) . '.'; + $info['description'] = 'Tests ' . $annotations['coversDefaultClass'] . '.'; } else { $info['description'] = static::parseTestClassSummary($doc_comment); diff --git a/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageNegotiationSettingsTest.php b/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageNegotiationSettingsTest.php index fe5ff0ca062..54fdf4b0d21 100644 --- a/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageNegotiationSettingsTest.php +++ b/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageNegotiationSettingsTest.php @@ -10,7 +10,6 @@ use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; /** * Tests the migration of language negotiation. * - * @group #slow * @group migrate_drupal_7 */ class MigrateLanguageNegotiationSettingsTest extends MigrateDrupal7TestBase { diff --git a/core/modules/link/tests/src/Functional/LinkFieldUITest.php b/core/modules/link/tests/src/Functional/LinkFieldUITest.php index 5c78abc2391..694fb6b3677 100644 --- a/core/modules/link/tests/src/Functional/LinkFieldUITest.php +++ b/core/modules/link/tests/src/Functional/LinkFieldUITest.php @@ -15,7 +15,6 @@ use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; * Tests link field UI functionality. * * @group link - * @group #slow */ class LinkFieldUITest extends BrowserTestBase { diff --git a/core/modules/package_manager/tests/src/Kernel/SupportedReleaseValidatorTest.php b/core/modules/package_manager/tests/src/Kernel/SupportedReleaseValidatorTest.php index 2e9a0977fa3..90348cdfdd3 100644 --- a/core/modules/package_manager/tests/src/Kernel/SupportedReleaseValidatorTest.php +++ b/core/modules/package_manager/tests/src/Kernel/SupportedReleaseValidatorTest.php @@ -13,6 +13,7 @@ use Drupal\Tests\package_manager\Traits\FixtureUtilityTrait; * @coversDefaultClass \Drupal\package_manager\Validator\SupportedReleaseValidator * @group #slow * @group package_manager + * @group #slow * @internal */ class SupportedReleaseValidatorTest extends PackageManagerKernelTestBase { diff --git a/core/modules/path/tests/src/Kernel/Migrate/d6/MigrateUrlAliasTest.php b/core/modules/path/tests/src/Kernel/Migrate/d6/MigrateUrlAliasTest.php index be5d811fe54..d5cc9759ab1 100644 --- a/core/modules/path/tests/src/Kernel/Migrate/d6/MigrateUrlAliasTest.php +++ b/core/modules/path/tests/src/Kernel/Migrate/d6/MigrateUrlAliasTest.php @@ -13,7 +13,6 @@ use Drupal\Tests\Traits\Core\PathAliasTestTrait; /** * URL alias migration. * - * @group #slow * @group migrate_drupal_6 */ class MigrateUrlAliasTest extends MigrateDrupal6TestBase { diff --git a/core/modules/system/tests/src/Kernel/DateFormatAccessControlHandlerTest.php b/core/modules/system/tests/src/Kernel/DateFormatAccessControlHandlerTest.php index 82d866e985e..6c8c42da59e 100644 --- a/core/modules/system/tests/src/Kernel/DateFormatAccessControlHandlerTest.php +++ b/core/modules/system/tests/src/Kernel/DateFormatAccessControlHandlerTest.php @@ -77,8 +77,6 @@ class DateFormatAccessControlHandlerTest extends KernelTestBase { * An array of test cases. */ public static function providerTestAccess(): array { - $originalContainer = \Drupal::hasContainer() ? \Drupal::getContainer() : NULL; - $c = new ContainerBuilder(); $cache_contexts_manager = (new Prophet())->prophesize(CacheContextsManager::class); $cache_contexts_manager->assertValidTokens()->willReturn(TRUE); @@ -86,7 +84,7 @@ class DateFormatAccessControlHandlerTest extends KernelTestBase { $c->set('cache_contexts_manager', $cache_contexts_manager); \Drupal::setContainer($c); - $data = [ + return [ 'No permission + unlocked' => [ [], 'unlocked', @@ -124,13 +122,6 @@ class DateFormatAccessControlHandlerTest extends KernelTestBase { AccessResult::allowed()->addCacheContexts(['user.permissions']), ], ]; - - // Restore the original container if needed. - if ($originalContainer) { - \Drupal::setContainer($originalContainer); - } - - return $data; } } diff --git a/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeTest.php b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeTest.php index 511778daf20..1d9654dd505 100644 --- a/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeTest.php +++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeTest.php @@ -10,7 +10,6 @@ use Drupal\node\Entity\Node; /** * Upgrade taxonomy term node associations. * - * @group #slow * @group migrate_drupal_6 */ class MigrateTermNodeTest extends MigrateDrupal6TestBase { diff --git a/core/modules/workflows/tests/src/Kernel/WorkflowAccessControlHandlerTest.php b/core/modules/workflows/tests/src/Kernel/WorkflowAccessControlHandlerTest.php index 180edc868f6..e46fbcf417b 100644 --- a/core/modules/workflows/tests/src/Kernel/WorkflowAccessControlHandlerTest.php +++ b/core/modules/workflows/tests/src/Kernel/WorkflowAccessControlHandlerTest.php @@ -124,8 +124,6 @@ class WorkflowAccessControlHandlerTest extends KernelTestBase { * An array of test data. */ public static function checkAccessProvider() { - $originalContainer = \Drupal::hasContainer() ? \Drupal::getContainer() : NULL; - $container = new ContainerBuilder(); $cache_contexts_manager = (new Prophet())->prophesize(CacheContextsManager::class); $cache_contexts_manager->assertValidTokens()->willReturn(TRUE); @@ -133,7 +131,7 @@ class WorkflowAccessControlHandlerTest extends KernelTestBase { $container->set('cache_contexts_manager', $cache_contexts_manager); \Drupal::setContainer($container); - $data = [ + return [ 'Admin view' => [ 'adminUser', 'view', @@ -277,13 +275,6 @@ class WorkflowAccessControlHandlerTest extends KernelTestBase { AccessResult::allowed()->addCacheContexts(['user.permissions']), ], ]; - - // Restore the original container if needed. - if ($originalContainer) { - \Drupal::setContainer($originalContainer); - } - - return $data; } } diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index 96f16eed9c7..4545a00cc3a 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -17,13 +17,14 @@ use Drupal\Component\Utility\Timer; use Drupal\Core\Composer\Composer; use Drupal\Core\Database\Database; use Drupal\Core\Test\EnvironmentCleaner; -use Drupal\Core\Test\PhpUnitTestDiscovery; use Drupal\Core\Test\PhpUnitTestRunner; use Drupal\Core\Test\SimpletestTestRunResultsStorage; +use Drupal\Core\Test\RunTests\TestFileParser; use Drupal\Core\Test\TestDatabase; use Drupal\Core\Test\TestRun; use Drupal\Core\Test\TestRunnerKernel; use Drupal\Core\Test\TestRunResultsStorageInterface; +use Drupal\Core\Test\TestDiscovery; use Drupal\BuildTests\Framework\BuildTestBase; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; use Drupal\KernelTests\KernelTestBase; @@ -48,10 +49,6 @@ const SIMPLETEST_SCRIPT_COLOR_EXCEPTION = 33; const SIMPLETEST_SCRIPT_COLOR_YELLOW = 33; // A refreshing cyan. const SIMPLETEST_SCRIPT_COLOR_CYAN = 36; -// A fainting gray. -const SIMPLETEST_SCRIPT_COLOR_GRAY = 90; -// A notable white. -const SIMPLETEST_SCRIPT_COLOR_BRIGHT_WHITE = "1;97"; // Restricting the chunk of queries prevents memory exhaustion. const SIMPLETEST_SCRIPT_SQLITE_VARIABLE_LIMIT = 350; @@ -89,12 +86,12 @@ if ($args['list']) { // Display all available tests organized by one @group annotation. echo "\nAvailable test groups & classes\n"; echo "-------------------------------\n\n"; - $test_discovery = new PhpUnitTestDiscovery(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core'); + $test_discovery = new TestDiscovery( + \Drupal::root(), + \Drupal::service('class_loader') + ); try { $groups = $test_discovery->getTestClasses($args['module']); - foreach ($test_discovery->getWarnings() as $warning) { - simpletest_script_print($warning . "\n", SIMPLETEST_SCRIPT_COLOR_EXCEPTION); - } } catch (Exception $e) { error_log((string) $e); @@ -122,8 +119,11 @@ if ($args['list']) { // @see https://www.drupal.org/node/2569585 if ($args['list-files'] || $args['list-files-json']) { // List all files which could be run as tests. - $test_discovery = new PhpUnitTestDiscovery(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core'); - // PhpUnitTestDiscovery::findAllClassFiles() gives us a classmap similar to a + $test_discovery = new TestDiscovery( + \Drupal::root(), + \Drupal::service('class_loader') + ); + // TestDiscovery::findAllClassFiles() gives us a classmap similar to a // Composer 'classmap' array. $test_classes = $test_discovery->findAllClassFiles(); // JSON output is the easiest. @@ -177,15 +177,6 @@ if (!Composer::upgradePHPUnitCheck(Version::id())) { exit(SIMPLETEST_SCRIPT_EXIT_FAILURE); } -echo "\n"; -echo "Drupal test run\n\n"; -echo sprintf("Drupal Version: %s\n", \Drupal::VERSION); -echo sprintf("PHP Version: %s\n", \PHP_VERSION); -echo sprintf("PHP Binary: %s\n", $php ?? getenv('_')); -echo sprintf("PHPUnit Version: %s\n", Version::id()); -echo "-------------------------------\n"; -echo "\n"; - $test_list = simpletest_script_get_test_list(); // Try to allocate unlimited time to run the tests. @@ -364,11 +355,6 @@ All arguments are long options. The index of the job in the job set. - --debug-discovery - - If provided, dumps detailed information on the tests selected - for execution, before the execution starts. - <test1>[,<test2>[,<test3> ...]] One or more tests to be run. By default, these are interpreted @@ -441,7 +427,6 @@ function simpletest_script_parse_args() { 'non-html' => FALSE, 'ci-parallel-node-index' => 1, 'ci-parallel-node-total' => 1, - 'debug-discovery' => FALSE, ]; // Override with set values. @@ -934,15 +919,17 @@ function simpletest_script_command(TestRun $test_run, string $test_class): array function simpletest_script_get_test_list() { global $args; - $test_discovery = new PhpUnitTestDiscovery(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core'); + $test_discovery = new TestDiscovery( + \Drupal::root(), + \Drupal::service('class_loader') + ); + $types_processed = empty($args['types']); $test_list = []; $slow_tests = []; if ($args['all'] || $args['module'] || $args['directory']) { try { $groups = $test_discovery->getTestClasses($args['module'], $args['types'], $args['directory']); - foreach ($test_discovery->getWarnings() as $warning) { - simpletest_script_print($warning . "\n", SIMPLETEST_SCRIPT_COLOR_EXCEPTION); - } + $types_processed = TRUE; } catch (Exception $e) { echo (string) $e; @@ -951,34 +938,30 @@ function simpletest_script_get_test_list() { // Ensure that tests marked explicitly as @group #slow are run at the // beginning of each job. if (key($groups) === '#slow') { - $slow_tests = array_shift($groups); + $slow_tests = array_keys(array_shift($groups)); } $not_slow_tests = []; foreach ($groups as $group => $tests) { - $not_slow_tests = array_merge($not_slow_tests, $tests); + $not_slow_tests = array_merge($not_slow_tests, array_keys($tests)); } // Filter slow tests out of the not slow tests and ensure a unique list // since tests may appear in more than one group. - $not_slow_tests = array_diff_key($not_slow_tests, $slow_tests); + $not_slow_tests = array_unique(array_diff($not_slow_tests, $slow_tests)); // If the tests are not being run in parallel, then ensure slow tests run // all together first. if ((int) $args['ci-parallel-node-total'] <= 1 ) { sort_tests_by_type_and_methods($slow_tests); sort_tests_by_type_and_methods($not_slow_tests); - $all_tests_list = array_merge($slow_tests, $not_slow_tests); - assign_tests_sequence($all_tests_list); - dump_tests_sequence($all_tests_list, $args); - $test_list = array_keys($all_tests_list); + $test_list = array_merge($slow_tests, $not_slow_tests); } else { - // Sort all tests by the number of test cases on the test class. - // This is used in combination with @group #slow to start the slowest - // tests first and distribute tests between test runners. + // Sort all tests by the number of public methods on the test class. + // This is a proxy for the approximate time taken to run the test, + // which is used in combination with @group #slow to start the slowest tests + // first and distribute tests between test runners. sort_tests_by_public_method_count($slow_tests); sort_tests_by_public_method_count($not_slow_tests); - $all_tests_list = array_merge($slow_tests, $not_slow_tests); - assign_tests_sequence($all_tests_list); // Now set up a bin per test runner. $bin_count = (int) $args['ci-parallel-node-total']; @@ -992,8 +975,6 @@ function simpletest_script_get_test_list() { $binned_other_tests = place_tests_into_bins($not_slow_tests, $bin_count); $other_tests_for_job = $binned_other_tests[$args['ci-parallel-node-index'] - 1]; $test_list = array_merge($slow_tests_for_job, $other_tests_for_job); - dump_bin_tests_sequence($args['ci-parallel-node-index'], $all_tests_list, $test_list, $args); - $test_list = array_keys($test_list); } } else { @@ -1007,9 +988,6 @@ function simpletest_script_get_test_list() { else { try { $groups = $test_discovery->getTestClasses(NULL, $args['types']); - foreach ($test_discovery->getWarnings() as $warning) { - simpletest_script_print($warning . "\n", SIMPLETEST_SCRIPT_COLOR_EXCEPTION); - } } catch (Exception $e) { echo (string) $e; @@ -1027,24 +1005,19 @@ function simpletest_script_get_test_list() { } elseif ($args['file']) { // Extract test case class names from specified files. + $parser = new TestFileParser(); foreach ($args['test_names'] as $file) { - if (!file_exists($file) || is_dir($file)) { + if (!file_exists($file)) { simpletest_script_print_error('File not found: ' . $file); exit(SIMPLETEST_SCRIPT_EXIT_FAILURE); } - $fileTests = current($test_discovery->getTestClasses(NULL, [], $file)); - $test_list = array_merge($test_list, $fileTests); + $test_list = array_merge($test_list, $parser->getTestListFromFile($file)); } - assign_tests_sequence($test_list); - dump_tests_sequence($test_list, $args); - $test_list = array_keys($test_list); } else { try { $groups = $test_discovery->getTestClasses(NULL, $args['types']); - foreach ($test_discovery->getWarnings() as $warning) { - simpletest_script_print($warning . "\n", SIMPLETEST_SCRIPT_COLOR_EXCEPTION); - } + $types_processed = TRUE; } catch (Exception $e) { echo (string) $e; @@ -1061,15 +1034,22 @@ function simpletest_script_get_test_list() { } // Merge the tests from the groups together. foreach ($args['test_names'] as $group_name) { - $test_list = array_merge($test_list, $groups[$group_name]); + $test_list = array_merge($test_list, array_keys($groups[$group_name])); } - assign_tests_sequence($test_list); - dump_tests_sequence($test_list, $args); // Ensure our list of tests contains only one entry for each test. - $test_list = array_keys($test_list); + $test_list = array_unique($test_list); } } + // If the test list creation does not automatically limit by test type then + // we need to do so here. + if (!$types_processed) { + $test_list = array_filter($test_list, function ($test_class) use ($args) { + $test_info = TestDiscovery::getTestInfo($test_class); + return in_array($test_info['type'], $args['types'], TRUE); + }); + } + if (empty($test_list)) { simpletest_script_print_error('No valid tests were specified.'); exit(SIMPLETEST_SCRIPT_EXIT_FAILURE); @@ -1082,11 +1062,11 @@ function simpletest_script_get_test_list() { * Sort tests by test type and number of public methods. */ function sort_tests_by_type_and_methods(array &$tests): void { - uasort($tests, function ($a, $b) { - if (get_test_type_weight($a['name']) === get_test_type_weight($b['name'])) { - return $b['tests_count'] <=> $a['tests_count']; + usort($tests, function ($a, $b) { + if (get_test_type_weight($a) === get_test_type_weight($b)) { + return get_test_class_method_count($b) <=> get_test_class_method_count($a); } - return get_test_type_weight($b['name']) <=> get_test_type_weight($a['name']); + return get_test_type_weight($b) <=> get_test_type_weight($a); }); } @@ -1103,8 +1083,8 @@ function sort_tests_by_type_and_methods(array &$tests): void { * An array of test class names. */ function sort_tests_by_public_method_count(array &$tests): void { - uasort($tests, function ($a, $b) { - return $b['tests_count'] <=> $a['tests_count']; + usort($tests, function ($a, $b) { + return get_test_class_method_count($b) <=> get_test_class_method_count($a); }); } @@ -1125,46 +1105,28 @@ function get_test_type_weight(string $class): int { } /** - * Assigns the test sequence. + * Get an approximate test method count for a test class. * - * @param array $tests - * The array of test class info. - */ -function assign_tests_sequence(array &$tests): void { - $i = 0; - foreach ($tests as &$testInfo) { - $testInfo['sequence'] = ++$i; - } -} - -/** - * Dumps the list of tests in order of execution after sorting. - * - * @param array $tests - * The array of test class info. - * @param array $args - * The command line arguments. + * @param string $class + * The test class name. */ -function dump_tests_sequence(array $tests, array $args): void { - if ($args['debug-discovery'] === FALSE) { - return; - } - echo "Test execution sequence\n"; - echo "-----------------------\n\n"; - echo " Seq Slow? Group Cnt Class\n"; - echo "-----------------------------------------\n"; - $i = 0; - foreach ($tests as $testInfo) { - echo sprintf( - "%4d %5s %15s %4d %s\n", - $testInfo['sequence'], - in_array('#slow', $testInfo['groups']) ? '#slow' : '', - trim_with_ellipsis($testInfo['group'], 15, \STR_PAD_RIGHT), - $testInfo['tests_count'], - trim_with_ellipsis($testInfo['name'], 60, \STR_PAD_LEFT), - ); +function get_test_class_method_count(string $class): int { + $reflection = new \ReflectionClass($class); + $count = 0; + foreach ($reflection->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { + // If a method uses a dataProvider, increase the count by 20 since data + // providers result in a single method running multiple times. + $comments = $method->getDocComment(); + preg_match_all('#@(.*?)\n#s', $comments, $annotations); + foreach ($annotations[1] as $annotation) { + if (str_starts_with($annotation, 'dataProvider')) { + $count = $count + 20; + continue; + } + } + $count++; } - echo "-----------------------------------------\n\n"; + return $count; } /** @@ -1187,51 +1149,13 @@ function place_tests_into_bins(array $tests, int $bin_count) { // Create a bin corresponding to each parallel test job. $bins = array_fill(0, $bin_count, []); // Go through each test and add them to one bin at a time. - $i = 0; foreach ($tests as $key => $test) { - $bins[($i++ % $bin_count)][$key] = $test; + $bins[($key % $bin_count)][] = $test; } return $bins; } /** - * Dumps the list of tests in order of execution for a bin. - * - * @param int $bin - * The bin. - * @param array $allTests - * The list of all test classes discovered. - * @param array $tests - * The list of test class to run for this bin. - * @param array $args - * The command line arguments. - */ -function dump_bin_tests_sequence(int $bin, array $allTests, array $tests, array $args): void { - if ($args['debug-discovery'] === FALSE) { - return; - } - echo "Test execution sequence. "; - echo "Tests marked *** will be executed in this PARALLEL BIN #{$bin}.\n"; - echo "-------------------------------------------------------------------------------------\n\n"; - echo "Bin Seq Slow? Group Cnt Class\n"; - echo "--------------------------------------------\n"; - foreach ($allTests as $testInfo) { - $inBin = isset($tests[$testInfo['name']]); - $message = sprintf( - "%s %4d %5s %15s %4d %s\n", - $inBin ? "***" : " ", - $testInfo['sequence'], - in_array('#slow', $testInfo['groups']) ? '#slow' : '', - trim_with_ellipsis($testInfo['group'], 15, \STR_PAD_RIGHT), - $testInfo['tests_count'], - trim_with_ellipsis($testInfo['name'], 60, \STR_PAD_LEFT), - ); - simpletest_script_print($message, $inBin ? SIMPLETEST_SCRIPT_COLOR_BRIGHT_WHITE : SIMPLETEST_SCRIPT_COLOR_GRAY); - } - echo "-------------------------------------------------\n\n"; -} - -/** * Initialize the reporter. */ function simpletest_script_reporter_init(): void { @@ -1246,6 +1170,12 @@ function simpletest_script_reporter_init(): void { 'debug' => 'Log', ]; + echo "\n"; + echo "Drupal test run\n"; + echo "Using PHP Binary: $php\n"; + echo "---------------\n"; + echo "\n"; + // Tell the user about what tests are to be run. if ($args['all']) { echo "All tests will run.\n\n"; @@ -1448,7 +1378,7 @@ function simpletest_script_reporter_display_results(TestRunResultsStorageInterfa function simpletest_script_format_result($result): void { global $args, $results_map, $color; - $summary = sprintf("%-9.9s %9.3fs %s\n", $results_map[$result->status], $result->time, trim_with_ellipsis($result->function, 80, STR_PAD_LEFT)); + $summary = sprintf("%-9.9s %9.3fs %-80.80s\n", $results_map[$result->status], $result->time, trim_with_ellipsis($result->function, 80, STR_PAD_LEFT)); simpletest_script_print($summary, simpletest_script_color_code($result->status)); @@ -1610,12 +1540,12 @@ function simpletest_script_load_messages_by_test_id(TestRunResultsStorageInterfa */ function trim_with_ellipsis(string $input, int $length, int $side): string { if (strlen($input) < $length) { - return str_pad($input, $length, ' ', \STR_PAD_RIGHT); + return str_pad($input, $length, ' ', STR_PAD_RIGHT); } elseif (strlen($input) > $length) { return match($side) { - \STR_PAD_RIGHT => substr($input, 0, $length - 1) . '…', - default => '…' . substr($input, -$length + 1), + STR_PAD_RIGHT => substr($input, 0, $length - 3) . '...', + default => '...' . substr($input, -$length + 3), }; } return $input; diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php deleted file mode 100644 index feb6addef2a..00000000000 --- a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Drupal\KernelTests\Core\Test; - -use Drupal\Core\Test\PhpUnitTestDiscovery; -use Drupal\Core\Test\TestDiscovery; -use Drupal\KernelTests\KernelTestBase; -use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; - -/** - * Tests ::findAllClassFiles() between TestDiscovery and PhpUnitTestDiscovery. - * - * PhpUnitTestDiscovery uses PHPUnit API to build the list of test classes, - * while TestDiscovery uses Drupal legacy code. - */ -#[CoversClass(PhpUnitTestDiscovery::class)] -#[Group('TestSuites')] -#[Group('Test')] -#[Group('#slow')] -class PhpUnitApiFindAllClassFilesTest extends KernelTestBase { - - /** - * Checks that Drupal legacy and PHPUnit API based discoveries are equal. - */ - #[DataProvider('argumentsProvider')] - #[IgnoreDeprecations] - public function testEquality(?string $extension = NULL, ?string $directory = NULL): void { - $testDiscovery = new TestDiscovery( - $this->container->getParameter('app.root'), - $this->container->get('class_loader') - ); - $internalList = $testDiscovery->findAllClassFiles($extension, $directory); - - // Location of PHPUnit configuration file. - $configurationFilePath = $this->container->getParameter('app.root') . \DIRECTORY_SEPARATOR . 'core'; - // @todo once PHPUnit 10 is no longer used, remove the condition. - // @see https://www.drupal.org/project/drupal/issues/3497116 - if (RunnerVersion::getMajor() >= 11) { - $configurationFilePath .= \DIRECTORY_SEPARATOR . '.phpunit-next.xml'; - } - - $phpUnitTestDiscovery = new PhpUnitTestDiscovery($configurationFilePath); - - $phpUnitList = $phpUnitTestDiscovery->findAllClassFiles($extension, $directory); - - // Downgrade results to make them comparable, working around bugs and - // additions. - // 1. TestDiscovery discovers non-test classes that PHPUnit does not. - $internalList = array_intersect_key($internalList, $phpUnitList); - - $this->assertEquals($internalList, $phpUnitList); - } - - /** - * Provides test data to ::testEquality. - */ - public static function argumentsProvider(): \Generator { - yield 'All tests' => []; - yield 'Extension: system' => ['extension' => 'system']; - yield 'Extension: system, directory' => [ - 'extension' => 'system', - 'directory' => 'core/modules/system/tests/src', - ]; - } - -} diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php deleted file mode 100644 index 32d21e3e6c3..00000000000 --- a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Drupal\KernelTests\Core\Test; - -use Drupal\Core\Test\PhpUnitTestDiscovery; -use Drupal\Core\Test\TestDiscovery; -use Drupal\KernelTests\KernelTestBase; -use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; - -/** - * Tests ::getTestClasses() between TestDiscovery and PhpPUnitTestDiscovery. - * - * PhpPUnitTestDiscovery uses PHPUnit API to build the list of test classes, - * while TestDiscovery uses Drupal legacy code. - */ -#[CoversClass(PhpUnitTestDiscovery::class)] -#[Group('TestSuites')] -#[Group('Test')] -#[Group('#slow')] -class PhpUnitApiGetTestClassesTest extends KernelTestBase { - - /** - * Checks that Drupal legacy and PHPUnit API based discoveries are equal. - */ - #[DataProvider('argumentsProvider')] - #[IgnoreDeprecations] - public function testEquality(array $suites, ?string $extension = NULL, ?string $directory = NULL): void { - $testDiscovery = new TestDiscovery( - $this->container->getParameter('app.root'), - $this->container->get('class_loader') - ); - $internalList = $testDiscovery->getTestClasses($extension, $suites, $directory); - - // Location of PHPUnit configuration file. - $configurationFilePath = $this->container->getParameter('app.root') . \DIRECTORY_SEPARATOR . 'core'; - // @todo once PHPUnit 10 is no longer used, remove the condition. - // @see https://www.drupal.org/project/drupal/issues/3497116 - if (RunnerVersion::getMajor() >= 11) { - $configurationFilePath .= \DIRECTORY_SEPARATOR . '.phpunit-next.xml'; - } - - $phpUnitTestDiscovery = new PhpUnitTestDiscovery($configurationFilePath); - - $phpUnitList = $phpUnitTestDiscovery->getTestClasses($extension, $suites, $directory); - - // Downgrade results to make them comparable, working around bugs and - // additions. - // 1. Remove TestDiscovery empty groups. - $internalList = array_filter($internalList); - // 2. Remove TestDiscovery '##no-group-annotations' group. - unset($internalList['##no-group-annotations']); - // 3. Remove 'file' and 'tests_count' keys from PHPUnit results. - foreach ($phpUnitList as &$group) { - foreach ($group as &$testClass) { - unset($testClass['file']); - unset($testClass['tests_count']); - } - } - // 4. Remove from PHPUnit results groups not found by TestDiscovery. - $phpUnitList = array_intersect_key($phpUnitList, $internalList); - // 5. Remove from PHPUnit groups classes not found by TestDiscovery. - foreach ($phpUnitList as $groupName => &$group) { - $group = array_intersect_key($group, $internalList[$groupName]); - } - // 6. Remove from PHPUnit test classes groups not found by TestDiscovery. - foreach ($phpUnitList as $groupName => &$group) { - foreach ($group as $testClassName => &$testClass) { - $testClass['groups'] = array_intersect_key($testClass['groups'], $internalList[$groupName][$testClassName]['groups']); - } - } - - $this->assertEquals($internalList, $phpUnitList); - } - - /** - * Provides test data to ::testEquality. - */ - public static function argumentsProvider(): \Generator { - yield 'All tests' => ['suites' => []]; - yield 'Testsuite: functional-javascript' => ['suites' => ['PHPUnit-FunctionalJavascript']]; - yield 'Testsuite: functional' => ['suites' => ['PHPUnit-Functional']]; - yield 'Testsuite: kernel' => ['suites' => ['PHPUnit-Kernel']]; - yield 'Testsuite: unit' => ['suites' => ['PHPUnit-Unit']]; - yield 'Testsuite: unit-component' => ['suites' => ['PHPUnit-Unit-Component']]; - yield 'Testsuite: build' => ['suites' => ['PHPUnit-Build']]; - yield 'Extension: system' => ['suites' => [], 'extension' => 'system']; - yield 'Extension: system, testsuite: unit' => [ - 'suites' => ['PHPUnit-Unit'], - 'extension' => 'system', - ]; - yield 'Extension: system, directory' => [ - 'suites' => [], - 'extension' => 'system', - 'directory' => 'core/modules/system/tests/src', - ]; - yield 'Extension: system, testsuite: unit, directory' => [ - 'suites' => ['PHPUnit-Unit'], - 'extension' => 'system', - 'directory' => 'core/modules/system/tests/src', - ]; - } - -} diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitTestDiscoveryTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitTestDiscoveryTest.php index d8534458049..705981f7507 100644 --- a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitTestDiscoveryTest.php +++ b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitTestDiscoveryTest.php @@ -7,8 +7,6 @@ namespace Drupal\KernelTests\Core\Test; use Drupal\Core\Test\TestDiscovery; use Drupal\KernelTests\KernelTestBase; use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\TextUI\Configuration\Builder; use PHPUnit\TextUI\Configuration\TestSuiteBuilder; use Symfony\Component\Process\Process; @@ -24,10 +22,11 @@ use Symfony\Component\Process\Process; * list thus generated, with the list generated by * \Drupal\Core\Test\TestDiscovery, which is used by run-tests.sh, to ensure * both methods will run the same tests, + * + * @group TestSuites + * @group Test + * @group #slow */ -#[Group('TestSuites')] -#[Group('Test')] -#[Group('#slow')] class PhpUnitTestDiscoveryTest extends KernelTestBase { private const TEST_LIST_MISMATCH_MESSAGE = @@ -62,7 +61,6 @@ class PhpUnitTestDiscoveryTest extends KernelTestBase { /** * Tests equality of test discovery between run-tests.sh and PHPUnit CLI. */ - #[IgnoreDeprecations] public function testPhpUnitTestDiscoveryEqualsInternal(): void { // Drupal's test discovery, used by run-tests.sh. $testDiscovery = new TestDiscovery( @@ -78,19 +76,11 @@ class PhpUnitTestDiscoveryTest extends KernelTestBase { $internalList = array_unique($internalList); asort($internalList); - // Location of PHPUnit configuration file. - $configurationFilePath = $this->root . \DIRECTORY_SEPARATOR . 'core'; - // @todo once PHPUnit 10 is no longer used, remove the condition. - // @see https://www.drupal.org/project/drupal/issues/3497116 - if (RunnerVersion::getMajor() >= 11) { - $configurationFilePath .= \DIRECTORY_SEPARATOR . '.phpunit-next.xml'; - } - // PHPUnit's test discovery - via CLI execution. $process = new Process([ 'vendor/bin/phpunit', '--configuration', - $configurationFilePath, + 'core', '--list-tests-xml', $this->xmlOutputFile, ], $this->root); @@ -123,8 +113,14 @@ class PhpUnitTestDiscoveryTest extends KernelTestBase { // Check against Drupal's discovery. $this->assertEquals(implode("\n", $phpUnitClientList), implode("\n", $internalList), self::TEST_LIST_MISMATCH_MESSAGE); + // @todo once PHPUnit 10 is no longer used re-enable the rest of the test. + // @see https://www.drupal.org/project/drupal/issues/3497116 + if (RunnerVersion::getMajor() >= 11) { + $this->markTestIncomplete('On PHPUnit 11+ the test triggers warnings due to phpunit.xml setup. Re-enable in https://www.drupal.org/project/drupal/issues/3497116.'); + } + // PHPUnit's test discovery - via API. - $phpUnitConfiguration = (new Builder())->build(['--configuration', $configurationFilePath]); + $phpUnitConfiguration = (new Builder())->build(['--configuration', 'core']); $phpUnitTestSuite = (new TestSuiteBuilder())->build($phpUnitConfiguration); $phpUnitApiList = []; foreach ($phpUnitTestSuite->tests() as $testSuite) { diff --git a/core/tests/Drupal/Tests/Core/Menu/LocalActionManagerTest.php b/core/tests/Drupal/Tests/Core/Menu/LocalActionManagerTest.php index d0759a4bf08..08fa2eceaf5 100644 --- a/core/tests/Drupal/Tests/Core/Menu/LocalActionManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Menu/LocalActionManagerTest.php @@ -203,8 +203,6 @@ class LocalActionManagerTest extends UnitTestCase { } public static function getActionsForRouteProvider() { - $originalContainer = \Drupal::hasContainer() ? \Drupal::getContainer() : NULL; - $cache_contexts_manager = (new Prophet())->prophesize(CacheContextsManager::class); $cache_contexts_manager->assertValidTokens(Argument::any()) ->willReturn(TRUE); @@ -386,11 +384,6 @@ class LocalActionManagerTest extends UnitTestCase { ], ]; - // Restore the original container if needed. - if ($originalContainer) { - \Drupal::setContainer($originalContainer); - } - return $data; } diff --git a/core/tests/Drupal/Tests/Core/Test/RunTests/TestFileParserTest.php b/core/tests/Drupal/Tests/Core/Test/RunTests/TestFileParserTest.php index 9138d54523d..957b2f61f97 100644 --- a/core/tests/Drupal/Tests/Core/Test/RunTests/TestFileParserTest.php +++ b/core/tests/Drupal/Tests/Core/Test/RunTests/TestFileParserTest.php @@ -6,18 +6,12 @@ namespace Drupal\Tests\Core\Test\RunTests; use Drupal\Core\Test\RunTests\TestFileParser; use Drupal\Tests\UnitTestCase; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; /** - * Tests for the deprecated TestFileParser class. + * @coversDefaultClass \Drupal\Core\Test\RunTests\TestFileParser + * @group Test + * @group RunTests */ -#[CoversClass(TestFileParser::class)] -#[Group('Test')] -#[Group('RunTest')] -#[IgnoreDeprecations] class TestFileParserTest extends UnitTestCase { public static function provideTestFileContents() { @@ -72,9 +66,9 @@ COMPOUND } /** - * @legacy-covers ::parseContents + * @covers ::parseContents + * @dataProvider provideTestFileContents */ - #[DataProvider('provideTestFileContents')] public function testParseContents($expected, $contents): void { $parser = new TestFileParser(); @@ -84,7 +78,7 @@ COMPOUND } /** - * @legacy-covers ::getTestListFromFile + * @covers ::getTestListFromFile */ public function testGetTestListFromFile(): void { $parser = new TestFileParser(); diff --git a/core/tests/Drupal/Tests/Core/Test/TestDiscoveryTest.php b/core/tests/Drupal/Tests/Core/Test/TestDiscoveryTest.php index 0fb55e6c7f8..bfbb4ca2e40 100644 --- a/core/tests/Drupal/Tests/Core/Test/TestDiscoveryTest.php +++ b/core/tests/Drupal/Tests/Core/Test/TestDiscoveryTest.php @@ -13,23 +13,17 @@ use Drupal\Core\Test\Exception\MissingGroupException; use Drupal\Core\Test\TestDiscovery; use Drupal\Tests\UnitTestCase; use org\bovigo\vfs\vfsStream; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; /** - * Unit tests for TestDiscovery. + * @coversDefaultClass \Drupal\Core\Test\TestDiscovery + * @group Test */ -#[CoversClass(TestDiscovery::class)] -#[Group('Test')] -#[IgnoreDeprecations] class TestDiscoveryTest extends UnitTestCase { /** - * @legacy-covers ::getTestInfo + * @covers ::getTestInfo + * @dataProvider infoParserProvider */ - #[DataProvider('infoParserProvider')] public function testTestInfoParser($expected, $classname, $doc_comment = NULL): void { $info = TestDiscovery::getTestInfo($classname, $doc_comment); $this->assertEquals($expected, $info); @@ -40,14 +34,14 @@ class TestDiscoveryTest extends UnitTestCase { $tests[] = [ // Expected result. [ - 'name' => TestDatabaseTest::class, + 'name' => static::class, 'group' => 'Test', - 'groups' => ['Test', 'simpletest', 'Template'], - 'description' => 'Tests \Drupal\Core\Test\TestDatabase.', + 'groups' => ['Test'], + 'description' => 'Tests \Drupal\Core\Test\TestDiscovery.', 'type' => 'PHPUnit-Unit', ], // Classname. - TestDatabaseTest::class, + static::class, ]; // A core unit test. @@ -223,7 +217,7 @@ class TestDiscoveryTest extends UnitTestCase { } /** - * @legacy-covers ::getTestInfo + * @covers ::getTestInfo */ public function testTestInfoParserMissingGroup(): void { $classname = 'Drupal\KernelTests\field\BulkDeleteTest'; @@ -238,7 +232,7 @@ EOT; } /** - * @legacy-covers ::getTestInfo + * @covers ::getTestInfo */ public function testTestInfoParserMissingSummary(): void { $classname = 'Drupal\KernelTests\field\BulkDeleteTest'; @@ -317,7 +311,7 @@ EOF; } /** - * @legacy-covers ::getTestClasses + * @covers ::getTestClasses */ public function testGetTestClasses(): void { $this->setupVfsWithTestClasses(); @@ -386,7 +380,7 @@ EOF; } /** - * @legacy-covers ::getTestClasses + * @covers ::getTestClasses */ public function testGetTestClassesWithSelectedTypes(): void { $this->setupVfsWithTestClasses(); @@ -431,7 +425,7 @@ EOF; } /** - * @legacy-covers ::getTestClasses + * @covers ::getTestClasses */ public function testGetTestsInProfiles(): void { $this->setupVfsWithTestClasses(); @@ -460,9 +454,9 @@ EOF; } /** - * @legacy-covers ::getPhpunitTestSuite + * @covers ::getPhpunitTestSuite + * @dataProvider providerTestGetPhpunitTestSuite */ - #[DataProvider('providerTestGetPhpunitTestSuite')] public function testGetPhpunitTestSuite($classname, $expected): void { $this->assertEquals($expected, TestDiscovery::getPhpunitTestSuite($classname)); } @@ -488,7 +482,7 @@ EOF; /** * Ensure that classes are not reflected when the docblock is empty. * - * @legacy-covers ::getTestInfo + * @covers ::getTestInfo */ public function testGetTestInfoEmptyDocblock(): void { // If getTestInfo() performed reflection, it won't be able to find the @@ -503,7 +497,7 @@ EOF; /** * Ensure TestDiscovery::scanDirectory() ignores certain abstract file types. * - * @legacy-covers ::scanDirectory + * @covers ::scanDirectory */ public function testScanDirectoryNoAbstract(): void { $this->setupVfsWithTestClasses(); |