diff --git a/composer.json b/composer.json index 8da852da9288c8c13a8ff3a4da3d6edbb96c16a7..6192b0ab500cdd0b8bbe8c98fad8a056759ef6cb 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "composer/composer": "^1.9.1", "drupal/coder": "^8.3.7", "mikey179/vfsstream": "^1.6.8", - "phpunit/phpunit": "^8.4.1", + "phpunit/phpunit": "^8.4.1 || ^9", "phpspec/prophecy": "^1.7", "symfony/css-selector": "^4.4", "symfony/phpunit-bridge": "^5.1.4", @@ -93,7 +93,10 @@ "pre-update-cmd": "Drupal\\Composer\\Composer::ensureComposerVersion", "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump", "drupal-phpunit-upgrade-check": "Drupal\\Core\\Composer\\Composer::upgradePHPUnit", - "drupal-phpunit-upgrade": "@composer update phpunit/phpunit symfony/phpunit-bridge phpspec/prophecy symfony/yaml --with-dependencies --no-progress", + "drupal-phpunit-upgrade": [ + "@composer update phpunit/phpunit --with-dependencies --no-progress", + "@composer require phpspec/prophecy-phpunit:^2 --no-progress --no-suggest" + ], "post-update-cmd": [ "Drupal\\Composer\\Composer::generateMetapackages" ], diff --git a/composer.lock b/composer.lock index 7654dfbdb221db6a990331224243101d40c26bc2..cd026c8142ca32c8414a07da6d5b7b1e59100d46 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "059e8aee61edb73b1526b840eb6c624c", + "content-hash": "09de613d0e44689de15282c33d3d700e", "packages": [ { "name": "asm89/stack-cors", diff --git a/composer/Metapackage/DevDependencies/composer.json b/composer/Metapackage/DevDependencies/composer.json index b6de7308ab55b9eccf565d35674c9a726befb382..ace515f3938631baea28c171e5e9caa94313adfb 100644 --- a/composer/Metapackage/DevDependencies/composer.json +++ b/composer/Metapackage/DevDependencies/composer.json @@ -16,7 +16,7 @@ "justinrainbow/json-schema": "^5.2", "mikey179/vfsstream": "^1.6.8", "phpspec/prophecy": "^1.7", - "phpunit/phpunit": "^8.4.1", + "phpunit/phpunit": "^8.4.1 || ^9", "symfony/browser-kit": "^4.4", "symfony/css-selector": "^4.4", "symfony/dom-crawler": "^4.4 !=4.4.5", diff --git a/core/lib/Drupal/Core/Composer/Composer.php b/core/lib/Drupal/Core/Composer/Composer.php index 6b7d5899d6e0ef7064909b4c5033f936fc988ce0..2f60ab9d0fc78a61c1de1a534d63f5c05d0872f7 100644 --- a/core/lib/Drupal/Core/Composer/Composer.php +++ b/core/lib/Drupal/Core/Composer/Composer.php @@ -310,7 +310,7 @@ public static function upgradePHPUnit(Event $event) { return; } - // If the PHP version is 7.3 or above and PHPUnit is less than version 7 + // If the PHP version is 7.4 or above and PHPUnit is less than version 9 // call the drupal-phpunit-upgrade script to upgrade PHPUnit. if (!static::upgradePHPUnitCheck($phpunit_package->getVersion())) { $event->getComposer() @@ -332,7 +332,7 @@ public static function upgradePHPUnit(Event $event) { * TRUE if the PHPUnit needs to be upgraded, FALSE if not. */ public static function upgradePHPUnitCheck($phpunit_version) { - return !(version_compare(PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION, '7.3') >= 0 && version_compare($phpunit_version, '7.0') < 0); + return !(version_compare(PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION, '7.4') >= 0 && version_compare($phpunit_version, '9.0') < 0); } } diff --git a/core/modules/hal/tests/src/Kernel/EntityTranslationNormalizeTest.php b/core/modules/hal/tests/src/Kernel/EntityTranslationNormalizeTest.php index bd31f529cc47e3ee4f29f4538a67c5a77227dc57..af1f10a22caa67eb0de36c8111a5ba58bc1de9a0 100644 --- a/core/modules/hal/tests/src/Kernel/EntityTranslationNormalizeTest.php +++ b/core/modules/hal/tests/src/Kernel/EntityTranslationNormalizeTest.php @@ -70,8 +70,8 @@ public function testNodeTranslation() { $normalized = $this->serializer->normalize($node, $this->format); - $this->assertContains(['lang' => 'en', 'value' => $node->getTitle()], $normalized['title'], 'Original language title has been normalized.'); - $this->assertContains(['lang' => 'de', 'value' => $translation->getTitle()], $normalized['title'], 'Translation language title has been normalized.'); + $this->assertContainsEquals(['lang' => 'en', 'value' => $node->getTitle()], $normalized['title'], 'Original language title has been normalized.'); + $this->assertContainsEquals(['lang' => 'de', 'value' => $translation->getTitle()], $normalized['title'], 'Translation language title has been normalized.'); /** @var \Drupal\node\NodeInterface $denormalized_node */ $denormalized_node = $this->serializer->denormalize($normalized, 'Drupal\node\Entity\Node', $this->format); diff --git a/core/modules/migrate/tests/src/Unit/MigrateStubTest.php b/core/modules/migrate/tests/src/Unit/MigrateStubTest.php index fcf171b17c424017eb50de8ac14205240985c0f7..4a68dfdffc69501f471e4e1d81fc49b92e3c6098 100644 --- a/core/modules/migrate/tests/src/Unit/MigrateStubTest.php +++ b/core/modules/migrate/tests/src/Unit/MigrateStubTest.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\migrate\Unit; use Drupal\Component\Plugin\Exception\PluginNotFoundException; +use Drupal\Tests\UnitTestCase; use Drupal\migrate\MigrateStub; use Drupal\migrate\Plugin\MigrateDestinationInterface; use Drupal\migrate\Plugin\MigrateIdMapInterface; @@ -10,7 +11,6 @@ use Drupal\migrate\Plugin\MigrationInterface; use Drupal\migrate\Plugin\MigrationPluginManagerInterface; use Drupal\migrate\Row; -use PHPUnit\Framework\TestCase; use Prophecy\Argument; /** @@ -20,7 +20,7 @@ * * @coversDefaultClass \Drupal\migrate\MigrateStub */ -class MigrateStubTest extends TestCase { +class MigrateStubTest extends UnitTestCase { /** * The plugin manager prophecy. diff --git a/core/modules/system/tests/src/Kernel/Entity/EntityReferenceSelectionReferenceableTest.php b/core/modules/system/tests/src/Kernel/Entity/EntityReferenceSelectionReferenceableTest.php index 16b98105353a87409ab3fb9a11c817f2d31639a4..a4bea10bdfe75da6420a8bae6397bf2160def87b 100644 --- a/core/modules/system/tests/src/Kernel/Entity/EntityReferenceSelectionReferenceableTest.php +++ b/core/modules/system/tests/src/Kernel/Entity/EntityReferenceSelectionReferenceableTest.php @@ -126,7 +126,7 @@ public function testReferenceablesWithNoLabelKey($match, $match_operator, $limit // entity labels. // @see \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface::getReferenceableEntities() $item = is_string($item) ? Html::escape($item) : $item; - $this->assertContains($item, $referenceables[$this->bundle]); + $this->assertContainsEquals($item, $referenceables[$this->bundle]); } // Test ::countReferenceableEntities(). diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index 955eb5bf55b0a75549f188795c92a42c14104f29..91b47782610a260ce11ee078676d8242d4cf588a 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -149,7 +149,7 @@ } if (!Composer::upgradePHPUnitCheck(Version::id())) { - simpletest_script_print_error("PHPUnit testing framework version 7 or greater is required when running on PHP 7.3 or greater. Run the command 'composer run-script drupal-phpunit-upgrade' in order to fix this."); + simpletest_script_print_error("PHPUnit testing framework version 9 or greater is required when running on PHP 7.4 or greater. Run the command 'composer run-script drupal-phpunit-upgrade' in order to fix this."); exit(SIMPLETEST_SCRIPT_EXIT_FAILURE); } diff --git a/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php b/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php index 7bd4f7034714b4f85a2e8ca79011f0f7fcf5cec2..898aa582beb75376a5634019bf05f5a548c6c0c1 100644 --- a/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php +++ b/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php @@ -7,6 +7,7 @@ use Behat\Mink\Mink; use Behat\Mink\Session; use Drupal\Component\FileSystem\FileSystem as DrupalFilesystem; +use Drupal\Tests\PhpUnitCompatibilityTrait; use Drupal\Tests\Traits\PhpUnitWarnings; use PHPUnit\Framework\TestCase; use Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem; @@ -53,6 +54,7 @@ abstract class BuildTestBase extends TestCase { use ExternalCommandRequirementsTrait; use PhpUnitWarnings; + use PhpUnitCompatibilityTrait; /** * The working directory where this test will manipulate files. diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php index 1e6c1b3ead32722e327de55a32e4c6064f45a890..e5925e81004622f191ee7f03e1e943c27b901425 100644 --- a/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php +++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php @@ -612,7 +612,7 @@ public function testUnmetDependency() { 'Configuration <em class="placeholder">unknown.config</em> depends on the <em class="placeholder">unknown</em> extension that will not be installed after import.', ]; foreach ($expected as $expected_message) { - $this->assertContains($expected_message, $error_log, $expected_message); + $this->assertContainsEquals($expected_message, $error_log, $expected_message); } } @@ -658,7 +658,7 @@ public function testUnmetDependency() { 'Configuration <em class="placeholder">config_test.dynamic.dotted.theme</em> depends on themes (<em class="placeholder">unknown, Seven</em>) that will not be installed after import.', ]; foreach ($expected as $expected_message) { - $this->assertContains($expected_message, $error_log, $expected_message); + $this->assertContainsEquals($expected_message, $error_log, $expected_message); } } } diff --git a/core/tests/Drupal/KernelTests/Core/File/NameMungingTest.php b/core/tests/Drupal/KernelTests/Core/File/NameMungingTest.php index 1e97b7a805a070f8884bac3b7c3ccfe0dcaef02b..991f9263c9bde6481f8b964895be453af7438599 100644 --- a/core/tests/Drupal/KernelTests/Core/File/NameMungingTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/NameMungingTest.php @@ -42,7 +42,7 @@ public function testMunging() { $munged_name = file_munge_filename($this->name, '', TRUE); $messages = \Drupal::messenger()->all(); \Drupal::messenger()->deleteAll(); - $this->assertContains(strtr('For security reasons, your upload has been renamed to <em class="placeholder">%filename</em>.', ['%filename' => $munged_name]), $messages['status'], 'Alert properly set when a file is renamed.'); + $this->assertContainsEquals(strtr('For security reasons, your upload has been renamed to <em class="placeholder">%filename</em>.', ['%filename' => $munged_name]), $messages['status'], 'Alert properly set when a file is renamed.'); $this->assertNotEqual($munged_name, $this->name, new FormattableMarkup('The new filename (%munged) has been modified from the original (%original)', ['%munged' => $munged_name, '%original' => $this->name])); } diff --git a/core/tests/Drupal/KernelTests/Core/Messenger/MessengerTest.php b/core/tests/Drupal/KernelTests/Core/Messenger/MessengerTest.php index ac305022ff300d9dfb6c836f3de800b1c4d40413..e244e05e044c064a550e106e999c3106b4979a6b 100644 --- a/core/tests/Drupal/KernelTests/Core/Messenger/MessengerTest.php +++ b/core/tests/Drupal/KernelTests/Core/Messenger/MessengerTest.php @@ -49,7 +49,7 @@ public function testRemoveSingleMessage() { // Check we only have the second one. $this->assertCount(1, $this->messenger->messagesByType(MessengerInterface::TYPE_STATUS)); - $this->assertContains('Second message with <em>markup!</em> (not removed).', $this->messenger->deleteByType(MessengerInterface::TYPE_STATUS)); + $this->assertContainsEquals('Second message with <em>markup!</em> (not removed).', $this->messenger->deleteByType(MessengerInterface::TYPE_STATUS)); } diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php index 88c956b661b3142a5051700bab3d8f0c4fe2ec10..86644ee69e359809e3802c36ec5ed3b3c612cc8e 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -18,6 +18,7 @@ use Drupal\Core\Test\TestDatabase; use Drupal\Tests\ConfigTestTrait; use Drupal\Tests\RandomGeneratorTrait; +use Drupal\Tests\PhpUnitCompatibilityTrait; use Drupal\Tests\TestRequirementsTrait; use Drupal\Tests\Traits\PhpUnitWarnings; use Drupal\TestTools\Comparator\MarkupInterfaceComparator; @@ -79,6 +80,7 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa use ConfigTestTrait; use TestRequirementsTrait; use PhpUnitWarnings; + use PhpUnitCompatibilityTrait; /** * {@inheritdoc} diff --git a/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit8/TestCompatibilityTrait.php b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit8/TestCompatibilityTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..9beee7d0a1988188d49e5e36ab6cfba2d6478fbc --- /dev/null +++ b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit8/TestCompatibilityTrait.php @@ -0,0 +1,10 @@ +<?php + +namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit8; + +/** + * Drupal's forward compatibility layer with multiple versions of PHPUnit. + */ +trait TestCompatibilityTrait { + +} diff --git a/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit9/TestCompatibilityTrait.php b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit9/TestCompatibilityTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..29be2acbec8bc75032c2125eab1c9e882fe69e81 --- /dev/null +++ b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit9/TestCompatibilityTrait.php @@ -0,0 +1,14 @@ +<?php + +namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit9; + +use Prophecy\PhpUnit\ProphecyTrait; + +/** + * Drupal's forward compatibility layer with multiple versions of PHPUnit. + */ +trait TestCompatibilityTrait { + + use ProphecyTrait; + +} diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php index 448bb6a22b60b0d565556c141731ffae92a408a7..73aeb23d3f1142ee00bda6b187fd5aefd8d79c3f 100644 --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -65,6 +65,7 @@ abstract class BrowserTestBase extends TestCase { } use XdebugRequestTrait; use PhpUnitWarnings; + use PhpUnitCompatibilityTrait; /** * The database prefix of this test run. diff --git a/core/tests/Drupal/Tests/Component/Annotation/Plugin/Discovery/AnnotationBridgeDecoratorTest.php b/core/tests/Drupal/Tests/Component/Annotation/Plugin/Discovery/AnnotationBridgeDecoratorTest.php index 12732e110ace4d4b778f6ea6b80c465c279ce4d8..324eab95b4bd131dbb5f22ad7902b2eef321bfff 100644 --- a/core/tests/Drupal/Tests/Component/Annotation/Plugin/Discovery/AnnotationBridgeDecoratorTest.php +++ b/core/tests/Drupal/Tests/Component/Annotation/Plugin/Discovery/AnnotationBridgeDecoratorTest.php @@ -6,6 +6,7 @@ use Drupal\Component\Annotation\Plugin\Discovery\AnnotationBridgeDecorator; use Drupal\Component\Plugin\Definition\PluginDefinition; use Drupal\Component\Plugin\Discovery\DiscoveryInterface; +use Drupal\Tests\PhpUnitCompatibilityTrait; use PHPUnit\Framework\TestCase; /** @@ -14,6 +15,8 @@ */ class AnnotationBridgeDecoratorTest extends TestCase { + use PhpUnitCompatibilityTrait; + /** * @covers ::getDefinitions */ diff --git a/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php b/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php index f348b0705b600a0115330f9d841bc9de7fc9bfc1..481827488467f05ad2d074c3ab6bdc09cf430198 100644 --- a/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php +++ b/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php @@ -8,6 +8,7 @@ namespace Drupal\Tests\Component\DependencyInjection; use Drupal\Component\Utility\Crypt; +use Drupal\Tests\PhpUnitCompatibilityTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; @@ -24,6 +25,8 @@ */ class ContainerTest extends TestCase { + use PhpUnitCompatibilityTrait; + /** * The tested container. * diff --git a/core/tests/Drupal/Tests/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php b/core/tests/Drupal/Tests/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php index 92ee5490acbeb43b3f1df90b65465a608f98c0ae..5785aed465bb8467ec6455d1d8f15486c93f1ab2 100644 --- a/core/tests/Drupal/Tests/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php +++ b/core/tests/Drupal/Tests/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php @@ -8,6 +8,7 @@ namespace Drupal\Tests\Component\DependencyInjection\Dumper { use Drupal\Component\Utility\Crypt; + use Drupal\Tests\PhpUnitCompatibilityTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; @@ -24,6 +25,8 @@ */ class OptimizedPhpArrayDumperTest extends TestCase { + use PhpUnitCompatibilityTrait; + /** * The container builder instance. * diff --git a/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php b/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php index be2054811ea93b3d25e0b0c8c71333c6c8c4b582..76f0064e7d96ab22a07730904913274c79c99fb5 100644 --- a/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php +++ b/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php @@ -4,7 +4,6 @@ use Drupal\Component\Diff\Engine\DiffOp; use PHPUnit\Framework\TestCase; -use PHPUnit\Framework\Error\Error; /** * Test DiffOp base class. @@ -25,7 +24,7 @@ class DiffOpTest extends TestCase { * @covers ::reverse */ public function testReverse() { - $this->expectException(Error::class); + $this->expectError(); $op = new DiffOp(); $result = $op->reverse(); } diff --git a/core/tests/Drupal/Tests/Component/Gettext/PoStreamWriterTest.php b/core/tests/Drupal/Tests/Component/Gettext/PoStreamWriterTest.php index 39cf95d18aa24ab44a79d37c3d58f4265b643e08..47644dd2300b7746878f5d99c6296ae143facdd7 100644 --- a/core/tests/Drupal/Tests/Component/Gettext/PoStreamWriterTest.php +++ b/core/tests/Drupal/Tests/Component/Gettext/PoStreamWriterTest.php @@ -4,6 +4,7 @@ use Drupal\Component\Gettext\PoItem; use Drupal\Component\Gettext\PoStreamWriter; +use Drupal\Tests\PhpUnitCompatibilityTrait; use org\bovigo\vfs\vfsStream; use org\bovigo\vfs\vfsStreamFile; use PHPUnit\Framework\TestCase; @@ -14,6 +15,8 @@ */ class PoStreamWriterTest extends TestCase { + use PhpUnitCompatibilityTrait; + /** * The PO writer object under test. * diff --git a/core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php b/core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php index 6230bdbd7ba6a7ca3b9b9ac2acfcfcf890ca0e6a..c17b1bb516d0387034017aa05b8ea2c403f4a356 100644 --- a/core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php +++ b/core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php @@ -4,8 +4,8 @@ use Drupal\Component\PhpStorage\FileStorage; use Drupal\Component\Utility\Random; +use Drupal\Tests\Traits\PhpUnitWarnings; use org\bovigo\vfs\vfsStreamDirectory; -use PHPUnit\Framework\Error\Warning; /** * @coversDefaultClass \Drupal\Component\PhpStorage\FileStorage @@ -14,6 +14,8 @@ */ class FileStorageTest extends PhpStorageTestBase { + use PhpUnitWarnings; + /** * Standard test settings to pass to storage instances. * @@ -99,8 +101,8 @@ public function testCreateDirectoryFailWarning() { 'bin' => 'test', ]); $code = "<?php\n echo 'here';"; - $this->expectException(Warning::class); - $this->expectExceptionMessage('mkdir(): Permission Denied'); + $this->expectWarning(); + $this->expectWarningMessage('mkdir(): Permission Denied'); $storage->save('subdirectory/foo.php', $code); } diff --git a/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php b/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php index 954ff70110c902d7aab4f0406f996a596c727f32..e8192fcac5a5b9683f8772d3d128bef6efc66355 100644 --- a/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php +++ b/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php @@ -5,6 +5,7 @@ use Drupal\Component\Plugin\Exception\PluginNotFoundException; use Drupal\Component\Plugin\Mapper\MapperInterface; use Drupal\Component\Plugin\PluginManagerBase; +use Drupal\Tests\PhpUnitCompatibilityTrait; use PHPUnit\Framework\TestCase; /** @@ -13,6 +14,8 @@ */ class PluginManagerBaseTest extends TestCase { + use PhpUnitCompatibilityTrait; + /** * A callback method for mocking FactoryInterface objects. */ diff --git a/core/tests/Drupal/Tests/Composer/Plugin/VendorHardening/ConfigTest.php b/core/tests/Drupal/Tests/Composer/Plugin/VendorHardening/ConfigTest.php index 9755278b512ccfc89798b121e0dd79d6f6506a58..f800cdd5262a61fee635249335a98e194a9f1635 100644 --- a/core/tests/Drupal/Tests/Composer/Plugin/VendorHardening/ConfigTest.php +++ b/core/tests/Drupal/Tests/Composer/Plugin/VendorHardening/ConfigTest.php @@ -4,6 +4,7 @@ use Composer\Package\RootPackageInterface; use Drupal\Composer\Plugin\VendorHardening\Config; +use Drupal\Tests\Traits\PhpUnitWarnings; use PHPUnit\Framework\TestCase; /** @@ -12,6 +13,8 @@ */ class ConfigTest extends TestCase { + use PhpUnitWarnings; + /** * @covers ::getPathsForPackage */ diff --git a/core/tests/Drupal/Tests/Composer/Plugin/VendorHardening/VendorHardeningPluginTest.php b/core/tests/Drupal/Tests/Composer/Plugin/VendorHardening/VendorHardeningPluginTest.php index 845356f887e9247bad2d257fa40930d934135b4d..3e130ba389bd26e3d8836675b0541494b031f726 100644 --- a/core/tests/Drupal/Tests/Composer/Plugin/VendorHardening/VendorHardeningPluginTest.php +++ b/core/tests/Drupal/Tests/Composer/Plugin/VendorHardening/VendorHardeningPluginTest.php @@ -8,6 +8,8 @@ use Composer\Package\RootPackageInterface; use Drupal\Composer\Plugin\VendorHardening\Config; use Drupal\Composer\Plugin\VendorHardening\VendorHardeningPlugin; +use Drupal\Tests\PhpUnitCompatibilityTrait; +use Drupal\Tests\Traits\PhpUnitWarnings; use org\bovigo\vfs\vfsStream; use PHPUnit\Framework\TestCase; @@ -17,6 +19,9 @@ */ class VendorHardeningPluginTest extends TestCase { + use PhpUnitWarnings; + use PhpUnitCompatibilityTrait; + public function setUp(): void { parent::setUp(); vfsStream::setup('vendor', NULL, [ diff --git a/core/tests/Drupal/Tests/ComposerIntegrationTest.php b/core/tests/Drupal/Tests/ComposerIntegrationTest.php index 5cd2719bebf4ff2028c29d6bae00db43f99ebc2b..d74cf4202782b26dd66527816dc86317be87a61b 100644 --- a/core/tests/Drupal/Tests/ComposerIntegrationTest.php +++ b/core/tests/Drupal/Tests/ComposerIntegrationTest.php @@ -5,6 +5,7 @@ use Drupal\Composer\Plugin\VendorHardening\Config; use Drupal\Core\Composer\Composer; use Drupal\Tests\Composer\ComposerIntegrationTrait; +use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion; use Symfony\Component\Yaml\Yaml; /** @@ -260,6 +261,11 @@ public function testVendorCleanup($class, $property) { $reflection = new \ReflectionProperty($class, $property); $reflection->setAccessible(TRUE); $config = $reflection->getValue(); + // PHPUnit 9.5.3 removes 'phpunit/php-token-stream' from its dependencies. + // @todo remove the check below when PHPUnit 9 is the minimum. + if (RunnerVersion::getMajor() >= 9) { + unset($config['phpunit/php-token-stream']); + } foreach (array_keys($config) as $package) { $this->assertContains(strtolower($package), $packages); } diff --git a/core/tests/Drupal/Tests/Core/Asset/CssCollectionGrouperUnitTest.php b/core/tests/Drupal/Tests/Core/Asset/CssCollectionGrouperUnitTest.php index 7e5fe84836be9aa2c9a4099a328c6faa9262d788..40efadf4ea4367e10de5994f598bbcc94929be60 100644 --- a/core/tests/Drupal/Tests/Core/Asset/CssCollectionGrouperUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Asset/CssCollectionGrouperUnitTest.php @@ -113,8 +113,8 @@ public function testGrouper() { $this->assertSame('all', $group['media']); $this->assertTrue($group['preprocess']); $this->assertCount(3, $group['items']); - $this->assertContains($css_assets['system.base.css'], $group['items']); - $this->assertContains($css_assets['js.module.css'], $group['items']); + $this->assertContainsEquals($css_assets['system.base.css'], $group['items']); + $this->assertContainsEquals($css_assets['js.module.css'], $group['items']); // Check group 2. $group = $groups[1]; @@ -123,7 +123,7 @@ public function testGrouper() { $this->assertSame('all', $group['media']); $this->assertTrue($group['preprocess']); $this->assertCount(1, $group['items']); - $this->assertContains($css_assets['field.css'], $group['items']); + $this->assertContainsEquals($css_assets['field.css'], $group['items']); // Check group 3. $group = $groups[2]; @@ -132,7 +132,7 @@ public function testGrouper() { $this->assertSame('all', $group['media']); $this->assertTrue($group['preprocess']); $this->assertCount(1, $group['items']); - $this->assertContains($css_assets['external.css'], $group['items']); + $this->assertContainsEquals($css_assets['external.css'], $group['items']); // Check group 4. $group = $groups[3]; @@ -141,7 +141,7 @@ public function testGrouper() { $this->assertSame('all', $group['media']); $this->assertTrue($group['preprocess']); $this->assertCount(1, $group['items']); - $this->assertContains($css_assets['elements.css'], $group['items']); + $this->assertContainsEquals($css_assets['elements.css'], $group['items']); // Check group 5. $group = $groups[4]; @@ -150,7 +150,7 @@ public function testGrouper() { $this->assertSame('print', $group['media']); $this->assertTrue($group['preprocess']); $this->assertCount(1, $group['items']); - $this->assertContains($css_assets['print.css'], $group['items']); + $this->assertContainsEquals($css_assets['print.css'], $group['items']); } } diff --git a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php index 3c2bb0bbae6e3f9629a5e9c8c286bc64f1c824d1..6ef3a4fd8f13ed3bebb26b4290c9f22ac280cb43 100644 --- a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php +++ b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php @@ -132,6 +132,17 @@ public static function getSkippedDeprecations() { 'AssertLegacyTrait::assertFieldByXPath() is deprecated in drupal:8.3.0 and is removed from drupal:10.0.0. Use $this->xpath() instead and check the values directly in the test. See https://www.drupal.org/node/3129738', 'AssertLegacyTrait::assertNoFieldByXPath() is deprecated in drupal:8.3.0 and is removed from drupal:10.0.0. Use $this->xpath() instead and assert that the result is empty. See https://www.drupal.org/node/3129738', 'AssertLegacyTrait::assertFieldsByValue() is deprecated in drupal:8.3.0 and is removed from drupal:10.0.0. Use iteration over the fields yourself instead and directly check the values in the test. See https://www.drupal.org/node/3129738', + // PHPUnit 9. + "The \"PHPUnit\TextUI\DefaultResultPrinter\" class is considered internal This class is not covered by the backward compatibility promise for PHPUnit. It may change without further notice. You should not use it from \"Drupal\Tests\Listeners\HtmlOutputPrinter\".", + 'assertFileNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileDoesNotExist() instead.', + 'assertRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertMatchesRegularExpression() instead.', + 'assertNotRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDoesNotMatchRegularExpression() instead.', + 'assertDirectoryNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryDoesNotExist() instead.', + 'Support for using expectException() with PHPUnit\\Framework\\Error\\Warning is deprecated and will be removed in PHPUnit 10. Use expectWarning() instead.', + 'Support for using expectException() with PHPUnit\\Framework\\Error\\Error is deprecated and will be removed in PHPUnit 10. Use expectError() instead.', + 'assertDirectoryNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotWritable() instead.', + 'assertFileNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotWritable() instead.', + 'The at() matcher has been deprecated. It will be removed in PHPUnit 10. Please refactor your test to not rely on the order in which methods are invoked.', ]; } diff --git a/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php b/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php index a3f7916e98677a90d7cf90e6d57d71209ddf72b1..a85c320499724ee13be17abecfa9fdc780bc05a3 100644 --- a/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php +++ b/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php @@ -2,15 +2,27 @@ namespace Drupal\Tests\Listeners; +use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion; use PHPUnit\Framework\TestResult; -use PHPUnit\TextUI\ResultPrinter; + +// In order to manage different implementations across PHPUnit versions, we +// dynamically load the base ResultPrinter class dependent on the PHPUnit runner +// version. +if (!class_exists(ResultPrinterBase::class, FALSE)) { + if (RunnerVersion::getMajor() < 9) { + class_alias('PHPUnit\TextUI\ResultPrinter', ResultPrinterBase::class); + } + else { + class_alias('PHPUnit\TextUI\DefaultResultPrinter', ResultPrinterBase::class); + } +} /** * Defines a class for providing html output results for functional tests. * * @internal */ -class HtmlOutputPrinter extends ResultPrinter { +class HtmlOutputPrinter extends ResultPrinterBase { use HtmlOutputPrinterTrait; diff --git a/core/tests/Drupal/Tests/PhpUnitCompatibilityTrait.php b/core/tests/Drupal/Tests/PhpUnitCompatibilityTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..dc6aed489bfaf6f04c6bc87eaeb3d02c0f3e0706 --- /dev/null +++ b/core/tests/Drupal/Tests/PhpUnitCompatibilityTrait.php @@ -0,0 +1,21 @@ +<?php + +namespace Drupal\Tests; + +use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion; + +// In order to manage different method signatures between PHPUnit versions, we +// dynamically load a compatibility trait dependent on the PHPUnit runner +// version. +if (!trait_exists(PhpunitVersionDependentTestCompatibilityTrait::class, FALSE)) { + class_alias("Drupal\TestTools\PhpUnitCompatibility\PhpUnit" . RunnerVersion::getMajor() . "\TestCompatibilityTrait", PhpUnitVersionDependentTestCompatibilityTrait::class); +} + +/** + * Makes Drupal's test API forward compatible with multiple versions of PHPUnit. + */ +trait PhpUnitCompatibilityTrait { + + use PhpUnitVersionDependentTestCompatibilityTrait; + +} diff --git a/core/tests/Drupal/Tests/PhpUnitWarningsTest.php b/core/tests/Drupal/Tests/PhpUnitWarningsTest.php index 6a741265e3439d802c81b7b20e69ea7617039098..45d298ca36f02d8dfe7620a2e93b86cde2b9efd4 100644 --- a/core/tests/Drupal/Tests/PhpUnitWarningsTest.php +++ b/core/tests/Drupal/Tests/PhpUnitWarningsTest.php @@ -2,12 +2,17 @@ namespace Drupal\Tests; +use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; + /** * @coversDefaultClass \Drupal\Tests\Traits\PhpUnitWarnings * @group legacy */ class PhpUnitWarningsTest extends UnitTestCase { + use ExpectDeprecationTrait; + /** * @expectedDeprecation Test warning for \Drupal\Tests\PhpUnitWarningsTest::testAddWarning() */ @@ -16,46 +21,66 @@ public function testAddWarning() { } /** - * @expectedDeprecation Using assertContains() with string haystacks is deprecated and will not be supported in PHPUnit 9. Refactor your test to use assertStringContainsString() or assertStringContainsStringIgnoringCase() instead. - * @expectedDeprecation The optional $ignoreCase parameter of assertContains() is deprecated and will be removed in PHPUnit 9. + * Tests assertContains. */ public function testAssertContains() { + if (RunnerVersion::getMajor() > 8) { + $this->markTestSkipped("In PHPUnit 9+, argument 2 passed to PHPUnit\Framework\Assert::assertContains() must be iterable."); + } + $this->expectDeprecation('Using assertContains() with string haystacks is deprecated and will not be supported in PHPUnit 9. Refactor your test to use assertStringContainsString() or assertStringContainsStringIgnoringCase() instead.'); + $this->expectDeprecation('The optional $ignoreCase parameter of assertContains() is deprecated and will be removed in PHPUnit 9.'); $this->assertContains('string', 'aaaa_string_aaa'); $this->assertContains('STRING', 'aaaa_string_aaa', '', TRUE); } /** - * @expectedDeprecation Using assertNotContains() with string haystacks is deprecated and will not be supported in PHPUnit 9. Refactor your test to use assertStringNotContainsString() or assertStringNotContainsStringIgnoringCase() instead. - * @expectedDeprecation The optional $ignoreCase parameter of assertNotContains() is deprecated and will be removed in PHPUnit 9. + * Tests assertNotContains. */ public function testAssertNotContains() { + if (RunnerVersion::getMajor() > 8) { + $this->markTestSkipped("In PHPUnit 9+, argument 2 passed to PHPUnit\Framework\Assert::assertNotContains() must be iterable."); + } + $this->expectDeprecation('Using assertNotContains() with string haystacks is deprecated and will not be supported in PHPUnit 9. Refactor your test to use assertStringNotContainsString() or assertStringNotContainsStringIgnoringCase() instead.'); + $this->expectDeprecation('The optional $ignoreCase parameter of assertNotContains() is deprecated and will be removed in PHPUnit 9.'); $this->assertNotContains('foo', 'bar'); $this->assertNotContains('FOO', 'bar', '', TRUE); } /** - * @expectedDeprecation assertArraySubset() is deprecated and will be removed in PHPUnit 9. + * Tests assertArraySubset. */ public function testAssertArraySubset() { + if (RunnerVersion::getMajor() > 8) { + $this->markTestSkipped("In PHPUnit 9+, assertArraySubset() is removed."); + } + $this->expectDeprecation('assertArraySubset() is deprecated and will be removed in PHPUnit 9.'); $this->assertArraySubset(['a'], ['a', 'b']); } /** - * @expectedDeprecation assertInternalType() is deprecated and will be removed in PHPUnit 9. Refactor your test to use assertIsArray(), assertIsBool(), assertIsFloat(), assertIsInt(), assertIsNumeric(), assertIsObject(), assertIsResource(), assertIsString(), assertIsScalar(), assertIsCallable(), or assertIsIterable() instead. + * Tests assertInternalType. */ public function testAssertInternalType() { + if (RunnerVersion::getMajor() > 8) { + $this->markTestSkipped("In PHPUnit 9+, assertInternalType() is removed."); + } + $this->expectDeprecation('assertInternalType() is deprecated and will be removed in PHPUnit 9. Refactor your test to use assertIsArray(), assertIsBool(), assertIsFloat(), assertIsInt(), assertIsNumeric(), assertIsObject(), assertIsResource(), assertIsString(), assertIsScalar(), assertIsCallable(), or assertIsIterable() instead.'); $this->assertInternalType('string', 'string'); } /** - * @expectedDeprecation assertAttributeEquals() is deprecated and will be removed in PHPUnit 9. - * @expectedDeprecation readAttribute() is deprecated and will be removed in PHPUnit 9. - * @expectedDeprecation getObjectAttribute() is deprecated and will be removed in PHPUnit 9. - * @expectedDeprecation assertAttributeSame() is deprecated and will be removed in PHPUnit 9. - * @expectedDeprecation assertAttributeInstanceOf() is deprecated and will be removed in PHPUnit 9. - * @expectedDeprecation assertAttributeEmpty() is deprecated and will be removed in PHPUnit 9. + * Tests assertion methods accessing class attributes. */ public function testAssertAttribute() { + if (RunnerVersion::getMajor() > 8) { + $this->markTestSkipped("In PHPUnit 9+, assertion methods accessing class attributes are removed."); + } + $this->expectDeprecation('assertAttributeEquals() is deprecated and will be removed in PHPUnit 9.'); + $this->expectDeprecation('readAttribute() is deprecated and will be removed in PHPUnit 9.'); + $this->expectDeprecation('getObjectAttribute() is deprecated and will be removed in PHPUnit 9.'); + $this->expectDeprecation('assertAttributeSame() is deprecated and will be removed in PHPUnit 9.'); + $this->expectDeprecation('assertAttributeInstanceOf() is deprecated and will be removed in PHPUnit 9.'); + $this->expectDeprecation('assertAttributeEmpty() is deprecated and will be removed in PHPUnit 9.'); $obj = new class() { protected $attribute = 'value'; protected $class; @@ -73,16 +98,24 @@ public function __construct() { } /** - * @expectedDeprecation The optional $canonicalize parameter of assertEquals() is deprecated and will be removed in PHPUnit 9. Refactor your test to use assertEqualsCanonicalizing() instead. + * Tests assertEquals. */ public function testAssertEquals() { + if (RunnerVersion::getMajor() > 8) { + $this->markTestSkipped("In PHPUnit 9+, the \$canonicalize parameter of assertEquals() is removed."); + } + $this->expectDeprecation('The optional $canonicalize parameter of assertEquals() is deprecated and will be removed in PHPUnit 9. Refactor your test to use assertEqualsCanonicalizing() instead.'); $this->assertEquals(['a', 'b'], ['b', 'a'], '', 0.0, 10, TRUE); } /** - * @expectedDeprecation expectExceptionMessageRegExp() is deprecated in PHPUnit 8 and will be removed in PHPUnit 9. + * Tests expectExceptionMessageRegExp. */ public function testExpectExceptionMessageRegExp() { + if (RunnerVersion::getMajor() > 8) { + $this->markTestSkipped("In PHPUnit 9+, expectExceptionMessageRegExp() is removed."); + } + $this->expectDeprecation('expectExceptionMessageRegExp() is deprecated in PHPUnit 8 and will be removed in PHPUnit 9.'); $this->expectException(\Exception::class); $this->expectExceptionMessageRegExp('/An exception .*/'); throw new \Exception('An exception has been triggered'); diff --git a/core/tests/Drupal/Tests/Traits/PhpUnitWarnings.php b/core/tests/Drupal/Tests/Traits/PhpUnitWarnings.php index d2e3039d208ea9b8b8995358df241f49675f1a02..9e16ae95279612529ee6940410ef60a5ea4c5ec4 100644 --- a/core/tests/Drupal/Tests/Traits/PhpUnitWarnings.php +++ b/core/tests/Drupal/Tests/Traits/PhpUnitWarnings.php @@ -37,6 +37,16 @@ trait PhpUnitWarnings { 'expectExceptionMessageRegExp() is deprecated in PHPUnit 8 and will be removed in PHPUnit 9.', // Warning for testing. 'Test warning for \Drupal\Tests\PhpUnitWarningsTest::testAddWarning()', + // PHPUnit 9. + 'assertFileNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileDoesNotExist() instead.', + 'assertRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertMatchesRegularExpression() instead.', + 'assertNotRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDoesNotMatchRegularExpression() instead.', + 'assertDirectoryNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryDoesNotExist() instead.', + 'Support for using expectException() with PHPUnit\\Framework\\Error\\Warning is deprecated and will be removed in PHPUnit 10. Use expectWarning() instead.', + 'Support for using expectException() with PHPUnit\\Framework\\Error\\Error is deprecated and will be removed in PHPUnit 10. Use expectError() instead.', + 'assertDirectoryNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotWritable() instead.', + 'assertFileNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotWritable() instead.', + 'The at() matcher has been deprecated. It will be removed in PHPUnit 10. Please refactor your test to not rely on the order in which methods are invoked.', ]; /** diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php index 3a4e035ce06082031a41b5c8ae382da12c9241cc..20dcb1d07a32358083923203c0826bd9589810a3 100644 --- a/core/tests/Drupal/Tests/UnitTestCase.php +++ b/core/tests/Drupal/Tests/UnitTestCase.php @@ -20,6 +20,7 @@ abstract class UnitTestCase extends TestCase { use PhpUnitWarnings; + use PhpUnitCompatibilityTrait; /** * The random generator.