Issue #2936802 by alexpott, Wim Leers: expectDeprecation() doesn't work in isolated tests
parent
0f34cdd433
commit
6a3ba025c4
|
@ -21,4 +21,16 @@ class ExpectDeprecationTest extends UnitTestCase {
|
||||||
@trigger_error('Test deprecation', E_USER_DEPRECATED);
|
@trigger_error('Test deprecation', E_USER_DEPRECATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::expectDeprecation
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
*/
|
||||||
|
public function testExpectDeprecationInIsolation() {
|
||||||
|
$this->expectDeprecation('Test isolated deprecation');
|
||||||
|
$this->expectDeprecation('Test isolated deprecation2');
|
||||||
|
@trigger_error('Test isolated deprecation', E_USER_DEPRECATED);
|
||||||
|
@trigger_error('Test isolated deprecation2', E_USER_DEPRECATED);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
namespace Drupal\Tests\Listeners;
|
namespace Drupal\Tests\Listeners;
|
||||||
|
|
||||||
|
use Drupal\Tests\Traits\ExpectDeprecationTrait;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes deprecations that we are yet to fix.
|
* Removes deprecations that we are yet to fix.
|
||||||
*
|
*
|
||||||
|
@ -10,6 +13,15 @@ namespace Drupal\Tests\Listeners;
|
||||||
* fixed.
|
* fixed.
|
||||||
*/
|
*/
|
||||||
trait DeprecationListenerTrait {
|
trait DeprecationListenerTrait {
|
||||||
|
use ExpectDeprecationTrait;
|
||||||
|
|
||||||
|
protected function deprecationStartTest($test) {
|
||||||
|
if ($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase) {
|
||||||
|
if ($this->willBeIsolated($test)) {
|
||||||
|
putenv('DRUPAL_EXPECTED_DEPRECATIONS_SERIALIZE=' . tempnam(sys_get_temp_dir(), 'exdep'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reacts to the end of a test.
|
* Reacts to the end of a test.
|
||||||
|
@ -21,6 +33,13 @@ trait DeprecationListenerTrait {
|
||||||
*/
|
*/
|
||||||
protected function deprecationEndTest($test, $time) {
|
protected function deprecationEndTest($test, $time) {
|
||||||
/** @var \PHPUnit\Framework\Test $test */
|
/** @var \PHPUnit\Framework\Test $test */
|
||||||
|
if ($file = getenv('DRUPAL_EXPECTED_DEPRECATIONS_SERIALIZE')) {
|
||||||
|
putenv('DRUPAL_EXPECTED_DEPRECATIONS_SERIALIZE');
|
||||||
|
$expected_deprecations = file_get_contents($file);
|
||||||
|
if ($expected_deprecations) {
|
||||||
|
$test->expectedDeprecations(unserialize($expected_deprecations));
|
||||||
|
}
|
||||||
|
}
|
||||||
if ($file = getenv('SYMFONY_DEPRECATIONS_SERIALIZE')) {
|
if ($file = getenv('SYMFONY_DEPRECATIONS_SERIALIZE')) {
|
||||||
$util_test_class = class_exists('PHPUnit_Util_Test') ? 'PHPUnit_Util_Test' : 'PHPUnit\Util\Test';
|
$util_test_class = class_exists('PHPUnit_Util_Test') ? 'PHPUnit_Util_Test' : 'PHPUnit\Util\Test';
|
||||||
$method = $test->getName(FALSE);
|
$method = $test->getName(FALSE);
|
||||||
|
@ -50,6 +69,26 @@ trait DeprecationListenerTrait {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a test is isolated.
|
||||||
|
*
|
||||||
|
* @param \PHPUnit_Framework_TestCase|\PHPUnit\Framework\TestCase $test
|
||||||
|
* The test to check.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* TRUE if the isolated, FALSE if not.
|
||||||
|
*/
|
||||||
|
private function willBeIsolated($test) {
|
||||||
|
if ($test->isInIsolation()) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = new \ReflectionProperty($test, 'runTestInSeparateProcess');
|
||||||
|
$r->setAccessible(TRUE);
|
||||||
|
|
||||||
|
return $r->getValue($test);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of deprecations to ignore whilst fixes are put in place.
|
* A list of deprecations to ignore whilst fixes are put in place.
|
||||||
*
|
*
|
||||||
|
|
|
@ -23,6 +23,13 @@ else {
|
||||||
use DrupalComponentTestListenerTrait;
|
use DrupalComponentTestListenerTrait;
|
||||||
use DrupalStandardsListenerTrait;
|
use DrupalStandardsListenerTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function startTest(Test $test) {
|
||||||
|
$this->deprecationStartTest($test);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,6 +17,13 @@ class DrupalListener extends \PHPUnit_Framework_BaseTestListener {
|
||||||
use DrupalComponentTestListenerTrait;
|
use DrupalComponentTestListenerTrait;
|
||||||
use DrupalStandardsListenerTrait;
|
use DrupalStandardsListenerTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function startTest(\PHPUnit_Framework_Test $test) {
|
||||||
|
$this->deprecationStartTest($test);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace Drupal\Tests\Traits;
|
||||||
|
|
||||||
use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListener as LegacySymfonyTestsListener;
|
use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListener as LegacySymfonyTestsListener;
|
||||||
use Symfony\Bridge\PhpUnit\SymfonyTestsListener;
|
use Symfony\Bridge\PhpUnit\SymfonyTestsListener;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the ability to dynamically set expected deprecation messages in tests.
|
* Adds the ability to dynamically set expected deprecation messages in tests.
|
||||||
|
@ -19,11 +20,20 @@ trait ExpectDeprecationTrait {
|
||||||
/**
|
/**
|
||||||
* Sets an expected deprecation message.
|
* Sets an expected deprecation message.
|
||||||
*
|
*
|
||||||
* @param string $msg
|
* @param string $message
|
||||||
* The expected deprecation message.
|
* The expected deprecation message.
|
||||||
*/
|
*/
|
||||||
protected function expectDeprecation($msg) {
|
protected function expectDeprecation($message) {
|
||||||
// Ensure the class or method is in the legacy group.
|
$this->expectedDeprecations([$message]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets expected deprecation messages.
|
||||||
|
*
|
||||||
|
* @param string[] $messages
|
||||||
|
* The expected deprecation messages.
|
||||||
|
*/
|
||||||
|
public function expectedDeprecations(array $messages) {
|
||||||
if (class_exists('PHPUnit_Util_Test', FALSE)) {
|
if (class_exists('PHPUnit_Util_Test', FALSE)) {
|
||||||
$test_util = 'PHPUnit_Util_Test';
|
$test_util = 'PHPUnit_Util_Test';
|
||||||
$assertion_failed_error = 'PHPUnit_Framework_AssertionFailedError';
|
$assertion_failed_error = 'PHPUnit_Framework_AssertionFailedError';
|
||||||
|
@ -32,36 +42,54 @@ trait ExpectDeprecationTrait {
|
||||||
$test_util = 'PHPUnit\Util\Test';
|
$test_util = 'PHPUnit\Util\Test';
|
||||||
$assertion_failed_error = 'PHPUnit\Framework\AssertionFailedError';
|
$assertion_failed_error = 'PHPUnit\Framework\AssertionFailedError';
|
||||||
}
|
}
|
||||||
$groups = $test_util::getGroups(get_class($this), $this->getName(FALSE));
|
if ($this instanceof \PHPUnit_Framework_TestCase || $this instanceof TestCase) {
|
||||||
if (!in_array('legacy', $groups, TRUE)) {
|
// Ensure the class or method is in the legacy group.
|
||||||
throw new $assertion_failed_error('Only tests with the `@group legacy` annotation can call `setExpectedDeprecation()`.');
|
$groups = $test_util::getGroups(get_class($this), $this->getName(FALSE));
|
||||||
}
|
if (!in_array('legacy', $groups, TRUE)) {
|
||||||
|
throw new $assertion_failed_error('Only tests with the `@group legacy` annotation can call `setExpectedDeprecation()`.');
|
||||||
|
}
|
||||||
|
|
||||||
if ($trait = $this->getSymfonyTestListenerTrait()) {
|
|
||||||
// If setting an expected deprecation there is no need to be strict about
|
// If setting an expected deprecation there is no need to be strict about
|
||||||
// testing nothing as this is an assertion.
|
// testing nothing as this is an assertion.
|
||||||
$this->getTestResultObject()->beStrictAboutTestsThatDoNotTestAnything(FALSE);
|
$this->getTestResultObject()
|
||||||
|
->beStrictAboutTestsThatDoNotTestAnything(FALSE);
|
||||||
|
|
||||||
// Add the expected deprecation message to the class property.
|
if ($trait = $this->getSymfonyTestListenerTrait()) {
|
||||||
$reflection_class = new \ReflectionClass($trait);
|
// Add the expected deprecation message to the class property.
|
||||||
$expected_deprecations_property = $reflection_class->getProperty('expectedDeprecations');
|
$reflection_class = new \ReflectionClass($trait);
|
||||||
$expected_deprecations_property->setAccessible(TRUE);
|
$expected_deprecations_property = $reflection_class->getProperty('expectedDeprecations');
|
||||||
$expected_deprecations = $expected_deprecations_property->getValue($trait);
|
$expected_deprecations_property->setAccessible(TRUE);
|
||||||
$expected_deprecations[] = $msg;
|
$expected_deprecations = $expected_deprecations_property->getValue($trait);
|
||||||
$expected_deprecations_property->setValue($trait, $expected_deprecations);
|
$expected_deprecations = array_merge($expected_deprecations, $messages);
|
||||||
|
$expected_deprecations_property->setValue($trait, $expected_deprecations);
|
||||||
|
|
||||||
// Register the error handler if necessary.
|
// Register the error handler if necessary.
|
||||||
$previous_error_handler_property = $reflection_class->getProperty('previousErrorHandler');
|
$previous_error_handler_property = $reflection_class->getProperty('previousErrorHandler');
|
||||||
$previous_error_handler_property->setAccessible(TRUE);
|
$previous_error_handler_property->setAccessible(TRUE);
|
||||||
$previous_error_handler = $previous_error_handler_property->getValue($trait);
|
$previous_error_handler = $previous_error_handler_property->getValue($trait);
|
||||||
if (!$previous_error_handler) {
|
if (!$previous_error_handler) {
|
||||||
$previous_error_handler = set_error_handler([$trait, 'handleError']);
|
$previous_error_handler = set_error_handler([$trait, 'handleError']);
|
||||||
$previous_error_handler_property->setValue($trait, $previous_error_handler);
|
$previous_error_handler_property->setValue($trait, $previous_error_handler);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
throw new $assertion_failed_error('Can not set an expected deprecation message because the Symfony\Bridge\PhpUnit\SymfonyTestsListener is not registered as a PHPUnit test listener.');
|
// Expected deprecations set by isolated tests need to be written to a file
|
||||||
|
// so that the test running process can take account of them.
|
||||||
|
if ($file = getenv('DRUPAL_EXPECTED_DEPRECATIONS_SERIALIZE')) {
|
||||||
|
$expected_deprecations = file_get_contents($file);
|
||||||
|
if ($expected_deprecations) {
|
||||||
|
$expected_deprecations = array_merge(unserialize($expected_deprecations), $messages);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$expected_deprecations = $messages;
|
||||||
|
}
|
||||||
|
file_put_contents($file, serialize($expected_deprecations));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new $assertion_failed_error('Can not set an expected deprecation message because the Symfony\Bridge\PhpUnit\SymfonyTestsListener is not registered as a PHPUnit test listener.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue