diff --git a/core/lib/Drupal/Core/Test/TestRunnerKernel.php b/core/lib/Drupal/Core/Test/TestRunnerKernel.php index 963a6c4e4d..f5b2ffb357 100644 --- a/core/lib/Drupal/Core/Test/TestRunnerKernel.php +++ b/core/lib/Drupal/Core/Test/TestRunnerKernel.php @@ -39,7 +39,7 @@ public function __construct($environment, $class_loader, $allow_dumping = FALSE, ]; $this->moduleData = [ 'system' => new Extension($this->root, 'module', 'core/modules/system/system.info.yml', 'system.module'), - 'simpletest' => new Extension($this->root, 'module', 'core/modules/simpletest/simpletest.info.yml', 'simpletest.module'), + 'simpletest' => new Extension($this->root, 'module', 'core/modules/simpletest/simpletest.info.yml'), ]; } diff --git a/core/modules/simpletest/simpletest.info.yml b/core/modules/simpletest/simpletest.info.yml new file mode 100644 index 0000000000..232680e7cf --- /dev/null +++ b/core/modules/simpletest/simpletest.info.yml @@ -0,0 +1,7 @@ +name: Testing +type: module +description: 'Provides a framework for unit and functional testing.' +package: Core +version: VERSION +core: 8.x +configure: simpletest.settings diff --git a/core/modules/simpletest/simpletest.services.yml b/core/modules/simpletest/simpletest.services.yml new file mode 100644 index 0000000000..427947eaee --- /dev/null +++ b/core/modules/simpletest/simpletest.services.yml @@ -0,0 +1,6 @@ +services: + test_discovery: + # @todo This class is deprecated. We use it here to support the deprecated + # testing hooks. Remove this before Drupal 9. + class: Drupal\simpletest\TestDiscovery + arguments: ['@app.root', '@class_loader', '@module_handler'] diff --git a/core/modules/simpletest/src/TestDiscovery.php b/core/modules/simpletest/src/TestDiscovery.php new file mode 100644 index 0000000000..8ce8b7de46 --- /dev/null +++ b/core/modules/simpletest/src/TestDiscovery.php @@ -0,0 +1,150 @@ +moduleHandler = $module_handler; + } + + /** + * Discovers all available tests in all extensions. + * + * This method is a near-duplicate of + * \Drupal\Core\Tests\TestDiscovery::getTestClasses(). It exists so that we + * can provide a BC invocation of hook_simpletest_alter(). + * + * @param string $extension + * (optional) The name of an extension to limit discovery to; e.g., 'node'. + * @param string[] $types + * An array of included test types. + * + * @return array + * An array of tests keyed by the the group name. If a test is annotated to + * belong to multiple groups, it will appear under all group keys it belongs + * to. + * @code + * $groups['block'] => array( + * 'Drupal\Tests\block\Functional\BlockTest' => array( + * 'name' => 'Drupal\Tests\block\Functional\BlockTest', + * 'description' => 'Tests block UI CRUD functionality.', + * 'group' => 'block', + * 'groups' => ['block', 'group2', 'group3'], + * ), + * ); + * @endcode + */ + public function getTestClasses($extension = NULL, array $types = []) { + if (!isset($extension) && empty($types)) { + if (!empty($this->testClasses)) { + return $this->testClasses; + } + } + $list = []; + + $classmap = $this->findAllClassFiles($extension); + + // Prevent expensive class loader lookups for each reflected test class by + // registering the complete classmap of test classes to the class loader. + // This also ensures that test classes are loaded from the discovered + // pathnames; a namespace/classname mismatch will throw an exception. + $this->classLoader->addClassMap($classmap); + + foreach ($classmap as $classname => $pathname) { + $finder = MockFileFinder::create($pathname); + $parser = new StaticReflectionParser($classname, $finder, TRUE); + try { + $info = static::getTestInfo($classname, $parser->getDocComment()); + } + catch (MissingGroupException $e) { + // If the class name ends in Test and is not a migrate table dump. + if (preg_match('/Test$/', $classname) && strpos($classname, 'migrate_drupal\Tests\Table') === FALSE) { + throw $e; + } + // If the class is @group annotation just skip it. Most likely it is an + // abstract class, trait or test fixture. + continue; + } + // Skip this test class if it is a Simpletest-based test and requires + // unavailable modules. TestDiscovery should not filter out module + // requirements for PHPUnit-based test classes. + // @todo Move this behavior to \Drupal\simpletest\TestBase so tests can be + // marked as skipped, instead. + // @see https://www.drupal.org/node/1273478 + if ($info['type'] == 'Simpletest') { + if (!empty($info['requires']['module'])) { + if (array_diff($info['requires']['module'], $this->availableExtensions['module'])) { + continue; + } + } + } + + foreach ($info['groups'] as $group) { + $list[$group][$classname] = $info; + } + } + + // Sort the groups and tests within the groups by name. + uksort($list, 'strnatcasecmp'); + foreach ($list as &$tests) { + uksort($tests, 'strnatcasecmp'); + } + + // Allow modules extending core tests to disable originals. + $this->moduleHandler->alterDeprecated('Convert your test to a PHPUnit-based one and implement test listeners. See: https://www.drupal.org/node/2939892', 'simpletest', $list); + + if (!isset($extension) && empty($types)) { + $this->testClasses = $list; + } + + if ($types) { + $list = NestedArray::filter($list, function ($element) use ($types) { + return !(is_array($element) && isset($element['type']) && !in_array($element['type'], $types)); + }); + } + + return $list; + } + +}