diff --git a/composer.json b/composer.json index 71dcc9605c..24e405d9bd 100644 --- a/composer.json +++ b/composer.json @@ -50,10 +50,12 @@ "scripts": { "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump", "post-autoload-dump": [ - "Drupal\\Core\\Composer\\Composer::ensureHtaccess" + "Drupal\\Core\\Composer\\Composer::ensureHtaccess", + "Drupal\\Core\\Composer\\Composer::upgradePHPUnit" ], "post-package-install": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup", "post-package-update": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup", + "drupal-phpunit-upgrade": "@composer upgrade phpunit/phpunit --with-dependencies", "phpcs": "phpcs --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --", "phpcbf": "phpcbf --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --" }, diff --git a/core/composer.json b/core/composer.json index 31bc51a0fa..c4bb384b92 100644 --- a/core/composer.json +++ b/core/composer.json @@ -44,7 +44,7 @@ "jcalderonzumba/gastonjs": "^1.0.2", "jcalderonzumba/mink-phantomjs-driver": "^0.3.1", "mikey179/vfsStream": "^1.2", - "phpunit/phpunit": ">=4.8.35 <5", + "phpunit/phpunit": "^4.8.35 || ^6.1", "phpspec/prophecy": "^1.4", "symfony/css-selector": "~3.2.8", "symfony/phpunit-bridge": "^3.4.0@beta" diff --git a/core/lib/Drupal/Core/Composer/Composer.php b/core/lib/Drupal/Core/Composer/Composer.php index 016f93a348..8bfc7bb8c2 100644 --- a/core/lib/Drupal/Core/Composer/Composer.php +++ b/core/lib/Drupal/Core/Composer/Composer.php @@ -6,6 +6,7 @@ use Composer\Script\Event; use Composer\Installer\PackageEvent; use Composer\Semver\Constraint\Constraint; +use PHPUnit\Runner\Version; /** * Provides static functions for composer script events. @@ -143,6 +144,24 @@ public static function ensureHtaccess(Event $event) { } } + /** + * Fires the drupal-phpunit-upgrade script event if necessary. + * + * @param \Composer\Script\Event $event + */ + public static function upgradePHPUnit(Event $event) { + if (class_exists('PHPUnit_Runner_Version')) { + $phpunit_version = \PHPUnit_Runner_Version::id(); + } + if (class_exists('\PHPUnit\Runner\Version')) { + $phpunit_version = Version::id(); + } + // @todo if we haven't determine version throw an error. + if (version_compare(PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION, '7.1') >= 0 && version_compare($phpunit_version, '6.0') < 0) { + $event->getComposer()->getEventDispatcher()->dispatchScript('drupal-phpunit-upgrade'); + } + } + /** * Remove possibly problematic test files from vendored projects. * diff --git a/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php b/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php index 1569411353..5d3a20b6a6 100644 --- a/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php +++ b/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php @@ -49,6 +49,7 @@ public function setUpDisplayVariant($configuration = [], $definition = []) { $container = new Container(); $cache_context_manager = $this->getMockBuilder('Drupal\Core\Cache\CacheContextsManager') ->disableOriginalConstructor() + ->setMethods(['assertValidTokens']) ->getMock(); $container->set('cache_contexts_manager', $cache_context_manager); $cache_context_manager->expects($this->any()) @@ -209,9 +210,6 @@ public function testBuild(array $blocks_config, $visible_block_count, array $exp $title_block_plugin = $this->getMock('Drupal\Core\Block\TitleBlockPluginInterface'); foreach ($blocks_config as $block_id => $block_config) { $block = $this->getMock('Drupal\block\BlockInterface'); - $block->expects($this->any()) - ->method('getContexts') - ->willReturn([]); $block->expects($this->atLeastOnce()) ->method('getPlugin') ->willReturn($block_config[1] ? $main_content_block_plugin : ($block_config[2] ? $messages_block_plugin : ($block_config[3] ? $title_block_plugin : $block_plugin))); diff --git a/core/modules/content_moderation/tests/src/Kernel/EntityStateChangeValidationTest.php b/core/modules/content_moderation/tests/src/Kernel/EntityStateChangeValidationTest.php index 2fefc0148c..d72000b868 100644 --- a/core/modules/content_moderation/tests/src/Kernel/EntityStateChangeValidationTest.php +++ b/core/modules/content_moderation/tests/src/Kernel/EntityStateChangeValidationTest.php @@ -217,7 +217,7 @@ public function testInvalidStateMultilingual() { /** * Tests that content without prior moderation information can be moderated. */ - public function testLegacyContent() { + public function testExistingContentWithNoModeration() { $node_type = NodeType::create([ 'type' => 'example', ]); @@ -251,7 +251,7 @@ public function testLegacyContent() { /** * Tests that content without prior moderation information can be translated. */ - public function testLegacyMultilingualContent() { + public function testExistingMultilingualContentWithNoModeration() { // Enable French. ConfigurableLanguage::createFromLangcode('fr')->save(); diff --git a/core/modules/migrate/tests/src/Unit/MigrateTestCase.php b/core/modules/migrate/tests/src/Unit/MigrateTestCase.php index 20d7662d29..558cecb94a 100644 --- a/core/modules/migrate/tests/src/Unit/MigrateTestCase.php +++ b/core/modules/migrate/tests/src/Unit/MigrateTestCase.php @@ -78,11 +78,6 @@ protected function getMigration() { $configuration = &$this->migrationConfiguration; - $migration->method('getHighWaterProperty') - ->willReturnCallback(function () use ($configuration) { - return isset($configuration['high_water_property']) ? $configuration['high_water_property'] : ''; - }); - $migration->method('set') ->willReturnCallback(function ($argument, $value) use (&$configuration) { $configuration[$argument] = $value; diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index 4b6f421e55..441b2398f4 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -18,7 +18,7 @@ use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait; use Drupal\Tests\EntityViewTrait; use Drupal\Tests\block\Traits\BlockCreationTrait as BaseBlockCreationTrait; -use Drupal\Tests\Listeners\DeprecationListener; +use Drupal\Tests\Listeners\DeprecationListenerTrait; use Drupal\Tests\node\Traits\ContentTypeCreationTrait; use Drupal\Tests\node\Traits\NodeCreationTrait; use Drupal\Tests\Traits\Core\CronRunTrait; @@ -698,7 +698,7 @@ protected function curlHeaderCallback($curlHandler, $header) { if ($parameters[1] === 'User deprecated function') { if (getenv('SYMFONY_DEPRECATIONS_HELPER') !== 'disabled') { $message = (string) $parameters[0]; - if (!in_array($message, DeprecationListener::getSkippedDeprecations())) { + if (!in_array($message, DeprecationListenerTrait::getSkippedDeprecations())) { call_user_func_array([&$this, 'error'], $parameters); } } diff --git a/core/modules/tour/src/Tests/TourTestBase.php b/core/modules/tour/src/Tests/TourTestBase.php index e139650706..f551c8151b 100644 --- a/core/modules/tour/src/Tests/TourTestBase.php +++ b/core/modules/tour/src/Tests/TourTestBase.php @@ -14,6 +14,17 @@ */ abstract class TourTestBase extends WebTestBase { + /** + * {@inheritdoc} + */ + protected function setUp() { + // Support both PHPUnit 4 and 6. + if (!class_exists('\PHPUnit_Util_XML') && class_exists('\PHPUnit\Util\XML')) { + class_alias('\PHPUnit\Util\XML', '\PHPUnit_Util_XML'); + } + parent::setUp(); + } + /** * Assert function to determine if tips rendered to the page * have a corresponding page element. diff --git a/core/modules/update/tests/src/Unit/UpdateFetcherTest.php b/core/modules/update/tests/src/Unit/UpdateFetcherTest.php index c3e447d1fc..61c767deda 100644 --- a/core/modules/update/tests/src/Unit/UpdateFetcherTest.php +++ b/core/modules/update/tests/src/Unit/UpdateFetcherTest.php @@ -28,7 +28,7 @@ class UpdateFetcherTest extends UnitTestCase { */ protected function setUp() { $config_factory = $this->getConfigFactoryStub(['update.settings' => ['fetch_url' => 'http://www.example.com']]); - $http_client_mock = $this->getMock('\GuzzleHttp\ClientInterface'); + $http_client_mock = $this->createMock('\GuzzleHttp\ClientInterface'); $this->updateFetcher = new UpdateFetcher($config_factory, $http_client_mock); } diff --git a/core/phpunit.xml.dist b/core/phpunit.xml.dist index bfe74673b2..750c6e2b50 100644 --- a/core/phpunit.xml.dist +++ b/core/phpunit.xml.dist @@ -49,16 +49,11 @@ - + - + - - - - diff --git a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php index 95ee39fd3a..38e610c3b5 100644 --- a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php +++ b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php @@ -188,7 +188,7 @@ public function testInvalidLinkNotExistsExact() { /** * Tests legacy text asserts. */ - public function testLegacyTextAsserts() { + public function testTextAsserts() { $this->drupalGet('test-encoded'); $dangerous = 'Bad html '; $sanitized = Html::escape($dangerous); @@ -202,7 +202,7 @@ public function testLegacyTextAsserts() { /** * Tests legacy field asserts which use xpath directly. */ - public function testLegacyXpathAsserts() { + public function testXpathAsserts() { $this->drupalGet('test-field-xpath'); $this->assertFieldsByValue($this->xpath("//h1[@class = 'page-title']"), NULL); $this->assertFieldsByValue($this->xpath('//table/tbody/tr[2]/td[1]'), 'one'); @@ -245,7 +245,7 @@ public function testLegacyXpathAsserts() { /** * Tests legacy field asserts using textfields. */ - public function testLegacyFieldAssertsForTextfields() { + public function testFieldAssertsForTextfields() { $this->drupalGet('test-field-xpath'); // *** 1. assertNoField(). @@ -387,7 +387,7 @@ public function testLegacyFieldAssertsForTextfields() { /** * Tests legacy field asserts for options field type. */ - public function testLegacyFieldAssertsForOptions() { + public function testFieldAssertsForOptions() { $this->drupalGet('test-field-xpath'); // Option field type. @@ -443,7 +443,7 @@ public function testLegacyFieldAssertsForOptions() { /** * Tests legacy field asserts for button field type. */ - public function testLegacyFieldAssertsForButton() { + public function testFieldAssertsForButton() { $this->drupalGet('test-field-xpath'); $this->assertFieldById('edit-save', NULL); @@ -485,7 +485,7 @@ public function testLegacyFieldAssertsForButton() { /** * Tests legacy field asserts for checkbox field type. */ - public function testLegacyFieldAssertsForCheckbox() { + public function testFieldAssertsForCheckbox() { $this->drupalGet('test-field-xpath'); // Part 1 - Test by name. diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php index 32c97b63b5..91da81edf8 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -20,6 +20,7 @@ use Drupal\simpletest\AssertContentTrait; use Drupal\Tests\AssertHelperTrait; use Drupal\Tests\ConfigTestTrait; +use Drupal\Tests\Phpunit5FCTrait; use Drupal\Tests\RandomGeneratorTrait; use Drupal\Tests\TestRequirementsTrait; use Drupal\simpletest\TestServiceProvider; @@ -76,6 +77,7 @@ use RandomGeneratorTrait; use ConfigTestTrait; use TestRequirementsTrait; + use Phpunit5FCTrait; /** * {@inheritdoc} diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php index b12ba60b8a..83e43605fe 100644 --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -66,6 +66,7 @@ createUser as drupalCreateUser; } use XdebugRequestTrait; + use Phpunit5FCTrait; /** * The database prefix of this test run. diff --git a/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php index 297125bf63..b89d351c75 100644 --- a/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php +++ b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php @@ -87,7 +87,13 @@ public function testDateDiff($input1, $input2, $absolute, \DateInterval $expecte * @dataProvider providerTestInvalidDateDiff */ public function testInvalidDateDiff($input1, $input2, $absolute) { - $this->setExpectedException(\BadMethodCallException::class, 'Method Drupal\Component\Datetime\DateTimePlus::diff expects parameter 1 to be a \DateTime or \Drupal\Component\Datetime\DateTimePlus object'); + if (method_exists($this, 'expectException')) { + $this->expectException(\BadMethodCallException::class); + $this->expectExceptionMessage('Method Drupal\Component\Datetime\DateTimePlus::diff expects parameter 1 to be a \DateTime or \Drupal\Component\Datetime\DateTimePlus object'); + } + else { + $this->setExpectedException(\BadMethodCallException::class, 'Method Drupal\Component\Datetime\DateTimePlus::diff expects parameter 1 to be a \DateTime or \Drupal\Component\Datetime\DateTimePlus object'); + } $interval = $input1->diff($input2, $absolute); } @@ -104,7 +110,12 @@ public function testInvalidDateDiff($input1, $input2, $absolute) { * @dataProvider providerTestInvalidDateArrays */ public function testInvalidDateArrays($input, $timezone, $class) { - $this->setExpectedException($class); + if (method_exists($this, 'expectException')) { + $this->expectException($class); + } + else { + $this->setExpectedException($class); + } $this->assertInstanceOf( '\Drupal\Component\DateTimePlus', DateTimePlus::createFromArray($input, $timezone) @@ -242,7 +253,12 @@ public function testDateFormat($input, $timezone, $format, $format_date, $expect * @dataProvider providerTestInvalidDates */ public function testInvalidDates($input, $timezone, $format, $message, $class) { - $this->setExpectedException($class); + if (method_exists($this, 'expectException')) { + $this->expectException($class); + } + else { + $this->setExpectedException($class); + } DateTimePlus::createFromFormat($format, $input, $timezone); } @@ -800,7 +816,12 @@ public function testValidateFormat() { // Parse the same date with ['validate_format' => TRUE] and make sure we // get the expected exception. - $this->setExpectedException(\UnexpectedValueException::class); + if (method_exists($this, 'expectException')) { + $this->expectException(\UnexpectedValueException::class); + } + else { + $this->setExpectedException(\UnexpectedValueException::class); + } $date = DateTimePlus::createFromFormat('Y-m-d H:i:s', '11-03-31 17:44:00', 'UTC', ['validate_format' => TRUE]); } @@ -859,7 +880,13 @@ public function testChainableNonChainable() { * @covers ::__call */ public function testChainableNonCallable() { - $this->setExpectedException(\BadMethodCallException::class, 'Call to undefined method Drupal\Component\Datetime\DateTimePlus::nonexistent()'); + if (method_exists($this, 'expectException')) { + $this->expectException(\BadMethodCallException::class); + $this->expectExceptionMessage('Call to undefined method Drupal\Component\Datetime\DateTimePlus::nonexistent()'); + } + else { + $this->setExpectedException(\BadMethodCallException::class, 'Call to undefined method Drupal\Component\Datetime\DateTimePlus::nonexistent()'); + } $date = new DateTimePlus('now', 'Australia/Sydney'); $date->setTimezone(new \DateTimeZone('America/New_York'))->nonexistent(); } diff --git a/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php b/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php index 4a5fa80205..29c27b23c7 100644 --- a/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php +++ b/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php @@ -37,7 +37,12 @@ class TimeTest extends TestCase { protected function setUp() { parent::setUp(); - $this->requestStack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack'); + if (method_exists($this, 'createMock')) { + $this->requestStack = $this->createMock('Symfony\Component\HttpFoundation\RequestStack'); + } + else { + $this->requestStack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack'); + } $this->time = new Time($this->requestStack); } diff --git a/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php b/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php index 0e6a1472cd..c2d43db027 100644 --- a/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php +++ b/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php @@ -983,6 +983,28 @@ protected function getCollection($collection, $resolve = TRUE) { ]; } + /** + * Compatibility layer for PHPUnit 6 to support PHPUnit 4 code. + * + * @param mixed $class + * @param string $message + * @param int $exception_code + */ + private function setExpectedException($class, $message = '', $exception_code = NULL) { + if (method_exists($this, 'expectException')) { + $this->expectException($class); + if (!empty($message)) { + $this->expectExceptionMessage($message); + } + if ($exception_code !== NULL) { + $this->expectExceptionCode($exception_code); + } + } + else { + parent::setExpectedException($class, $message, $exception_code); + } + } + } /** diff --git a/core/tests/Drupal/Tests/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php b/core/tests/Drupal/Tests/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php index 3c44752748..c1b70954d1 100644 --- a/core/tests/Drupal/Tests/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php +++ b/core/tests/Drupal/Tests/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php @@ -545,7 +545,12 @@ public function testGetServiceDefinitionForDecoratedService() { $services['bar'] = $bar_definition; $this->containerBuilder->getDefinitions()->willReturn($services); - $this->setExpectedException(InvalidArgumentException::class); + if (method_exists($this, 'expectException')) { + $this->expectException(InvalidArgumentException::class); + } + else { + $this->setExpectedException(InvalidArgumentException::class); + } $this->dumper->getArray(); } @@ -562,7 +567,12 @@ public function testGetServiceDefinitionForExpression() { $services['bar'] = $bar_definition; $this->containerBuilder->getDefinitions()->willReturn($services); - $this->setExpectedException(RuntimeException::class); + if (method_exists($this, 'expectException')) { + $this->expectException(RuntimeException::class); + } + else { + $this->setExpectedException(RuntimeException::class); + } $this->dumper->getArray(); } @@ -579,7 +589,12 @@ public function testGetServiceDefinitionForObject() { $services['bar'] = $bar_definition; $this->containerBuilder->getDefinitions()->willReturn($services); - $this->setExpectedException(RuntimeException::class); + if (method_exists($this, 'expectException')) { + $this->expectException(RuntimeException::class); + } + else { + $this->setExpectedException(RuntimeException::class); + } $this->dumper->getArray(); } @@ -596,7 +611,12 @@ public function testGetServiceDefinitionForResource() { $services['bar'] = $bar_definition; $this->containerBuilder->getDefinitions()->willReturn($services); - $this->setExpectedException(RuntimeException::class); + if (method_exists($this, 'expectException')) { + $this->expectException(RuntimeException::class); + } + else { + $this->setExpectedException(RuntimeException::class); + } $this->dumper->getArray(); } diff --git a/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php b/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php index 1a649ae510..dbbb6ec081 100644 --- a/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php +++ b/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php @@ -4,6 +4,7 @@ use Drupal\Component\Diff\Engine\DiffOp; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Error\Error; /** * Test DiffOp base class. @@ -24,7 +25,12 @@ class DiffOpTest extends TestCase { * @covers ::reverse */ public function testReverse() { - $this->setExpectedException(\PHPUnit_Framework_Error::class); + if (method_exists($this, 'expectException')) { + $this->expectException(Error::class); + } + else { + $this->setExpectedException(\PHPUnit_Framework_Error::class); + } $op = new DiffOp(); $result = $op->reverse(); } diff --git a/core/tests/Drupal/Tests/Component/Discovery/YamlDirectoryDiscoveryTest.php b/core/tests/Drupal/Tests/Component/Discovery/YamlDirectoryDiscoveryTest.php index 86134a7bdf..9ac807d744 100644 --- a/core/tests/Drupal/Tests/Component/Discovery/YamlDirectoryDiscoveryTest.php +++ b/core/tests/Drupal/Tests/Component/Discovery/YamlDirectoryDiscoveryTest.php @@ -124,7 +124,13 @@ public function testDiscoveryAlternateId() { * @covers ::getIdentifier */ public function testDiscoveryNoIdException() { - $this->setExpectedException(DiscoveryException::class, 'The vfs://modules/test_1/item_1.test.yml contains no data in the identifier key \'id\''); + if (method_exists($this, 'expectException')) { + $this->expectException(DiscoveryException::class); + $this->expectExceptionMessage('The vfs://modules/test_1/item_1.test.yml contains no data in the identifier key \'id\''); + } + else { + $this->setExpectedException(DiscoveryException::class, 'The vfs://modules/test_1/item_1.test.yml contains no data in the identifier key \'id\''); + } vfsStream::setup('modules', NULL, [ 'test_1' => [ 'item_1.test.yml' => "", @@ -144,7 +150,13 @@ public function testDiscoveryNoIdException() { * @covers ::findAll */ public function testDiscoveryInvalidYamlException() { - $this->setExpectedException(DiscoveryException::class, 'The vfs://modules/test_1/item_1.test.yml contains invalid YAML'); + if (method_exists($this, 'expectException')) { + $this->expectException(DiscoveryException::class); + $this->expectExceptionMessage('The vfs://modules/test_1/item_1.test.yml contains invalid YAML'); + } + else { + $this->setExpectedException(DiscoveryException::class, 'The vfs://modules/test_1/item_1.test.yml contains invalid YAML'); + } vfsStream::setup('modules', NULL, [ 'test_1' => [ 'item_1.test.yml' => "id: invalid\nfoo : [bar}", diff --git a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php index ea0685a717..a750ecaf09 100644 --- a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php +++ b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php @@ -38,7 +38,7 @@ public function testGetListenersWithCallables() // When passing in callables exclusively as listeners into the event // dispatcher constructor, the event dispatcher must not attempt to // resolve any services. - $container = $this->getMock(ContainerInterface::class); + $container = $this->getMockBuilder(ContainerInterface::class)->getMock(); $container->expects($this->never())->method($this->anything()); $firstListener = new CallableClass(); @@ -73,7 +73,7 @@ public function testDispatchWithCallables() // When passing in callables exclusively as listeners into the event // dispatcher constructor, the event dispatcher must not attempt to // resolve any services. - $container = $this->getMock(ContainerInterface::class); + $container = $this->getMockBuilder(ContainerInterface::class)->getMock(); $container->expects($this->never())->method($this->anything()); $firstListener = new CallableClass(); diff --git a/core/tests/Drupal/Tests/Component/FileCache/FileCacheFactoryTest.php b/core/tests/Drupal/Tests/Component/FileCache/FileCacheFactoryTest.php index 995f5fc851..f919598434 100644 --- a/core/tests/Drupal/Tests/Component/FileCache/FileCacheFactoryTest.php +++ b/core/tests/Drupal/Tests/Component/FileCache/FileCacheFactoryTest.php @@ -59,7 +59,13 @@ public function testGet() { */ public function testGetNoPrefix() { FileCacheFactory::setPrefix(NULL); - $this->setExpectedException(\InvalidArgumentException::class, 'Required prefix configuration is missing'); + if (method_exists($this, 'expectException')) { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Required prefix configuration is missing'); + } + else { + $this->setExpectedException(\InvalidArgumentException::class, 'Required prefix configuration is missing'); + } FileCacheFactory::get('test_foo_settings', []); } diff --git a/core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php b/core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php index 52e1b83c03..168d1603e3 100644 --- a/core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php +++ b/core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php @@ -5,7 +5,7 @@ use Drupal\Component\PhpStorage\FileStorage; use Drupal\Component\Utility\Random; use org\bovigo\vfs\vfsStreamDirectory; -use PHPUnit_Framework_Error_Warning; +use PHPUnit\Framework\Error\Warning; /** * @coversDefaultClass \Drupal\Component\PhpStorage\FileStorage @@ -99,7 +99,13 @@ public function testCreateDirectoryFailWarning() { 'bin' => 'test', ]); $code = "setExpectedException(PHPUnit_Framework_Error_Warning::class, 'mkdir(): Permission Denied'); + if (method_exists($this, 'expectException')) { + $this->expectException(Warning::class); + $this->expectExceptionMessage('mkdir(): Permission Denied'); + } + else { + $this->setExpectedException(\PHPUnit_Framework_Error_Warning::class, 'mkdir(): Permission Denied'); + } $storage->save('subdirectory/foo.php', $code); } diff --git a/core/tests/Drupal/Tests/Component/Serialization/YamlPeclTest.php b/core/tests/Drupal/Tests/Component/Serialization/YamlPeclTest.php index c2e0a0d888..5a71f48381 100644 --- a/core/tests/Drupal/Tests/Component/Serialization/YamlPeclTest.php +++ b/core/tests/Drupal/Tests/Component/Serialization/YamlPeclTest.php @@ -87,7 +87,12 @@ public function testGetFileExtension() { * @covers ::errorHandler */ public function testError() { - $this->setExpectedException(InvalidDataTypeException::class); + if (method_exists($this, 'expectException')) { + $this->expectException(InvalidDataTypeException::class); + } + else { + $this->setExpectedException(InvalidDataTypeException::class); + } YamlPecl::decode('foo: [ads'); } diff --git a/core/tests/Drupal/Tests/Component/Serialization/YamlSymfonyTest.php b/core/tests/Drupal/Tests/Component/Serialization/YamlSymfonyTest.php index 86c818c18e..d857d097a5 100644 --- a/core/tests/Drupal/Tests/Component/Serialization/YamlSymfonyTest.php +++ b/core/tests/Drupal/Tests/Component/Serialization/YamlSymfonyTest.php @@ -59,7 +59,12 @@ public function testGetFileExtension() { * @covers ::decode */ public function testError() { - $this->setExpectedException(InvalidDataTypeException::class); + if (method_exists($this, 'expectException')) { + $this->expectException(InvalidDataTypeException::class); + } + else { + $this->setExpectedException(InvalidDataTypeException::class); + } YamlSymfony::decode('foo: [ads'); } @@ -69,7 +74,13 @@ public function testError() { * @covers ::encode */ public function testObjectSupportDisabled() { - $this->setExpectedException(InvalidDataTypeException::class, 'Object support when dumping a YAML file has been disabled.'); + if (method_exists($this, 'expectException')) { + $this->expectException(InvalidDataTypeException::class); + $this->expectExceptionMessage('Object support when dumping a YAML file has been disabled.'); + } + else { + $this->setExpectedException(InvalidDataTypeException::class, 'Object support when dumping a YAML file has been disabled.'); + } $object = new \stdClass(); $object->foo = 'bar'; YamlSymfony::encode([$object]); diff --git a/core/tests/Drupal/Tests/Component/Utility/ArgumentsResolverTest.php b/core/tests/Drupal/Tests/Component/Utility/ArgumentsResolverTest.php index f15f14b85a..695edf4ba6 100644 --- a/core/tests/Drupal/Tests/Component/Utility/ArgumentsResolverTest.php +++ b/core/tests/Drupal/Tests/Component/Utility/ArgumentsResolverTest.php @@ -96,9 +96,16 @@ public function testGetWildcardArgument() { * Tests getArgument() with a Route, Request, and Account object. */ public function testGetArgumentOrder() { - $a1 = $this->getMock('\Drupal\Tests\Component\Utility\Test1Interface'); - $a2 = $this->getMock('\Drupal\Tests\Component\Utility\TestClass'); - $a3 = $this->getMock('\Drupal\Tests\Component\Utility\Test2Interface'); + if (method_exists($this, 'createMock')) { + $a1 = $this->createMock('\Drupal\Tests\Component\Utility\Test1Interface'); + $a2 = $this->createMock('\Drupal\Tests\Component\Utility\TestClass'); + $a3 = $this->createMock('\Drupal\Tests\Component\Utility\Test2Interface'); + } + else { + $a1 = $this->getMock('\Drupal\Tests\Component\Utility\Test1Interface'); + $a2 = $this->getMock('\Drupal\Tests\Component\Utility\TestClass'); + $a3 = $this->getMock('\Drupal\Tests\Component\Utility\Test2Interface'); + } $objects = [ 't1' => $a1, @@ -123,12 +130,23 @@ public function testGetArgumentOrder() { * Without the typehint, the wildcard object will not be passed to the callable. */ public function testGetWildcardArgumentNoTypehint() { - $a = $this->getMock('\Drupal\Tests\Component\Utility\Test1Interface'); + if (method_exists($this, 'createMock')) { + $a = $this->createMock('\Drupal\Tests\Component\Utility\Test1Interface'); + } + else { + $a = $this->getMock('\Drupal\Tests\Component\Utility\Test1Interface'); + } $wildcards = [$a]; $resolver = new ArgumentsResolver([], [], $wildcards); $callable = function ($route) {}; - $this->setExpectedException(\RuntimeException::class, 'requires a value for the "$route" argument.'); + if (method_exists($this, 'expectException')) { + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('requires a value for the "$route" argument.'); + } + else { + $this->setExpectedException(\RuntimeException::class, 'requires a value for the "$route" argument.'); + } $resolver->getArguments($callable); } @@ -156,7 +174,13 @@ public function testHandleNotUpcastedArgument() { $resolver = new ArgumentsResolver($scalars, $objects, []); $callable = function (\stdClass $foo) {}; - $this->setExpectedException(\RuntimeException::class, 'requires a value for the "$foo" argument.'); + if (method_exists($this, 'expectException')) { + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('requires a value for the "$foo" argument.'); + } + else { + $this->setExpectedException(\RuntimeException::class, 'requires a value for the "$foo" argument.'); + } $resolver->getArguments($callable); } @@ -167,7 +191,13 @@ public function testHandleNotUpcastedArgument() { */ public function testHandleUnresolvedArgument($callable) { $resolver = new ArgumentsResolver([], [], []); - $this->setExpectedException(\RuntimeException::class, 'requires a value for the "$foo" argument.'); + if (method_exists($this, 'expectException')) { + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('requires a value for the "$foo" argument.'); + } + else { + $this->setExpectedException(\RuntimeException::class, 'requires a value for the "$foo" argument.'); + } $resolver->getArguments($callable); } diff --git a/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php b/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php index 1860e04105..a8a8af0e6c 100644 --- a/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php +++ b/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php @@ -343,7 +343,12 @@ public function testTransformRootRelativeUrlsToAbsolute($html, $scheme_and_host, * @dataProvider providerTestTransformRootRelativeUrlsToAbsoluteAssertion */ public function testTransformRootRelativeUrlsToAbsoluteAssertion($scheme_and_host) { - $this->setExpectedException(\AssertionError::class); + if (method_exists($this, 'expectException')) { + $this->expectException(\AssertionError::class); + } + else { + $this->setExpectedException(\AssertionError::class); + } Html::transformRootRelativeUrlsToAbsolute('', $scheme_and_host); } diff --git a/core/tests/Drupal/Tests/Core/Entity/Access/EntityFormDisplayAccessControlHandlerTest.php b/core/tests/Drupal/Tests/Core/Entity/Access/EntityFormDisplayAccessControlHandlerTest.php index 1ee804d539..a92d76abb7 100644 --- a/core/tests/Drupal/Tests/Core/Entity/Access/EntityFormDisplayAccessControlHandlerTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/Access/EntityFormDisplayAccessControlHandlerTest.php @@ -164,10 +164,6 @@ protected function setUp() { ->willReturnMap([ ['entity_display', $storage_access_control_handler], ]); - $entity_type_manager - ->expects($this->any()) - ->method('getFieldDefinitions') - ->willReturn([]); $entity_type_manager ->expects($this->any()) ->method('getDefinition') diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php index ad68e2df68..55928b98a6 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php @@ -123,9 +123,6 @@ public function testGetOperations() { $url = $this->getMockBuilder('\Drupal\Core\Url') ->disableOriginalConstructor() ->getMock(); - $url->expects($this->any()) - ->method('toArray') - ->will($this->returnValue([])); $url->expects($this->atLeastOnce()) ->method('mergeOptions') ->with(['query' => ['destination' => '/foo/bar']]); diff --git a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php index 4a2dac5653..846ce0a59f 100644 --- a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php @@ -361,7 +361,7 @@ public function testSaveConfigEntity() { $this->assertSame('foo', $entity->getOriginalId()); $expected = ['id' => 'foo']; - $entity->expects($this->once()) + $entity->expects($this->atLeastOnce()) ->method('toArray') ->will($this->returnValue($expected)); diff --git a/core/tests/Drupal/Tests/Listeners/DeprecationListener.php b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php similarity index 97% rename from core/tests/Drupal/Tests/Listeners/DeprecationListener.php rename to core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php index 80b3d31c97..8b828e0178 100644 --- a/core/tests/Drupal/Tests/Listeners/DeprecationListener.php +++ b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php @@ -9,12 +9,18 @@ * This class will be removed once all the deprecation notices have been * fixed. */ -class DeprecationListener extends \PHPUnit_Framework_BaseTestListener { +trait DeprecationListenerTrait { /** - * {@inheritdoc} + * Reacts to the end of a test. + * + * @param $test + * The test object that has ended its test run. + * @param float $time + * The time the test took. */ - public function endTest(\PHPUnit_Framework_Test $test, $time) { + protected function deprecationEndTest($test, $time) { + /** @var \PHPUnit\Framework\Test $test */ // Need to edit the file of deprecations. if ($file = getenv('SYMFONY_DEPRECATIONS_SERIALIZE')) { $deprecations = file_get_contents($file); diff --git a/core/tests/Drupal/Tests/Listeners/DrupalComponentTestListener.php b/core/tests/Drupal/Tests/Listeners/DrupalComponentTestListenerTrait.php similarity index 52% rename from core/tests/Drupal/Tests/Listeners/DrupalComponentTestListener.php rename to core/tests/Drupal/Tests/Listeners/DrupalComponentTestListenerTrait.php index c349677305..0284f6da90 100644 --- a/core/tests/Drupal/Tests/Listeners/DrupalComponentTestListener.php +++ b/core/tests/Drupal/Tests/Listeners/DrupalComponentTestListenerTrait.php @@ -5,20 +5,28 @@ use Drupal\KernelTests\KernelTestBase;; use Drupal\Tests\BrowserTestBase;; use Drupal\Tests\UnitTestCase; -use PHPUnit\Framework\BaseTestListener; +use PHPUnit\Framework\AssertionFailedError; /** * Ensures that no component tests are extending a core test base class. + * + * @internal */ -class DrupalComponentTestListener extends BaseTestListener { +trait DrupalComponentTestListenerTrait { /** - * {@inheritdoc} + * Reacts to the end of a test. + * + * @param $test + * The test object that has ended its test run. + * @param float $time + * The time the test took. */ - public function endTest(\PHPUnit_Framework_Test $test, $time) { + protected function componentEndTest($test, $time) { + /** @var \PHPUnit\Framework\Test $test */ if (substr($test->toString(), 0, 22) == 'Drupal\Tests\Component') { if ($test instanceof BrowserTestBase || $test instanceof KernelTestBase || $test instanceof UnitTestCase) { - $error = new \PHPUnit_Framework_AssertionFailedError('Component tests should not extend a core test base class.'); + $error = new AssertionFailedError('Component tests should not extend a core test base class.'); $test->getTestResultObject()->addFailure($test, $error, $time); } } diff --git a/core/tests/Drupal/Tests/Listeners/DrupalListener.php b/core/tests/Drupal/Tests/Listeners/DrupalListener.php new file mode 100644 index 0000000000..db0c822588 --- /dev/null +++ b/core/tests/Drupal/Tests/Listeners/DrupalListener.php @@ -0,0 +1,36 @@ +deprecationEndTest($test, $time); + $this->componentEndTest($test, $time); + $this->standardsEndTest($test, $time); + } + + } +} diff --git a/core/tests/Drupal/Tests/Listeners/DrupalStandardsListener.php b/core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php similarity index 80% rename from core/tests/Drupal/Tests/Listeners/DrupalStandardsListener.php rename to core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php index fd15f8218b..d94299cc9f 100644 --- a/core/tests/Drupal/Tests/Listeners/DrupalStandardsListener.php +++ b/core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php @@ -2,15 +2,18 @@ namespace Drupal\Tests\Listeners; -use PHPUnit\Framework\BaseTestListener; +use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; /** * Listens for PHPUnit tests and fails those with invalid coverage annotations. * * Enforces various coding standards within test runs. + * + * @internal */ -class DrupalStandardsListener extends BaseTestListener { +trait DrupalStandardsListenerTrait { /** * Signals a coding standards failure to the user. @@ -21,10 +24,10 @@ class DrupalStandardsListener extends BaseTestListener { * The message to add to the failure notice. The test class name and test * name will be appended to this message automatically. */ - protected function fail(TestCase $test, $message) { + private function fail(TestCase $test, $message) { // Add the report to the test's results. $message .= ': ' . get_class($test) . '::' . $test->getName(); - $fail = new \PHPUnit_Framework_AssertionFailedError($message); + $fail = new AssertionFailedError($message); $result = $test->getTestResultObject(); $result->addFailure($test, $fail, 0); } @@ -38,7 +41,7 @@ protected function fail(TestCase $test, $message) { * @return bool * TRUE if the class exists, FALSE otherwise. */ - protected function classExists($class) { + private function classExists($class) { return class_exists($class, TRUE) || trait_exists($class, TRUE) || interface_exists($class, TRUE); } @@ -50,7 +53,7 @@ protected function classExists($class) { * @param \PHPUnit\Framework\TestCase $test * The test to examine. */ - public function checkValidCoversForTest(TestCase $test) { + private function checkValidCoversForTest(TestCase $test) { // If we're generating a coverage report already, don't do anything here. if ($test->getTestResultObject() && $test->getTestResultObject()->getCollectCodeCoverageInformation()) { return; @@ -141,7 +144,7 @@ public function checkValidCoversForTest(TestCase $test) { } /** - * {@inheritdoc} + * Reacts to the end of a test. * * We must mark this method as belonging to the special legacy group because * it might trigger an E_USER_DEPRECATED error during coverage annotation @@ -151,22 +154,58 @@ public function checkValidCoversForTest(TestCase $test) { * * @group legacy * + * @param $test + * The test object that has ended its test run. + * @param float $time + * The time the test took. + * * @see http://symfony.com/doc/current/components/phpunit_bridge.html#mark-tests-as-legacy */ - public function endTest(\PHPUnit_Framework_Test $test, $time) { + private function doEndTest($test, $time) { // \PHPUnit_Framework_Test does not have any useful methods of its own for // our purpose, so we have to distinguish between the different known // subclasses. if ($test instanceof TestCase) { $this->checkValidCoversForTest($test); } - elseif ($test instanceof \PHPUnit_Framework_TestSuite) { + elseif ($this->isTestSuite($test)) { foreach ($test->getGroupDetails() as $tests) { foreach ($tests as $test) { - $this->endTest($test, $time); + $this->doEndTest($test, $time); } } } } + /** + * Determine if a test object is a test suite regardless of PHPUnit version. + * + * @param $test + * The test object to test if it is a test suite. + * + * @return bool + * TRUE if it is a test suite, FALSE if not. + */ + private function isTestSuite($test) { + if (class_exists('\PHPUnit_Framework_TestSuite') && $test instanceof \PHPUnit_Framework_TestSuite) { + return TRUE; + } + if (class_exists('PHPUnit\Framework\TestSuite') && $test instanceof TestSuite) { + return TRUE; + } + return FALSE; + } + + /** + * Reacts to the end of a test. + * + * @param $test + * The test object that has ended its test run. + * @param float $time + * The time the test took. + */ + protected function standardsEndTest($test, $time) { + $this->doEndTest($test, $time); + } + } diff --git a/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php b/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php index ac22072d16..8021989868 100644 --- a/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php +++ b/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php @@ -2,70 +2,41 @@ namespace Drupal\Tests\Listeners; -/** - * Defines a class for providing html output results for functional tests. - */ -class HtmlOutputPrinter extends \PHPUnit_TextUI_ResultPrinter { - +use PHPUnit\Framework\TestResult; +use PHPUnit\TextUI\ResultPrinter; + +if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { + class_alias('Drupal\Tests\Listeners\Legacy\HtmlOutputPrinter', 'Drupal\Tests\Listeners\HtmlOutputPrinter'); + // Using an early return instead of a else does not work when using the + // PHPUnit phar due to some weird PHP behavior (the class gets defined without + // executing the code before it and so the definition is not properly + // conditional). +} +else { /** - * File to write html links to. + * Defines a class for providing html output results for functional tests. * - * @var string + * @internal */ - protected $browserOutputFile; - - /** - * {@inheritdoc} - */ - public function __construct($out, $verbose, $colors, $debug, $numberOfColumns) { - parent::__construct($out, $verbose, $colors, $debug, $numberOfColumns); - if ($html_output_directory = getenv('BROWSERTEST_OUTPUT_DIRECTORY')) { - // Initialize html output debugging. - $html_output_directory = rtrim($html_output_directory, '/'); - - // Check if directory exists. - if (!is_dir($html_output_directory) || !is_writable($html_output_directory)) { - $this->writeWithColor('bg-red, fg-black', "HTML output directory $html_output_directory is not a writable directory."); - } - else { - // Convert to a canonicalized absolute pathname just in case the current - // working directory is changed. - $html_output_directory = realpath($html_output_directory); - $this->browserOutputFile = tempnam($html_output_directory, 'browser_output_'); - if ($this->browserOutputFile) { - touch($this->browserOutputFile); - } - else { - $this->writeWithColor('bg-red, fg-black', "Unable to create a temporary file in $html_output_directory."); - } - } - } - - if ($this->browserOutputFile) { - putenv('BROWSERTEST_OUTPUT_FILE=' . $this->browserOutputFile); - } - else { - // Remove any environment variable. - putenv('BROWSERTEST_OUTPUT_FILE'); + class HtmlOutputPrinter extends ResultPrinter { + use HtmlOutputPrinterTrait; + /** + * {@inheritdoc} + */ + public function __construct($out = NULL, $verbose = FALSE, $colors = self::COLOR_DEFAULT, $debug = FALSE, $numberOfColumns = 80, $reverse = FALSE) { + parent::__construct($out, $verbose, $colors, $debug, $numberOfColumns, $reverse); + + $this->setUpHtmlOutput(); } - } - /** - * {@inheritdoc} - */ - public function printResult(\PHPUnit_Framework_TestResult $result) { - parent::printResult($result); + /** + * {@inheritdoc} + */ + public function printResult(TestResult $result) { + parent::printResult($result); - if ($this->browserOutputFile) { - $contents = file_get_contents($this->browserOutputFile); - if ($contents) { - $this->writeNewLine(); - $this->writeWithColor('bg-yellow, fg-black', 'HTML output was generated'); - $this->write($contents); - } - // No need to keep the file around any more. - unlink($this->browserOutputFile); + $this->printHtmlOutput(); } - } + } } diff --git a/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php b/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinterTrait.php similarity index 85% copy from core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php copy to core/tests/Drupal/Tests/Listeners/HtmlOutputPrinterTrait.php index ac22072d16..9900685884 100644 --- a/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinter.php +++ b/core/tests/Drupal/Tests/Listeners/HtmlOutputPrinterTrait.php @@ -4,8 +4,10 @@ /** * Defines a class for providing html output results for functional tests. + * + * @internal */ -class HtmlOutputPrinter extends \PHPUnit_TextUI_ResultPrinter { +trait HtmlOutputPrinterTrait { /** * File to write html links to. @@ -17,8 +19,7 @@ class HtmlOutputPrinter extends \PHPUnit_TextUI_ResultPrinter { /** * {@inheritdoc} */ - public function __construct($out, $verbose, $colors, $debug, $numberOfColumns) { - parent::__construct($out, $verbose, $colors, $debug, $numberOfColumns); + protected function setUpHtmlOutput() { if ($html_output_directory = getenv('BROWSERTEST_OUTPUT_DIRECTORY')) { // Initialize html output debugging. $html_output_directory = rtrim($html_output_directory, '/'); @@ -53,9 +54,7 @@ public function __construct($out, $verbose, $colors, $debug, $numberOfColumns) { /** * {@inheritdoc} */ - public function printResult(\PHPUnit_Framework_TestResult $result) { - parent::printResult($result); - + protected function printHtmlOutput() { if ($this->browserOutputFile) { $contents = file_get_contents($this->browserOutputFile); if ($contents) { diff --git a/core/tests/Drupal/Tests/Listeners/Legacy/DrupalListener.php b/core/tests/Drupal/Tests/Listeners/Legacy/DrupalListener.php new file mode 100644 index 0000000000..f7c2c76668 --- /dev/null +++ b/core/tests/Drupal/Tests/Listeners/Legacy/DrupalListener.php @@ -0,0 +1,29 @@ +deprecationEndTest($test, $time); + $this->componentEndTest($test, $time); + $this->standardsEndTest($test, $time); + } + +} diff --git a/core/tests/Drupal/Tests/Listeners/Legacy/HtmlOutputPrinter.php b/core/tests/Drupal/Tests/Listeners/Legacy/HtmlOutputPrinter.php new file mode 100644 index 0000000000..7c1f45e38f --- /dev/null +++ b/core/tests/Drupal/Tests/Listeners/Legacy/HtmlOutputPrinter.php @@ -0,0 +1,33 @@ +setUpHtmlOutput(); + } + + /** + * {@inheritdoc} + */ + public function printResult(\PHPUnit_Framework_TestResult $result) { + parent::printResult($result); + + $this->printHtmlOutput(); + } + +} diff --git a/core/tests/Drupal/Tests/Phpunit5FCTrait.php b/core/tests/Drupal/Tests/Phpunit5FCTrait.php new file mode 100644 index 0000000000..7ace0bf198 --- /dev/null +++ b/core/tests/Drupal/Tests/Phpunit5FCTrait.php @@ -0,0 +1,169 @@ +createMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, $proxyTarget); + } + + /** + * Returns a mock object for the specified class using the available method. + * + * The getMock method is deprecated in PHPUnit 5 but the createMock method is + * not available in PHPUnit 4. To provide forward compatibility this trait + * provides the createMock method and uses createMock if this method is + * available on the parent class or falls back to getMock if it isn't. + * + * @param string $originalClassName + * Name of the class to mock. + * @param array|null $methods + * When provided, only methods whose names are in the array are replaced + * with a configurable test double. The behavior of the other methods is not + * changed. Providing null means that no methods will be replaced. + * @param array $arguments + * Parameters to pass to the original class' constructor. + * @param string $mockClassName + * Class name for the generated test double class. + * @param bool $callOriginalConstructor + * Can be used to disable the call to the original class' constructor. + * @param bool $callOriginalClone + * Can be used to disable the call to the original class' clone constructor. + * @param bool $callAutoload + * Can be used to disable __autoload() during the generation of the test + * double class. + * @param bool $cloneArguments + * @param bool $callOriginalMethods + * @param object $proxyTarget + * + * @see \PHPUnit_Framework_TestCase::getMock + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function createMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE, $callOriginalMethods = FALSE, $proxyTarget = NULL) { + if ($this->isPhpunit5()) { + $mock = $this->getMockBuilder($originalClassName) + ->setMethods($methods) + ->setConstructorArgs($arguments) + ->setMockClassName($mockClassName) + ->setProxyTarget($proxyTarget); + if ($callOriginalConstructor) { + $mock->enableOriginalConstructor(); + } + else { + $mock->disableOriginalConstructor(); + } + if ($callOriginalClone) { + $mock->enableOriginalClone(); + } + else { + $mock->disableOriginalClone(); + } + if ($callAutoload) { + $mock->enableAutoload(); + } + else { + $mock->disableAutoload(); + } + if ($cloneArguments) { + $mock->enableArgumentCloning(); + } + else { + $mock->disableArgumentCloning(); + } + if ($callOriginalMethods) { + $mock->enableProxyingToOriginalMethods(); + } + else { + $mock->disableProxyingToOriginalMethods(); + } + return $mock->getMock(); + } + return parent::getMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, $proxyTarget); + } + + /** + * Checks if the trait is used in a class extending the PHPUnit 5 TestCase. + * + * @return bool + */ + private function isPhpunit5() { + // Get the parent class of the currently running test class. + $parent = get_parent_class($this); + // Ensure that the method_exists() check on PHPUnit 5's createMock method is + // carried out on the first parent of $this that does not have access to + // this trait's methods. This is because the trait also has a method called + // createMock(). Most often the check will be made on + // \PHPUnit\Framework\TestCase. + while (method_exists($parent, 'isPhpunit5')) { + $parent = get_parent_class($parent); + } + return method_exists($parent, 'createMock'); + } + + /** + * Compatibility layer for PHPUnit 6 to support PHPUnit 4 code. + * + * @param mixed $class + * @param string $message + * @param int $exception_code + */ + public function setExpectedException($class, $message = '', $exception_code = NULL) { + if (method_exists($this, 'expectException')) { + $this->expectException($class); + if (!empty($message)) { + $this->expectExceptionMessage($message); + } + if ($exception_code !== NULL) { + $this->expectExceptionCode($exception_code); + } + } + else { + parent::setExpectedException($class, $message, $exception_code); + } + } + +} diff --git a/core/tests/Drupal/Tests/Phpunit5FCTraitTest.php b/core/tests/Drupal/Tests/Phpunit5FCTraitTest.php new file mode 100644 index 0000000000..621003f6b3 --- /dev/null +++ b/core/tests/Drupal/Tests/Phpunit5FCTraitTest.php @@ -0,0 +1,98 @@ +assertSame($expected, $class->getMock($this->randomMachineName())); + } + + /** + * Test that createMock is available and calls the correct parent method. + * + * @covers ::createMock + * @dataProvider providerMockVersions + */ + public function testCreateMock($className, $expected) { + $class = new $className(); + $this->assertSame($expected, $class->createMock($this->randomMachineName())); + } + + /** + * Return the class names and the string they return. + * + * @return array + */ + public function providerMockVersions() { + return [ + [UnitTestCasePhpunit4TestClass::class, 'PHPUnit 4'], + [UnitTestCasePhpunit4TestClassExtends::class, 'PHPUnit 4'], + [UnitTestCasePhpunit5TestClass::class, 'PHPUnit 5'], + [UnitTestCasePhpunit5TestClassExtends::class, 'PHPUnit 5'], + ]; + } + +} + +/** + * Test class for \PHPUnit\Framework\TestCase in PHPUnit 4. + */ +class Phpunit4TestClass { + public function getMock($originalClassName) { + return 'PHPUnit 4'; + } + +} + +/** + * Test class for \PHPUnit\Framework\TestCase in PHPUnit 5. + */ +class Phpunit5TestClass { + public function createMock($originalClassName) { + return 'PHPUnit 5'; + } + +} + +/** + * Test class for \Drupal\Tests\UnitTestCase with PHPUnit 4. + */ +class UnitTestCasePhpunit4TestClass extends Phpunit4TestClass { + use Phpunit5FCTrait; + +} + +/** + * Test class for \Drupal\Tests\UnitTestCase with PHPUnit 4. + */ +class UnitTestCasePhpunit4TestClassExtends extends UnitTestCasePhpunit4TestClass { +} + +/** + * Test class for \Drupal\Tests\UnitTestCase with PHPUnit 5. + */ +class UnitTestCasePhpunit5TestClass extends Phpunit5TestClass { + use Phpunit5FCTrait; + +} + +/** + * Test class for \Drupal\Tests\UnitTestCase with PHPUnit 5. + */ +class UnitTestCasePhpunit5TestClassExtends extends UnitTestCasePhpunit5TestClass { +} diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php index 24ad6801bf..b4ac0c3805 100644 --- a/core/tests/Drupal/Tests/UnitTestCase.php +++ b/core/tests/Drupal/Tests/UnitTestCase.php @@ -17,6 +17,8 @@ */ abstract class UnitTestCase extends TestCase { + use Phpunit5FCTrait; + /** * The random generator. * @@ -135,7 +137,7 @@ public function getConfigFactoryStub(array $configs = []) { } // Construct a config factory with the array of configuration object stubs // as its return map. - $config_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface'); + $config_factory = $this->createMock('Drupal\Core\Config\ConfigFactoryInterface'); $config_factory->expects($this->any()) ->method('get') ->will($this->returnValueMap($config_get_map)); @@ -157,7 +159,7 @@ public function getConfigFactoryStub(array $configs = []) { * A mocked config storage. */ public function getConfigStorageStub(array $configs) { - $config_storage = $this->getMock('Drupal\Core\Config\NullStorage'); + $config_storage = $this->createMock('Drupal\Core\Config\NullStorage'); $config_storage->expects($this->any()) ->method('listAll') ->will($this->returnValue(array_keys($configs))); @@ -211,7 +213,7 @@ protected function getBlockMockWithMachineName($machine_name) { * A mock translation object. */ public function getStringTranslationStub() { - $translation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface'); + $translation = $this->createMock('Drupal\Core\StringTranslation\TranslationInterface'); $translation->expects($this->any()) ->method('translate') ->willReturnCallback(function ($string, array $args = [], array $options = []) use ($translation) { @@ -241,7 +243,7 @@ public function getStringTranslationStub() { * The container with the cache tags invalidator service. */ protected function getContainerWithCacheTagsInvalidator(CacheTagsInvalidatorInterface $cache_tags_validator) { - $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $container = $this->createMock('Symfony\Component\DependencyInjection\ContainerInterface'); $container->expects($this->any()) ->method('get') ->with('cache_tags.invalidator') @@ -258,7 +260,7 @@ protected function getContainerWithCacheTagsInvalidator(CacheTagsInvalidatorInte * The class resolver stub. */ protected function getClassResolverStub() { - $class_resolver = $this->getMock('Drupal\Core\DependencyInjection\ClassResolverInterface'); + $class_resolver = $this->createMock('Drupal\Core\DependencyInjection\ClassResolverInterface'); $class_resolver->expects($this->any()) ->method('getInstanceFromDefinition') ->will($this->returnCallback(function ($class) { diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php index f78b69ff04..f2edbd2d97 100644 --- a/core/tests/bootstrap.php +++ b/core/tests/bootstrap.php @@ -166,3 +166,38 @@ function drupal_phpunit_populate_class_loader() { // make PHP 5 and 7 handle assertion failures the same way, but this call does // not turn runtime assertions on if they weren't on already. Handle::register(); + +// @todo Decide if we need put in some code for WebTestBase too since there are +// tests using PHPUnit_Util_XML for example. +// PHPUnit 4 to PHPUnit 6 bridge. Tests written for PHPUnit 4 need to work on +// PHPUnit 6 with a minimum of fuss. +if (!class_exists('\PHPUnit_Framework_AssertionFailedError') && class_exists('\PHPUnit\Framework\AssertionFailedError')) { + class_alias('\PHPUnit\Framework\AssertionFailedError', '\PHPUnit_Framework_AssertionFailedError'); +} +if (!class_exists('\PHPUnit_Framework_Error_Warning') && class_exists('\PHPUnit\Framework\Error\Warning')) { + class_alias('\PHPUnit\Framework\Error\Warning', '\PHPUnit_Framework_Error_Warning'); +} +if (!class_exists('\PHPUnit_Framework_Error') && class_exists('\PHPUnit\Framework\Error\Error')) { + class_alias('\PHPUnit\Framework\Error\Error', '\PHPUnit_Framework_Error'); +} +if (!class_exists('\PHPUnit_Util_Test') && class_exists('\PHPUnit\Util\Test')) { + class_alias('\PHPUnit\Util\Test', '\PHPUnit_Util_Test'); +} +if (!class_exists('\PHPUnit_Util_XML') && class_exists('\PHPUnit\Util\XML')) { + class_alias('\PHPUnit\Util\XML', '\PHPUnit_Util_XML'); +} +if (!class_exists('\PHPUnit_Framework_SkippedTestError') && class_exists('\PHPUnit\Framework\SkippedTestError')) { + class_alias('\PHPUnit\Framework\SkippedTestError', '\PHPUnit_Framework_SkippedTestError'); +} +if (!class_exists('\PHPUnit_Framework_Exception') && class_exists('\PHPUnit\Framework\Exception')) { + class_alias('\PHPUnit\Framework\Exception', '\PHPUnit_Framework_Exception'); +} +if (!class_exists('\PHPUnit_Framework_ExpectationFailedException') && class_exists('\PHPUnit\Framework\ExpectationFailedException')) { + class_alias('\PHPUnit\Framework\ExpectationFailedException', '\PHPUnit_Framework_ExpectationFailedException'); +} +if (!class_exists('\PHPUnit_Framework_Constraint_Count') && class_exists('\PHPUnit\Framework\Constraint\Count')) { + class_alias('\PHPUnit\Framework\Constraint\Count', '\PHPUnit_Framework_Constraint_Count'); +} +if (!class_exists('\PHPUnit_Framework_MockObject_Matcher_InvokedRecorder') && class_exists('\PHPUnit\Framework\MockObject\Matcher\InvokedRecorder')) { + class_alias('\PHPUnit\Framework\MockObject\Matcher\InvokedRecorder', '\PHPUnit_Framework_MockObject_Matcher_InvokedRecorder'); +}