diff options
12 files changed, 176 insertions, 20 deletions
diff --git a/core/lib/Drupal/Core/Test/PhpUnitTestDiscovery.php b/core/lib/Drupal/Core/Test/PhpUnitTestDiscovery.php index d9737028821c..a02894c1c74d 100644 --- a/core/lib/Drupal/Core/Test/PhpUnitTestDiscovery.php +++ b/core/lib/Drupal/Core/Test/PhpUnitTestDiscovery.php @@ -6,6 +6,8 @@ namespace Drupal\Core\Test; use Drupal\Core\Test\Exception\MissingGroupException; use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion; +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Framework\DataProviderTestSuite; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestCase; @@ -21,6 +23,13 @@ use PHPUnit\TextUI\Configuration\TestSuiteBuilder; class PhpUnitTestDiscovery { /** + * The singleton. + * + * @var \Drupal\Core\Test\PhpUnitTestDiscovery|null + */ + private static ?self $instance = NULL; + + /** * The map of legacy test suite identifiers to phpunit.xml ones. * * @var array<string,string> @@ -42,16 +51,44 @@ class PhpUnitTestDiscovery { private array $reverseMap; /** + * Path to PHPUnit's configuration file. + */ + private string $configurationFilePath; + + /** * The warnings generated during the discovery. * * @var list<string> */ private array $warnings = []; - public function __construct( - private string $configurationFilePath, - ) { + private function __construct() { $this->reverseMap = array_flip($this->map); + try { + EventFacade::instance()->registerTracer(new PhpUnitTestDiscoveryTracer($this)); + EventFacade::instance()->seal(); + } + catch (EventFacadeIsSealedException) { + // Just continue. + } + } + + /** + * Returns the singleton instance. + */ + public static function instance(): self { + if (self::$instance === NULL) { + self::$instance = new self(); + } + return self::$instance; + } + + /** + * Sets the configuration file path. + */ + public function setConfigurationFilePath(string $configurationFilePath): self { + $this->configurationFilePath = $configurationFilePath; + return $this; } /** @@ -109,9 +146,11 @@ class PhpUnitTestDiscovery { } $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.'; + $this->addWarning( + ">>> The service container was changed during the test discovery <<<\n" . + "Probably, a test data provider method called \\Drupal::setContainer().\n" . + "Ensure that all the data providers restore the original container before returning data." + ); assert(isset($container)); \Drupal::setContainer($container); } @@ -153,6 +192,16 @@ class PhpUnitTestDiscovery { } /** + * Adds warning message generated during the discovery. + * + * @param string $message + * The warning message. + */ + public function addWarning(string $message): void { + $this->warnings[] = $message; + } + + /** * Returns the warnings generated during the discovery. * * @return list<string> @@ -180,6 +229,10 @@ class PhpUnitTestDiscovery { $list = []; foreach ($phpUnitTestSuite->tests() as $testSuite) { foreach ($testSuite->tests() as $testClass) { + if ($testClass->isEmpty()) { + continue; + } + if ($extension !== NULL && !str_starts_with($testClass->name(), "Drupal\\Tests\\{$extension}\\")) { continue; } @@ -218,6 +271,10 @@ class PhpUnitTestDiscovery { // In this case, PHPUnit found a single test class to run tests for. if ($phpUnitTestSuite->isForTestClass()) { + if ($phpUnitTestSuite->isEmpty()) { + return []; + } + if ($extension !== NULL && !str_starts_with($phpUnitTestSuite->name(), "Drupal\\Tests\\{$extension}\\")) { return []; } @@ -239,6 +296,10 @@ class PhpUnitTestDiscovery { // Multiple test classes were found. $list = []; foreach ($phpUnitTestSuite->tests() as $testClass) { + if ($testClass->isEmpty()) { + continue; + } + if ($extension !== NULL && !str_starts_with($testClass->name(), "Drupal\\Tests\\{$extension}\\")) { continue; } diff --git a/core/lib/Drupal/Core/Test/PhpUnitTestDiscoveryTracer.php b/core/lib/Drupal/Core/Test/PhpUnitTestDiscoveryTracer.php new file mode 100644 index 000000000000..681704830967 --- /dev/null +++ b/core/lib/Drupal/Core/Test/PhpUnitTestDiscoveryTracer.php @@ -0,0 +1,38 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Core\Test; + +use PHPUnit\Event\Event; +use PHPUnit\Event\Test\PhpunitErrorTriggered; +use PHPUnit\Event\Test\PhpunitWarningTriggered; +use PHPUnit\Event\TestRunner\WarningTriggered; +use PHPUnit\Event\Tracer\Tracer; + +/** + * Traces events dispatched by PHPUnit during the test discovery. + * + * @internal + */ +class PhpUnitTestDiscoveryTracer implements Tracer { + + public function __construct( + private readonly PHPUnitTestDiscovery $testDiscovery, + ) { + } + + /** + * {@inheritdoc} + */ + public function trace(Event $event): void { + if (in_array(get_class($event), [ + PhpunitErrorTriggered::class, + PhpunitWarningTriggered::class, + WarningTriggered::class, + ])) { + $this->testDiscovery->addWarning(sprintf('%s: %s', get_class($event), $event->message())); + } + } + +} diff --git a/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/CommentTypeRequirementsTest.php b/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/CommentTypeRequirementsTest.php index 379e51803b05..c04c478f3a2f 100644 --- a/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/CommentTypeRequirementsTest.php +++ b/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/CommentTypeRequirementsTest.php @@ -11,6 +11,7 @@ use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; * Tests check requirements for comment type source plugin. * * @group comment + * @group #slow */ class CommentTypeRequirementsTest extends MigrateDrupal7TestBase { diff --git a/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceLabelDescriptionTest.php b/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceLabelDescriptionTest.php index ca81ab17602b..20ea2c954b2c 100644 --- a/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceLabelDescriptionTest.php +++ b/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceLabelDescriptionTest.php @@ -13,6 +13,7 @@ use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase; * Tests migration of field label and description translations. * * @group migrate_drupal_6 + * @group #slow */ class MigrateFieldInstanceLabelDescriptionTest extends MigrateDrupal6TestBase implements MigrateDumpAlterInterface { diff --git a/core/modules/migrate_drupal/tests/src/Kernel/d7/FollowUpMigrationsTest.php b/core/modules/migrate_drupal/tests/src/Kernel/d7/FollowUpMigrationsTest.php index 151b7fae2477..c7d40c4c2d9d 100644 --- a/core/modules/migrate_drupal/tests/src/Kernel/d7/FollowUpMigrationsTest.php +++ b/core/modules/migrate_drupal/tests/src/Kernel/d7/FollowUpMigrationsTest.php @@ -12,6 +12,7 @@ use Drupal\user\Entity\User; * Tests follow-up migrations. * * @group migrate_drupal + * @group #slow */ class FollowUpMigrationsTest extends MigrateDrupal7TestBase { diff --git a/core/modules/package_manager/tests/src/Build/PackageInstallDirectWriteTest.php b/core/modules/package_manager/tests/src/Build/PackageInstallDirectWriteTest.php new file mode 100644 index 000000000000..307d17cdcdb3 --- /dev/null +++ b/core/modules/package_manager/tests/src/Build/PackageInstallDirectWriteTest.php @@ -0,0 +1,52 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\package_manager\Build; + +use PHPUnit\Framework\Attributes\Group; + +/** + * Tests installing packages with direct write mode enabled. + * + * @internal + */ +#[Group('package_manager')] +#[Group('#slow')] +class PackageInstallDirectWriteTest extends TemplateProjectTestBase { + + /** + * Tests installing packages in a stage directory. + */ + public function testPackageInstall(): void { + $this->createTestProject('RecommendedProject'); + $allow_direct_write = var_export(TRUE, TRUE); + $this->writeSettings("\n\$settings['package_manager_allow_direct_write'] = $allow_direct_write;"); + + $this->setReleaseMetadata([ + 'alpha' => __DIR__ . '/../../fixtures/release-history/alpha.1.1.0.xml', + ]); + $this->addRepository('alpha', $this->copyFixtureToTempDirectory(__DIR__ . '/../../fixtures/build_test_projects/alpha/1.0.0')); + // Repository definitions affect the lock file hash, so update the hash to + // ensure that Composer won't complain that the lock file is out of sync. + $this->runComposer('composer update --lock', 'project'); + + // Use the API endpoint to create a stage and install alpha 1.0.0. + $this->makePackageManagerTestApiRequest( + '/package-manager-test-api', + [ + 'runtime' => [ + 'drupal/alpha:1.0.0', + ], + ] + ); + // Assert the module was installed. + $this->assertFileEquals( + __DIR__ . '/../../fixtures/build_test_projects/alpha/1.0.0/composer.json', + $this->getWebRoot() . '/modules/contrib/alpha/composer.json', + ); + $this->assertRequestedChangesWereLogged(['Install drupal/alpha 1.0.0']); + $this->assertAppliedChangesWereLogged(['Installed drupal/alpha 1.0.0']); + } + +} diff --git a/core/modules/package_manager/tests/src/Build/PackageInstallTest.php b/core/modules/package_manager/tests/src/Build/PackageInstallTest.php index bea2c0d40243..362343eaa91a 100644 --- a/core/modules/package_manager/tests/src/Build/PackageInstallTest.php +++ b/core/modules/package_manager/tests/src/Build/PackageInstallTest.php @@ -15,15 +15,9 @@ class PackageInstallTest extends TemplateProjectTestBase { /** * Tests installing packages in a stage directory. - * - * @testWith [true] - * [false] */ - public function testPackageInstall(bool $allow_direct_write): void { + public function testPackageInstall(): void { $this->createTestProject('RecommendedProject'); - $allow_direct_write = var_export($allow_direct_write, TRUE); - $this->writeSettings("\n\$settings['package_manager_allow_direct_write'] = $allow_direct_write;"); - $this->setReleaseMetadata([ 'alpha' => __DIR__ . '/../../fixtures/release-history/alpha.1.1.0.xml', ]); diff --git a/core/modules/system/tests/src/Functional/Module/VersionTest.php b/core/modules/system/tests/src/Functional/Module/VersionTest.php index 7f3af598cfb8..1a98b7f246fa 100644 --- a/core/modules/system/tests/src/Functional/Module/VersionTest.php +++ b/core/modules/system/tests/src/Functional/Module/VersionTest.php @@ -8,6 +8,7 @@ namespace Drupal\Tests\system\Functional\Module; * Tests module version dependencies. * * @group Module + * @group #slow */ class VersionTest extends ModuleTestBase { diff --git a/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermTranslationTest.php b/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermTranslationTest.php index 1fb8b819fdc7..3499a404ac95 100644 --- a/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermTranslationTest.php +++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermTranslationTest.php @@ -12,6 +12,7 @@ use Drupal\taxonomy\TermInterface; * Test migration of translated taxonomy terms. * * @group migrate_drupal_7 + * @group #slow */ class MigrateTaxonomyTermTranslationTest extends MigrateDrupal7TestBase { diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index 96f16eed9c71..30e366f97b2e 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -89,7 +89,7 @@ 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 = PhpUnitTestDiscovery::instance()->setConfigurationFilePath(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core'); try { $groups = $test_discovery->getTestClasses($args['module']); foreach ($test_discovery->getWarnings() as $warning) { @@ -122,7 +122,7 @@ 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'); + $test_discovery = PhpUnitTestDiscovery::instance()->setConfigurationFilePath(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core'); // PhpUnitTestDiscovery::findAllClassFiles() gives us a classmap similar to a // Composer 'classmap' array. $test_classes = $test_discovery->findAllClassFiles(); @@ -934,14 +934,20 @@ 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 = PhpUnitTestDiscovery::instance()->setConfigurationFilePath(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core'); $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); + $warnings = $test_discovery->getWarnings(); + if (!empty($warnings)) { + simpletest_script_print("Test discovery warnings\n", SIMPLETEST_SCRIPT_COLOR_BRIGHT_WHITE); + simpletest_script_print("-----------------------\n", SIMPLETEST_SCRIPT_COLOR_BRIGHT_WHITE); + foreach ($warnings as $warning) { + simpletest_script_print('* ' . $warning . "\n\n", SIMPLETEST_SCRIPT_COLOR_EXCEPTION); + } + echo "\n"; } } catch (Exception $e) { diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php index 2afb26f1b9e0..a8697cc84968 100644 --- a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php +++ b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiFindAllClassFilesTest.php @@ -38,7 +38,7 @@ class PhpUnitApiFindAllClassFilesTest extends KernelTestBase { if (RunnerVersion::getMajor() >= 11) { $configurationFilePath .= \DIRECTORY_SEPARATOR . '.phpunit-next.xml'; } - $phpUnitTestDiscovery = new PhpUnitTestDiscovery($configurationFilePath); + $phpUnitTestDiscovery = PhpUnitTestDiscovery::instance()->setConfigurationFilePath($configurationFilePath); $phpUnitList = $phpUnitTestDiscovery->findAllClassFiles($extension, $directory); // Legacy TestDiscovery. diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php index 81cdfc9c6c5f..caedbc0d2b62 100644 --- a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php +++ b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitApiGetTestClassesTest.php @@ -38,7 +38,7 @@ class PhpUnitApiGetTestClassesTest extends KernelTestBase { if (RunnerVersion::getMajor() >= 11) { $configurationFilePath .= \DIRECTORY_SEPARATOR . '.phpunit-next.xml'; } - $phpUnitTestDiscovery = new PhpUnitTestDiscovery($configurationFilePath); + $phpUnitTestDiscovery = PhpUnitTestDiscovery::instance()->setConfigurationFilePath($configurationFilePath); $phpUnitList = $phpUnitTestDiscovery->getTestClasses($extension, $suites, $directory); // Legacy TestDiscovery. |