diff --git a/core/modules/simpletest/src/TestDiscovery.php b/core/modules/simpletest/src/TestDiscovery.php index d5d7d8a576..f6ac67cd53 100644 --- a/core/modules/simpletest/src/TestDiscovery.php +++ b/core/modules/simpletest/src/TestDiscovery.php @@ -189,14 +189,17 @@ public function getTestClasses($extension = NULL, array $types = []) { // abstract class, trait or test fixture. continue; } - // Skip this test class if it requires unavailable modules. - // @todo PHPUnit skips tests with unmet requirements when executing a test - // (instead of excluding them upfront). Refactor test runner to follow - // that approach. + // 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 (!empty($info['requires']['module'])) { - if (array_diff($info['requires']['module'], $this->availableExtensions['module'])) { - continue; + if ($info['type'] == 'Simpletest') { + if (!empty($info['requires']['module'])) { + if (array_diff($info['requires']['module'], $this->availableExtensions['module'])) { + continue; + } } } diff --git a/core/modules/simpletest/tests/src/Functional/MissingDependentModuleUnitTest.php b/core/modules/simpletest/tests/src/Functional/MissingDependentModuleUnitTest.php deleted file mode 100644 index 885a44c706..0000000000 --- a/core/modules/simpletest/tests/src/Functional/MissingDependentModuleUnitTest.php +++ /dev/null @@ -1,22 +0,0 @@ -fail('Running test with missing required module.'); - } - -} diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php index 5621d4aa19..45f70fb18b 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -45,9 +45,6 @@ * * @see \Drupal\Tests\KernelTestBase::$modules * @see \Drupal\Tests\KernelTestBase::enableModules() - * - * @todo Extend ::setRequirementsFromAnnotation() and ::checkRequirements() to - * account for '@requires module'. */ abstract class KernelTestBase extends \PHPUnit_Framework_TestCase implements ServiceProviderInterface { @@ -226,6 +223,51 @@ protected static function getDrupalRoot() { /** * {@inheritdoc} */ + protected function checkRequirements() { + parent::checkRequirements(); + + $this->root = static::getDrupalRoot(); + + // Check if required dependencies exist. + $annotations = $this->getAnnotations(); + if (!empty($annotations['class']['requires'])) { + $this->checkModuleRequirements($annotations['class']['requires']); + } + if (!empty($annotations['method']['requires'])) { + $this->checkModuleRequirements($annotations['method']['requires']); + } + } + + /** + * Checks missing module requirements. + * + * Iterates through a list of requires annotations and looks for missing + * modules. The test will be skipped if any of the required modules is + * missing. + * + * @param string[] $annotations + * A list of requires annotations from either a method or class annotation. + */ + protected function checkModuleRequirements(array $annotations) { + static::initFileCache(); + // drupal_valid_ua() might not be loaded. + require_once $this->root . '/core/includes/bootstrap.inc'; + foreach ($annotations as $requirement) { + if (strpos($requirement, 'module ') === 0) { + $module = trim(str_replace('module ', '', $requirement)); + try { + $this->getExtensionsForModules([$module]); + } + catch (\PHPUnit_Framework_Exception $e) { + throw new \PHPUnit_Framework_SkippedTestError("Module $module is required."); + } + } + } + } + + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); diff --git a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php index 7d89fd7bd8..be45e13051 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php +++ b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php @@ -206,6 +206,50 @@ public function testRenderWithTheme() { } /** + * Tests that a test method is skipped when it @requires a module not present. + * + * In order to catch checkRequirements() regressions, we have to make a new + * test object and run checkRequirements() here. + * + * @covers ::checkRequirements + * @covers ::checkModuleRequirements + */ + public function testMethodRequiresModule() { + $this->setExpectedException( + \PHPUnit_Framework_SkippedTestError::class, + 'Module drupal_dne_module is required.' + ); + + require __DIR__ . '/../../fixtures/MissingDependentModuleMethodTest.php'; + + $test = new MissingDependentModuleMethodTest(); + $test->setName('testMethodRequiresModule'); + $test->checkRequirements(); + } + + /** + * Tests that a test case is skipped when it @requires a module not present. + * + * In order to catch checkRequirements() regressions, we have to make a new + * test object and run checkRequirements() here. + * + * @covers ::checkRequirements + * @covers ::checkModuleRequirements + */ + public function testRequiresModule() { + $this->setExpectedException( + \PHPUnit_Framework_SkippedTestError::class, + 'Module drupal_dne_module is required.' + ); + + require __DIR__ . '/../../fixtures/MissingDependentModuleTest.php'; + + $test = new MissingDependentModuleTest(); + $test->setName('testRequiresModule'); + $test->checkRequirements(); + } + + /** * {@inheritdoc} */ protected function tearDown() { diff --git a/core/tests/fixtures/MissingDependentModuleMethodTest.php b/core/tests/fixtures/MissingDependentModuleMethodTest.php new file mode 100644 index 0000000000..15f0a23759 --- /dev/null +++ b/core/tests/fixtures/MissingDependentModuleMethodTest.php @@ -0,0 +1,28 @@ +fail('Running test with missing required module.'); + } + +} diff --git a/core/tests/fixtures/MissingDependentModuleTest.php b/core/tests/fixtures/MissingDependentModuleTest.php new file mode 100644 index 0000000000..ce2c49e593 --- /dev/null +++ b/core/tests/fixtures/MissingDependentModuleTest.php @@ -0,0 +1,30 @@ +fail('Running test with missing required module.'); + } + +}