Follow-up to #2488860: Bring phpunit bridge into drupal and use it for unit tests and simpletest to handle Deprecation

Problem/Motivation

#2488860: Bring phpunit bridge into drupal and use it for unit tests and simpletest to handle Deprecation adds supports for using @trigger_error(E_USER_DEPRECATED) to find usages of deprecated code in tests, with the symfony/phpunit-bridge package.

Unfortunately, symfony/phpunit-bridge has been unable to account for deprecation errors like this in tests which PHPUnit runs in a separate process.

That includes our BrowserTestBase and JavascriptTestBase tests, as well as any other PHPUnit-based test with @runTestsInSeparateProcess.

There are a few upstream issues and PRs for Symfony about this: https://github.com/symfony/symfony/issues/23003

Eventually this limitation of phpunit-bridge has been removed in https://github.com/symfony/symfony/pull/24548 and now gives us the ability to see these types of deprecation errors.

Proposed resolution

  • Target a 3.4.0 version of symfony/phpunit-bridge in core/composer.json (not released yet)
  • Fix our error handlers so they don't swallow E_USER_DEPRECATED
  • Ignore currently fired deprecations and file followups to remove each ignored deprecation. These followups need to remove the deprecation from the ignore list and either fix run-time to not call the call or add @group legacy to the test.

Remaining tasks

Determine whether TestBase/WebTestBase should respond to deprecation errors, #2904566: Allow TestBase to optionally notify/fail @trigger_error() deprecations, amend run-tests.sh. Current patch in #90 does because it was too easy to do it since we are using _drupal_error_handler_real to emit headers for the test process to discover if any deprecations have occurred.

How to test the patch

  1. Apply patch
  2. Run composer install to update PHPUnit Bridge
  3. Make sure any modifications to the test listeners that are in core/phpunit.xml.dist are in core/phpunit.xml (if you have a local customised file). You need both \Drupal\Tests\Listeners\DeprecationListener and Symfony\Bridge\PhpUnit\SymfonyTestsListener.
  4. If you want to see what it looks like without suppressing our many notices change \Drupal\Tests\Listeners\DeprecationListener::getSkippedDeprecations() to return an empty array and run Drupal\Tests\comment\Kernel\Plugin\migrate\source\d7\CommentTypeTest

User interface changes

None

API changes

None - a new test listener is added but it is marked as @internal

Issue summary update

Updates to make to https://www.drupal.org/node/2811561 once this is committed.

  • Add that Drupal\Tests\Listeners\DeprecationListener needs to be added to any custom phpunit.xml
  • Add section on suppressing errors - note the SYMFONY_DEPRECATIONS_HELPER global in phpunit.xml.dist and run-tests.sh's new option of --suppress-deprecations
  • Unpublish and publish so that additions are picked up by bots following CRs
CommentFileSizeAuthor
#131 2870194-4-131.patch36.38 KBalexpott
#131 124-131-interdiff.txt1.29 KBalexpott
#124 2870194-4-124.patch36.08 KBalexpott
#124 121-124-interdiff.txt1.01 KBalexpott
#121 2870194-4-121.patch35.07 KBalexpott
#121 115-121-interdiff.txt823 bytesalexpott
#115 2870194-4-115.patch34.86 KBalexpott
#115 111-115-interdiff.txt5.15 KBalexpott
#111 2870194-4-111.patch38.2 KBalexpott
#111 2870194-4-test-only.111.patch38.22 KBalexpott
#111 108-111-interdiff.txt7.24 KBalexpott
#108 2870194-4-107.patch35.69 KBalexpott
#108 106-107-interdiff.txt448 bytesalexpott
#107 2870194-4-106.patch35.69 KBalexpott
#107 97-106-interdiff.txt3 KBalexpott
#97 2870194-4-97.patch33.54 KBalexpott
#97 93-97-interdiff.txt1.58 KBalexpott
#93 2870194-4-93.patch33.37 KBalexpott
#93 90-93-interdiff.txt29.9 KBalexpott
#90 2870194-4-90.patch35.17 KBalexpott
#90 89-90-interdiff.txt1.37 KBalexpott
#89 2870194-4-89.patch35 KBalexpott
#89 87-89-interdiff.txt14.66 KBalexpott
#87 2870194-4-87.patch21.37 KBalexpott
#87 76-87-interdiff.txt8.36 KBalexpott
#76 2870194-4-76.patch16.93 KBalexpott
#74 ensure_that-2870194-74.patch21.94 KBjibran
#74 interdiff-aba174.txt822 bytesjibran
#69 ensure_that-2870194-69.patch21.99 KBjibran
#69 interdiff-2473dd.txt1.62 KBjibran
#68 ensure_that-2870194-68.patch21.53 KBjibran
#68 interdiff-426d54.txt1.2 KBjibran
#66 2870194-3-66.patch20.33 KBalexpott
#66 60-66-interdiff.txt1 KBalexpott
#60 ensure_that-2870194-60.patch19.33 KBjibran
#60 interdiff-d642ca.txt596 bytesjibran
#58 2870194-3-58.patch18.75 KBalexpott
#58 54-57-interdiff.txt899 bytesalexpott
#54 ensure_that-2870194-54.patch17.87 KBjibran
#54 interdiff-6c7b36.txt6.91 KBjibran
#51 2870194-deprecation-51.patch10.96 KBtim.plunkett
#51 2870194-deprecation-51-interdiff.txt2.23 KBtim.plunkett
#46 2870194-2-46.patch11.17 KBalexpott
#46 31-46-interdiff.txt3.22 KBalexpott
#40 interdiff.txt4.33 KBmile23
#40 2870194_39.patch9.05 KBmile23
#31 interdiff.txt11.25 KBmile23
#31 2870194_31.patch23.34 KBmile23
#27 interdiff.txt1.85 KBmile23
#27 2870194_26.patch13.32 KBmile23
#24 2870194_24.patch13.34 KBmile23
#22 interdiff.txt8.24 KBmile23
#22 2870194_22.patch13.35 KBmile23
#19 interdiff.txt941 bytesmile23
#19 2870194_19.patch6.17 KBmile23
#16 2870194_16.patch5.25 KBmile23
#10 2870194-10.patch4.61 KBalexpott
#4 2870194-bubble-deprecated.4.patch3.45 KBlarowlan
#4 interdiff.txt1.98 KBlarowlan

Comments

alexpott created an issue. See original summary.

alexpott’s picture

@mile23 posted a test in the other issue https://www.drupal.org/files/issues/2488860_functional_do_not_test.patch
This test tests deprecations in the test runner but we also need to test that we can catch deprecations in the site under test.

dawehner’s picture

Should we also be able to detect calls inside the running Drupal site?

larowlan’s picture

Status: Active » Needs review
StatusFileSize
new1.98 KB
new3.45 KB

We bubble errors up to the runner from the site under test.

See \Drupal\Core\Test\HttpClientMiddleware\TestHttpClientMiddleware.

Added to @Mile23's test, I think the first test method should be a kernel test, but that's for another day.

alexpott’s picture

Unfortunately neither of these tests seem to work with #2488860: Bring phpunit bridge into drupal and use it for unit tests and simpletest to handle Deprecation applied and the expectedDeprecation and @group legacy removed. I'm guessing this is because we play around with error handlers and shutdown functions in the parent site and I'm pretty sure we're going to need sometime in the site under test to unsilence the deprecation notices.

larowlan’s picture

Yeah I was expecting that to fail, or at least be marked as risky. Either my local phpunit.xml must be different or something in BTB::setUp is creating an assert and bypassing the risky tests check.

mile23’s picture

It doesn't help that I now get this error for every functional test, not just PhpUnitBridgeTest, even without the patch from #2488860: Bring phpunit bridge into drupal and use it for unit tests and simpletest to handle Deprecation

1) Drupal\FunctionalTests\Core\Test\PhpUnitBridgeTest::testSilencedError
GuzzleHttp\Exception\ConnectException: cURL error 7: Failed to connect to localhost port 80: Connection refused (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

Note to guzzle: MAMP is on port 8888, like it says in SIMPLETEST_URL.

Can't find an issue about it. Also want to file an issue for the testbot to randomize port numbers. :-)

User error. :-)

dawehner’s picture

@mile23
I think opening its own issue is the right thing to do :) I bet we can figure out a solution for the problem.

Inside \PHPUnit_Util_ErrorHandler::handleError we stop in the first if condition:

    public static function handleError($errno, $errstr, $errfile, $errline)
    {
        if (!($errno & error_reporting())) {
            return false;
        }

... The question is, why is the phpunit error handler executed. Debugging resulted for me to have the following code executed inside

\PHPUnit_Framework_TestResult::run

:


        if ($this->convertErrorsToExceptions) {
            $oldErrorHandler = set_error_handler(
                array('PHPUnit_Util_ErrorHandler', 'handleError'),
                E_ALL | E_STRICT
            );

            if ($oldErrorHandler === null) {
                $errorHandlerSet = true;
            } else {
                restore_error_handler();
            }
        }

I tracked down the problem, I believe. In the child process \PHPUnit_Framework_TestResult::run is used to execute the test.

In there we have two problems:

  1.         if ($this->convertErrorsToExceptions) {
                $oldErrorHandler = set_error_handler(
                    array('PHPUnit_Util_ErrorHandler', 'handleError'),
                    E_ALL | E_STRICT
                );
    
                if ($oldErrorHandler === null) {
                    $errorHandlerSet = true;
                } else {
                    restore_error_handler();
                }
            }
    

    is executed AFTER $this->startTest($test); and so overrides the symfony error handler

  2. Let's assume we swap those two around, the next problem is that $this->listeners in there is empty.

Does anyone else has some further observations?

mile23’s picture

Hmm. Interesting results from the test in #2488860-56: Bring phpunit bridge into drupal and use it for unit tests and simpletest to handle Deprecation

$ SIMPLETEST_BASE_URL=http://localhost:8888/ ./vendor/bin/phpunit -c core/ --stop-on-error --testsuite functional --filter PhpUnitBridgeTest
PHPUnit 4.8.35 by Sebastian Bergmann and contributors.

Testing 
F

Time: 26.47 seconds, Memory: 28.00MB

There was 1 failure:

1) Drupal\FunctionalTests\Core\Test\PhpUnitBridgeTest::testSilencedError
Failed asserting that format description matches text.
--- Expected
+++ Actual
@@ @@
 @expectedDeprecation:
-%A  This is the deprecation message for deprecated_test_function().
+

/Users/paul/pj2/drupal/vendor/symfony/phpunit-bridge/SymfonyTestsListener.php:198

FAILURES!
Tests: 1, Assertions: 3, Failures: 1.

Remaining deprecation notices (1)

\Drupal\views\Tests\ViewTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\views\Functional\ViewTestBase: 1x
    1x in FunctionalTestSuite::suite from Drupal\Tests\TestSuites

So here's the problem:

During test time, we don't allow autoloading of \Drupal\Tests\views\etc but we *do* allow autoloading of \Drupal\Views\Tests\etc. We have to do this because a) history, and b) we use phpunit-based tests to test Simpletest base classes and traits.

So using phpunit --filter means that all tests are loaded and parsed, which loads, for instance, Drupal\Tests\views\Functional\DefaultViewsTest and all of the other views functional tests. Because this test is alongside Drupal\Tests\views\Functional\ViewTestBase in the filesystem, it doesn't have a use statement (that's our coding standard). And even if it did, it still wouldn't autoload.

Since the base class ends in *Base.php, phpunit never finds it to include, so it's not going to be found when a class uses it. PHP is left saying this: 'ViewTestBase? Oh yeah, I know that one... it's Drupal\views\Tests\ViewTestBase!' Then we get the @trigger_error().

In an ideal world, we'd move all simpletest tests to another directory like MODULE_NAME/tests/simpletest_src/ or something and be happy. But we don't live in that world. :-)

We could also require use statements for all classes in tests, so there's no ambiguity. Er, never mind. Still wouldn't autoload correctly, and we'd end up with the simpletest base class in this case.

And we could make a special namespace that's always autoloaded, like \Drupal\Tests\module\SuiteName\Base\ and move all base classes into them.

This is all based on this change: #2863267: Convert web tests of views

alexpott’s picture

StatusFileSize
new4.61 KB

Yesterday I discovered that KernelTests aren't finding deprecations because of running tests in a separate process. So we need to bubble up in phpunit too!

See patch and run...

phpunit -c ./core core/tests/Drupal/KernelTests/Core/Test/DeprecationTest.php

I've debugged it and the listener is being added to the test and even adding the error handler is not enough :(

Status: Needs review » Needs work

The last submitted patch, 10: 2870194-10.patch, failed testing.

mile23’s picture

As per IRC chat, I've updated the deprecation policy: https://www.drupal.org/core/deprecation#how-test-base-class

And here's an issue to untangle ViewTestBase: #2876145: ConfigTranslationViewListUiTest is a WTB test in the Functional namespace

mile23’s picture

Ok, so we didn't need to change deprecation policy, because it was just a bad test.

Re #10: The culprit is KernelTestBase::runTestInSeparateProcess. This signals \PHPUnit_Framework_TestCase to exec() another phpunit process. But the way it does it is interesting:

It takes a number of values and pokes them into a template file. The template is then the process that's run by the exec(), and it executes the test.

We also get the handy-dandy \PHPUnit_Framework_TestCase::prepareTemplate(), which is a hook pattern immediately recognizable to any Drupal dev. :-) This lets us put whatever values we want into the template, and also lets us change the template.

The template: https://github.com/sebastianbergmann/phpunit/blob/master/src/Util/PHP/Te...

I couldn't find where anyone had run into this problem in the symfony issues, so it might be an upstream fix.

mile23’s picture

mile23’s picture

mile23’s picture

Title: Ensure that browsertestbase tests can use Symfony's PHPunit bridge to catch usages of deprecated code » Ensure that kernel, functional tests can use Symfony's PHPunit bridge to catch usages of deprecated code
Status: Needs work » Needs review
StatusFileSize
new5.25 KB

A patch of tests to prove that deprecation errors aren't bubbling up from kernel or functional tests.

Status: Needs review » Needs work

The last submitted patch, 16: 2870194_16.patch, failed testing.

mile23’s picture

Title: Ensure that kernel, functional tests can use Symfony's PHPunit bridge to catch usages of deprecated code » Ensure that process-isolated tests can use Symfony's PHPunit bridge to catch usages of deprecated code

It turns out this problem applies to any test with process isolation, such as annotation with @runTestsInSeparateProcesses.

mile23’s picture

Category: Task » Bug report
StatusFileSize
new6.17 KB
new941 bytes

And the test to prove it. :-)

Calling this a bug because we really can't rely on deprecation for much unless this is fixed. I think it's fair to say the solution will lie upstream.

mile23’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 19: 2870194_19.patch, failed testing.

mile23’s picture

Status: Needs work » Needs review
StatusFileSize
new13.35 KB
new8.24 KB

This is a patch that solves the problem of being able to test for deprecation errors in process-isolated tests.

It does not solve the problem of having deprecation errors in process-isolated tests fail tests that use deprecated code.

The reason @expectedDeprecation annotation didn't work is as follows:

Process-isolated tests end up sending a duplicate set of events to listeners. The first is the non-isolated one, and the second is isolated in a separate process.

The 'outside' non-isolated tests end up setting an expectation that fails, because the test never ends up being run (from the perspective of this 'outside' listener).

We solve this by subclassing SymfonyTestsListener and forcing it to not pay attention to tests which will eventually be run in isolation. Then we modify phpunit.xml.dist to use our new listener, and we also add a new isolated test template which adds this listener to the isolated test run.

So yay, we can at least test for deprecation errors. See, for instance, the results of Drupal\KernelTests\Core\Test\PhpUnitBridgeTest::testDeprecatedClass. :-)

The reason deprecation errors don't fail tests is as follows:

We silence the errors with @trigger_error().

Symfony\Bridge\PhpUnit\DeprecationErrorHandler is supposed to surface those errors under certain circumstances.

DeprecationErrorHandler does this by 1) Gathering them up in the error handler object. 2) Telling you about them in a shutdown function. 3) Calling exit(1) if there were errors.

That's all fine and dandy, except that as part of process isolation, PHPUnit ignores the result code from the executed process. So the deprecation error handler does its job, but PHPUnit pretends it didn't.

I couldn't find any upstream issues about either of these problems, so here we have a patch and a comment.

Status: Needs review » Needs work

The last submitted patch, 22: 2870194_22.patch, failed testing.

mile23’s picture

Status: Needs work » Needs review
StatusFileSize
new13.34 KB

Status: Needs review » Needs work

The last submitted patch, 24: 2870194_24.patch, failed testing.

dawehner’s picture

Amazing work! I don't have the mental power to review this patch, but heads up for actually trying to solve it!

mile23’s picture

Status: Needs work » Needs review
StatusFileSize
new13.32 KB
new1.85 KB

Aaaaaand the testbot linter doesn't like files named *.tpl.php. Imagine that.

Status: Needs review » Needs work

The last submitted patch, 27: 2870194_26.patch, failed testing.

mile23’s picture

mile23’s picture

Well you can apply the patch and see the results with this command:

SIMPLETEST_BASE_URL=[your url here] SIMPLETEST_DB=[your db here] ./vendor/bin/phpunit -c core/ --group Test

Note that if you change any of the expected deprecation error messages in any of the isolated tests, you'll get a fail. But if you take off the @group legacy and the @expectedDeprecation tags, you'll get a pass even though it should fail due to E_USER_DEPRECATION error.

Currently we fail in two places:

There were 2 failures:

1) Drupal\KernelTests\Core\Test\PhpUnitBridgeTest::testDeprecatedClass
Failed asserting that format description matches text.
--- Expected
+++ Actual
@@ @@
 @expectedDeprecation:
-%A  Drupal\deprecation_test\FixtureDeprecatedClass is deprecated.
+  Install profile will be a mandatory parameter in Drupal 9.0.
   Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass is deprecated.
+

/Users/paul/pj2/drupal/vendor/symfony/phpunit-bridge/SymfonyTestsListener.php:198
/Users/paul/pj2/drupal/core/tests/Drupal/Tests/Listeners/DrupalPhpUnitBridgeListener.php:34

2) Drupal\FunctionalTests\Core\Test\PhpUnitBridgeTest::testErrorOnSiteUnderTest
Failed asserting that format description matches text.
--- Expected
+++ Actual
@@ @@
 @expectedDeprecation:
-%A  This is the deprecation message for deprecation_test_function().
+

/Users/paul/pj2/drupal/vendor/symfony/phpunit-bridge/SymfonyTestsListener.php:198
/Users/paul/pj2/drupal/core/tests/Drupal/Tests/Listeners/DrupalPhpUnitBridgeListener.php:34

#1 shows two deprecations, one as a result of #2156401: Write install_profile value to configuration and only to settings.php if it is writeable which has a less-than-helpful deprecation message.

#2 shows that page controllers absorb some error messages we need to address.

mile23’s picture

Status: Needs work » Needs review
StatusFileSize
new23.34 KB
new11.25 KB

I give you: The Drupal fork of symfony/phpunit-bridge. :-)

I'll refer to this patch in an upstream issue.

The test run here will fail because the testbot still doesn't know how to lint a template file that starts with <?php.

This patch gives us the ability to fail tests with @trigger_error() in process isolation. It does this by 'hacking core' of symfony/phpunit-bridge, so we'll work on an upstream change.

If you apply the patch and run it, you still get a fail from Drupal\FunctionalTests\Core\Test\PhpUnitBridgeTest, which signals that somewhere within the functional tests, we're swallowing E_USER_DEPRECATED. That's the next thing to solve.

This patch comments out the @trigger_error() deprecation from ExtensionInstallStorage::__construct() because it fails every test that builds a container. Bad core, bad!

The best way to demo this is the same as the last patch:

SIMPLETEST_BASE_URL=[your url here] SIMPLETEST_DB=[your db here] ./vendor/bin/phpunit -c core/ --group Test

Then edit Drupal\KernelTests\Core\Test\PhpUnitBridgeTest to remove the @group legacy line and also the @expectedDeprecation lines. Then re-run the same test command from above. This shows you a process-isolated deprecation fail.

Status: Needs review » Needs work

The last submitted patch, 31: 2870194_31.patch, failed testing.

mile23’s picture

mile23’s picture

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mile23’s picture

mile23’s picture

Some incremental forward motion at https://github.com/symfony/symfony/issues/23003

Unfortunately it's a fix in 3.3, which we can't use #2882826: Constrain symfony/phpunit-bridge to 3.2.*

mile23’s picture

phpunit-bridge now has does the process-isolated dance: https://github.com/symfony/symfony/pull/24548/commits/ff379efb59de25bcdb...

alexpott’s picture

So do we need to update the phpunit-bridge once that commit is tagged in a release? I think we can since the concern of #2882826: Constrain symfony/phpunit-bridge to 3.2.* turns out not be an issue.

mile23’s picture

Status: Needs work » Needs review
StatusFileSize
new9.05 KB
new4.33 KB

Still a WIP.

This patch modifies #19 to update symfony/phpunit-bridge to dev-master, which we really don't want. :-) We should change to >3.3.10 eventually.

The only fail from this patch is Drupal\FunctionalTests\Core\Test\PhpUnitBridgeTest::testErrorOnSiteUnderTest() which tests whether a deprecation surfaces from drupalGet(Url::fromRoute('deprecation_test.route')); (it doesn't).

We might consider putting this into 8.4.x when it's all done.

alexpott’s picture

@Mile23 nice one! So close to having this done :) And we've helped make Symfony better in the process.

alexpott’s picture

Drupal\FunctionalTests\Core\Test\PhpUnitBridgeTest::testErrorOnSiteUnderTest() is super tricky because the deprecation is occurring on site under test - so we're going to need to surface that somehow.

mile23’s picture

So yah, basically the remainder of this issue is finding ways to test whether our error handler(s) swallows deprecation errors.

Status: Needs review » Needs work

The last submitted patch, 40: 2870194_39.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

alexpott’s picture

We're going to need to change our error handler - it totally swallows them.
if ($error_level & error_reporting()) {
error_reporting() will always return 0 when the error is silenced via @

alexpott’s picture

StatusFileSize
new3.22 KB
new11.17 KB

Here's an approach that seems to work.

mile23’s picture

Status: Needs work » Needs review

Let's see how many deprecation errors are hidden... :-)

Status: Needs review » Needs work

The last submitted patch, 46: 2870194-2-46.patch, failed testing. View results

mile23’s picture

Yup. Pretty terrifying.

So we have to deal with deprecations in symfony and twig and probably others, as well as Drupal core before we can add this.

It'd be great to have a way to filter them, so that we could say: Only show the deprecations in twig or whatever.

Or perhaps a way to just turn on the handler in code, so that you could submit a patch that performs changes due to deprecation, and also turns on the deprecation reporting. Then when we're done, we can remove the code that does the switch for permanent fail due to deprecation.

jibran’s picture

+++ b/core/composer.json
@@ -18,7 +18,7 @@
-        "twig/twig": "^1.35.0",
+        "twig/twig": "^1.23.1",

This is an unwanted change.

tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new2.23 KB
new10.96 KB

Reeeally curious to see what is actually failing other than the 10 bajillion things about ArgumentsResolver.
Also fixed the stray Twig change called out in #50, but that didn't make the interdiff.

mile23’s picture

Issue summary: View changes

Re: #50

Sorry about that. Must have been a branch mixup.

Status: Needs review » Needs work

The last submitted patch, 51: 2870194-deprecation-51.patch, failed testing. View results

jibran’s picture

Status: Needs work » Needs review
StatusFileSize
new6.91 KB
new17.87 KB

Status: Needs review » Needs work

The last submitted patch, 54: ensure_that-2870194-54.patch, failed testing. View results

alexpott’s picture

Look at all that technical debt being uncovered - this is pretty cool.

alexpott’s picture

Install profile will be a mandatory parameter in Drupal 9.0.
That's going to be hard to fix. This is happening in super early installer before a profile is chosen when we render the profile select page. To do this we need the theme.manager -> theme.negiotator -> access_check.theme -> theme_handler -> config.factory -> config.typed -> config.storage.schema.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new899 bytes
new18.75 KB

Hard but not impossible :) we can just swap out config schema storage in the very early installer becauseI think it is just not relevant.

Status: Needs review » Needs work

The last submitted patch, 58: 2870194-3-58.patch, failed testing. View results

jibran’s picture

Status: Needs work » Needs review
StatusFileSize
new596 bytes
new19.33 KB

Here is another quick win.

alexpott’s picture

+++ b/core/modules/system/tests/modules/system_test/system_test.routing.yml
@@ -194,5 +194,7 @@ system_test.echo_utf8:
+  options:
+    utf8: 'TRUE'

I think we fixed it so that our router always supports UTF-8 routes so having to add this seems unnecessary. Maybe we should always set this to true for all routes?

jibran’s picture

\Symfony\Component\Routing\RouteCompiler::compilePattern throws LogicException if non utf8 path sets the utf8 to TRUE.

alexpott’s picture

@jibran then maybe we should detect UTF-8 and set it automatically.

+++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/AllowedValuesConstraint.php
@@ -16,6 +16,7 @@
+  public $strict = TRUE;

This is causing test failures. For example Drupal\Tests\content_translation\Functional\ContentTranslationLanguageChangeTest the validator on the published field when in strict mode is failing.

Status: Needs review » Needs work

The last submitted patch, 60: ensure_that-2870194-60.patch, failed testing. View results

jibran’s picture

@alexpott ok, but I think if we want BC compatible solution then we should create sub-issues all these changes are out of the scope for this issue imo.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new1 KB
new20.33 KB

@jibran it's tricky - this issue is obviously going to expose existing technical debt. I agree though that each runtime change should have it's own issue. It's going to take a while but each change will be better reviewed. There's also no harm continuing here to work out all the necessary fixes.

Here's a fix for the AllowedValuesConstraint change.

Status: Needs review » Needs work

The last submitted patch, 66: 2870194-3-66.patch, failed testing. View results

jibran’s picture

Status: Needs work » Needs review
StatusFileSize
new1.2 KB
new21.53 KB

Fixes for

exception: [User deprecated function] Line 48 of core/modules/editor/src/Plugin/EditorBase.php:
The Drupal\editor\Plugin\EditorBase::settingsFormValidate method is deprecated since version 8.3.x and will be removed in 9.0.0.

and

exception: [User deprecated function] Line 57 of core/modules/editor/src/Plugin/EditorBase.php:
The Drupal\editor\Plugin\EditorBase::settingsFormSubmit method is deprecated since version 8.3.x and will be removed in 9.0.0.
jibran’s picture

StatusFileSize
new1.62 KB
new21.99 KB

@jibran then maybe we should detect UTF-8 and set it automatically.

How about this?

The last submitted patch, 68: ensure_that-2870194-68.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 69: ensure_that-2870194-69.patch, failed testing. View results

mile23’s picture

If you scroll down to the bottom of the last set of results, you'll see deprecation errors in Simpletest.Drupal\simpletest\Tests\SimpleTestTest. They occur because the deprecated traits are loaded during discovery, and trigger deprecation errors after their namespace.

These deprecations occur because SimpleTestTest uses TestDiscovery to find and run tests.

For instance, in SimpleTestTest::testWebTestRunner() we load the test runner form, via $this->drupalGet('admin/config/development/testing'). This in turn calls TestDiscovery::getTestClasses().

TestDiscovery::getTestClasses() uses reflection to gather information about the files it finds, including traits because the traits live within the namespaces of the other test files.

Since it's using reflection, the deprecated trait files are require'd, so their deprecation errors are triggered, and you see errors like this:

exception: [User deprecated function] Line 5 of core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php:
Drupal\taxonomy\Tests\TaxonomyTranslationTestTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\taxonomy\Functional\TaxonomyTranslationTestTrait

Even if you replace all usages of TaxonomyTranslationTestTrait with the non-deprecated one, you'll still see this exception, because it occurs during discovery.

If we were to limit discovery to *Test.php files, then we would never include the traits in our classmap, so they would never be autoloadable. Because that's how TestDiscovery works. :-)

dawehner’s picture

The reason why the rest tests fails is the following:

In HEAD when bc_primitives_as_strings is enabled, we basically return the data as it is set on the entity object. In the normal cases its coming from the database, and as such its returned as string.
This patch enforces that boolean objects always contain integers, no matter what.
If you are 100% honest this problem is not specific to boolean items though. If you are honest any value stored in any field might be used with the AllowedValue field and as such potentially problematic.

At least for me it feels like having a way to disable some deprecation notices instead of all or nothing, might be a good idea.

jibran’s picture

Status: Needs work » Needs review
StatusFileSize
new822 bytes
new21.94 KB

This should fix utf8 warnings.

Status: Needs review » Needs work

The last submitted patch, 74: ensure_that-2870194-74.patch, failed testing. View results

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new16.93 KB

So whilst trying to work out all the issues this uncovers I've noticed that we're also emitting errors for WebTestBase tests. I don't think we should support deprecation find in those tests - only the new BrowserTestBase because the whole infrastructure for managing them depends on PHPUnit.

Also to get this in so we don't accumulate new tech debt like we have I think we should exclude the current notices and then file issues to fix them.

Here's a start on the list. No interdiff because kinda a new way around of doing this.

Status: Needs review » Needs work

The last submitted patch, 76: 2870194-4-76.patch, failed testing. View results

mile23’s picture

Generally agree that WTB shouldn't be how you discover deprecations. But we do have #2904566: Allow TestBase to optionally notify/fail @trigger_error() deprecations, amend run-tests.sh with a patch. :-)

We really do need to explore one other thing... The PR that fixes phpunit-bridge also modifies symfony/browser-kit, which we use via mink for functional[javascript] tests.

I couldn't figure out how to specify browser-kit ^3.3.10@dev (I didn't try very hard, but dev-master is 4.* and requires PHP 7), but we'll eventually pull it in anyway. So we should incorporate whatever changes are there by explicitly requiring it.

https://github.com/symfony/symfony/pull/24548

alexpott’s picture

@Mile23 we don't actually need to do the browserkit change because we can't add the error handler to the site under test - and we're changing our error handler and test system to do the same thing in the patches above. We also need to fix https://github.com/symfony/symfony/issues/24567 to get better info from the isolated tests.

mile23’s picture

+++ b/core/lib/Drupal/Core/Test/HttpClientMiddleware/TestHttpClientMiddleware.php
@@ -11,6 +11,12 @@
+  protected $skippedDeprecations = [
+    'As of 3.1 an Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface is used to resolve arguments. In 4.0 the $argumentResolver becomes the Symfony\Component\HttpKernel\Controller\ArgumentResolver if no other is provided instead of using the $resolver argument.',
+    'Symfony\Component\HttpKernel\Controller\ControllerResolver::getArguments is deprecated as of 3.1 and will be removed in 4.0. Implement the Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface and inject it in the HttpKernel instead.',
+    'The Twig_Node::getLine method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateLine() instead.',
+  ];
+

@@ -41,7 +47,17 @@ public function __invoke() {
+                      if (!in_array($message, $this->skippedDeprecations)) {

Could we work on a filter where we search the backtrace for a given namespace? We could have an env variable like PHPUNIT_BRIDGE_EXCLUDE=Symfony\Component\HttpKernel\

That would help us know when to swallow deprecation errors for WebTestBase as well.

This would be the inverse of setting SYMFONY_DEPRECATIONS_HELPER to a regex.

alexpott’s picture

@Mile23 maybe we'd need to move the filter then to the error handler. One problem is that we've got two different error handlers at play. In the test process under PHPUnit we have \Symfony\Bridge\PhpUnit\DeprecationErrorHandler() in the site under test we have Drupal's error handling system. The current patch is filtering where we trap the errors from the site under test and re-trigger them. So many layers :)

Also what the patches show is that WebTestBase tests are the ones exercising the majority of the deprecated code so if we want to uncover everything we need to add deprecation handling to them.

dawehner’s picture

Note: We have an issue for the http kernel already on #2912169: Inject the argument resolver into HttpKernel::__construct

alexpott’s picture

alexpott’s picture

More fun in Symfony land - our \Drupal\Tests\image\Kernel\ImageItemTest::testImageItemMalformed() revealed https://github.com/symfony/symfony/pull/24575

Any help with the 2 symfony PRs would be very appreciated.

mile23’s picture

Also what the patches show is that WebTestBase tests are the ones exercising the majority of the deprecated code

See #72. A lot of those deprecation errors are triggered during WTB tests which involve discovery.

Maybe run-tests.sh and/or the simpletest UI runner need to say SYMFONY_DEPRECATIONS_HELPER=disabled inside the child processes of WTB/TB tests.

mile23’s picture

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new8.36 KB
new21.37 KB

Just an update on where we are. Some changes have been merged in Symfony's PHPUnit Bridge that help us. It now supports test isolation and a couple of bugs in that support have been fixed. The last remaining PR to get done is https://github.com/symfony/symfony/pull/24685. I have a local branch where I've got deprecation testing working in KernelTestBase, BrowserTestBase (and therefore probably JavascriptTestBase but that is untested - there is no reason it should not work since JTB extends BTB) and WebTestBase. I've added support for WebTestBase because we still have quite a few and it is where a lot of our deprecated code is. I've also added the ability to exclude specific deprecations so we gradually work on fixing each specific one. We also need to think about contrib.

Here's the patch as it stands in case the proverbial bus comes along.

Status: Needs review » Needs work

The last submitted patch, 87: 2870194-4-87.patch, failed testing. View results

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new14.66 KB
new35 KB

Not sure we need the final PR for Symfony. I think we can fix our test bootstrap.php to register the deprecation collector when we need it too.

Here's a patch that should be green and show just how much work we've got to do to only call deprecated code paths from legacy tests.

The changes to the existing deprecation messages are to make them easier to test for. Ie. where the patch removes line breaks or swaps out __FILE__ (which makes the message environmentally specific)

alexpott’s picture

StatusFileSize
new1.37 KB
new35.17 KB

Missed one

The last submitted patch, 89: 2870194-4-89.patch, failed testing. View results

alexpott’s picture

Issue summary: View changes

Green! Updated issue summary to reflect current state of patch.

alexpott’s picture

StatusFileSize
new29.9 KB
new33.37 KB

New patch attached re-organises things so that:

  • The list of deprecations we are ignoring is in a better place
  • The messages outputted when an unexpected deprecation notice is triggered are better and don't contained a serialised array

This is ready for review!

alexpott’s picture

Issue summary: View changes

Updated issue summary with how to test instructions since it is not just apply patch and run a test.

alexpott’s picture

Issue summary: View changes
dawehner’s picture

Do we have an issue to track all the deprecation usages of Drupal itself?

  1. +++ b/core/modules/simpletest/src/WebTestBase.php
    @@ -690,9 +691,20 @@ protected function curlHeaderCallback($curlHandler, $header) {
    +      // Swallow deprecation notices. WebTestBase will not be updated to handle
    +      // them.
    

    This sounds like we will swallow all of the deprecations, which is not the case. Can we update this line here?

  2. +++ b/core/tests/Drupal/FunctionalTests/Core/Test/PhpUnitBridgeTest.php
    @@ -0,0 +1,32 @@
    +class PhpUnitBridgeTest extends BrowserTestBase {
    
    +++ b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitBridgeTest.php
    @@ -0,0 +1,33 @@
    +class PhpUnitBridgeTest extends KernelTestBase {
    

    👏 Yeah tests for both kernel and browser tests!

  3. +++ b/core/tests/Drupal/Tests/Listeners/DeprecationListener.php
    @@ -0,0 +1,115 @@
    + * @internal
    + *   This class will be removed once all the deprecation notices have been
    ...
    + */
    

    Don't we want to have the general feature available for longer?

  4. +++ b/core/tests/Drupal/Tests/Listeners/DeprecationListener.php
    @@ -0,0 +1,115 @@
    +    // Need to edit the file of deprecations.
    +    if ($file = getenv('SYMFONY_DEPRECATIONS_SERIALIZE')) {
    +      $deprecations = file_get_contents($file);
    +      $deprecations = $deprecations ? unserialize($deprecations) : [];
    

    Will parallel file operations be a potential source of future problems? It turns out its not, $this->runsInSeparateProcess = tempnam(sys_get_temp_dir(), 'deprec');. Thank you @alexpott

  5. +++ b/core/tests/bootstrap.php
    @@ -166,3 +167,8 @@ function drupal_phpunit_populate_class_loader() {
    +if ($ser = getenv('SYMFONY_DEPRECATIONS_SERIALIZE')) {
    +  DeprecationErrorHandler::collectDeprecations($ser);
    +}
    

    Let's use $file as well here.

alexpott’s picture

StatusFileSize
new1.58 KB
new33.54 KB

Thanks for the review @dawehner.

  1. Fixed - at one point I thought it wasn't worth doing WebTestBase but it turned out to be too easy.
  2. :)
  3. I don't think so. If your test is failing because of deprecation notices - mark the test @legacy and put an @expectedDeprecation annotation on it - or just fix it. We're in a special situation here because there are so many notices triggered by a test run that we have to handle it specially - rather than just fixing them. For me \Drupal\Tests\Listeners\DeprecationListener is just a way to handle the massive scope.
  4. Yep this is Symfony and they already run all their PHPUnit tests in parallel
  5. Yeah this is a copy from Symfony land but +1 to making it clearer in Drupal land.
dawehner’s picture

I don't think so. If your test is failing because of deprecation notices - mark the test @legacy and put an @expectedDeprecation annotation on it - or just fix it. We're in a special situation here because there are so many notices triggered by a test run that we have to handle it specially - rather than just fixing them. For me \Drupal\Tests\Listeners\DeprecationListener is just a way to handle the massive scope.

Fair. We should clearly document for contrib that in case they trigger errors, they need to add @legacy now.

alexpott’s picture

Created https://github.com/symfony/symfony/pull/24696 that should allow us to drop the changes to core/tests/bootstrap.php which would be great.

dawehner’s picture

Regarding a change notice, should we updated the existing one: https://www.drupal.org/node/2811561 or rather add a new one?

alexpott’s picture

One concern I have is contrib. If they are using silent deprecations as core is then, once we commit the current patch, their tests might just start failing. I'd be surprised if the deprecation practice of @trigger_error was widespread in contrib but it is a downside of using the same phpunit configuration for core and contrib.

If we have to be sure that we won't introduce a single fail for contrib then we need to implement a kill switch and have DrupalCI enable it for contrib testing and disable it for core. And then we'll need to provide some sort of UI on drupal.org for projects to enable deprecation testing. I think what might be best is to commit this to 8.5.x as early as possible and ensure that the CR has really good instructions for contrib so that when they do a run their project's tests against 8.5.x they know what to do.

Fortunately Symfony does have a killswitch for the deprecation functionality - SYMFONY_DEPRECATIONS_HELPER - see https://symfony.com/doc/current/components/phpunit_bridge.html#disabling... so I think we need to make sure that the WebTestBase code obeys this too. So at least we'll have the necessary plumbing in place for core if this does become an issue.

re #100 I think updating the existing change notice and re-publishing it once that is done will be okay. I think the change we need to make are

  • to tell people to add the extra test listener in
  • underline that contrib/custom might have to do some work for 8.5.x
  • document the killswitch
chi’s picture

I'd be surprised if the deprecation practice of @trigger_error was widespread in contrib

Here is search results for Drupal 8 modules hosted on drupal.org. So far only two modules address and salesforce have @trigger_error statement in its own code.

  1. address/src/Plugin/migrate/cckfield/AddressField.php
  2. loft_data_grids/vendor/symfony/yaml/Inline.php
  3. loft_data_grids/vendor/symfony/yaml/Unescaper.php
  4. loft_data_grids/vendor/symfony/yaml/Yaml.php
  5. loft_data_grids/vendor/symfony/yaml/Parser.php
  6. composer/vendor/composer/composer/tests/Composer/Test/Util/ErrorHandlerTest.php
  7. composer/vendor/composer/composer/tests/Composer/Test/Util/SilencerTest.php
  8. composer/vendor/symfony/process/Tests/ProcessTest.php
  9. potx/vendor/Twig/Filter.php
  10. potx/vendor/Twig/TokenParser/AutoEscape.php
  11. potx/vendor/Twig/Environment.php
  12. potx/vendor/Twig/TokenParserBroker.php
  13. potx/vendor/Twig/Node.php
  14. potx/vendor/Twig/Template.php
  15. potx/vendor/Twig/Filter/Method.php
  16. potx/vendor/Twig/Test/Node.php
  17. potx/vendor/Twig/Filter/Function.php
  18. potx/vendor/Twig/Test/Function.php
  19. potx/vendor/Twig/Test/Method.php
  20. potx/vendor/Twig/Filter/Node.php
  21. potx/vendor/Twig/Function.php
  22. potx/vendor/Twig/Function/Node.php
  23. potx/vendor/Twig/Function/Method.php
  24. potx/vendor/Twig/Function/Function.php
  25. potx/vendor/Twig/Node/Expression/Name.php
  26. potx/vendor/Twig/ExpressionParser.php
  27. potx/vendor/Twig/Loader/String.php
  28. potx/vendor/Twig/Lexer.php
  29. potx/vendor/Twig/Test.php
  30. potx/vendor/Twig/Extension/Escaper.php
  31. potx/vendor/Twig/Extension/Core.php
  32. potx/vendor/Twig/Autoloader.php
  33. salesforce/modules/salesforce_mapping/src/SalesforcePullEntityValueEvent.php
  34. salesforce/modules/salesforce_mapping/src/SalesforceQueryEvent.php
  35. salesforce/modules/salesforce_mapping/src/SalesforcePushParamsEvent.php
  36. salesforce/modules/salesforce_mapping/src/SalesforcePushEvent.php
  37. salesforce/modules/salesforce_mapping/src/SalesforcePushOpEvent.php
  38. salesforce/modules/salesforce_mapping/src/SalesforcePullEvent.php
dawehner’s picture

If we have to be sure that we won't introduce a single fail for contrib then we need to implement a kill switch and have DrupalCI enable it for contrib testing and disable it for core. And then we'll need to provide some sort of UI on drupal.org for projects to enable deprecation testing. I think what might be best is to commit this to 8.5.x as early as possible and ensure that the CR has really good instructions for contrib so that when they do a run their project's tests against 8.5.x they know what to do.

Don't they run it against the latest 8.5.x first? It feels like having some form of announcement could prevent issues in the first place.

@Chi
Thank you for your grep! This is a nice list as all those exceptions are in vendor code / non runtime code like migrations. Given that the risk seems to be quite low in the first place

alexpott’s picture

So looking at #102 there's address and salesforce - I'll run the tests locally and see what happens when this patch is applied. One great thing is that d.o now allows you to select what Drupal branch you run your tests with so I think we are actually okay here!

alexpott’s picture

I've run address, salesforce on 8.5.x with this patch applied. Tests pass.

potx is a 7.x module only
loft_data_grids does not work on 8.5.x cause https://github.com/aklump/loft_data_grids/issues/2
https://www.drupal.org/project/composer has no tests

Conclusion: there a likely to be very few problems for contrib. Phew!

dawehner’s picture

There is still almost 6 months before the 8.5 release, so I have the hope that if we publish a change record now, a lot of people will see it.
On the other hand I doubt there will be many people using something like that on custom modules, even it would be nice :)

alexpott’s picture

StatusFileSize
new3 KB
new35.69 KB

Here's a patch that adds the ability to suppress deprecation errors. I think this is super important for any projects which are making use of @trigger_error and have any tests that trigger such code. If they using run-tests.sh then all they need to do is pass --suppress-deprecations and if they are only PHPUnit then they can configure the global in their phpunit.xml (they also could just not add the listener but this way at least their tech debt has more chance of being exposed).

I've tested --suppress-deprecations with both a WebTestBase test and a KernelTestBase test - works great. And the PHPunit global works too.

I'll add a list of CR updates to make to the issue summary next.

alexpott’s picture

StatusFileSize
new448 bytes
new35.69 KB

Whitespace and a php file that is not a php file.

alexpott’s picture

Issue summary: View changes

Adding change record section to issue summary.

alexpott’s picture

Issue summary: View changes
alexpott’s picture

StatusFileSize
new7.24 KB
new38.22 KB
new38.2 KB

We can now move on to a more stable symfony/phpunit-bridge version and remove a workaround in our core/tests/bootstrap.php.

Also filing a patch where we're not silencing any of the deprecations - to make sure they are still being caught.

alexpott’s picture

Issue summary: View changes

The last submitted patch, 111: 2870194-4-test-only.111.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Status: Needs review » Needs work

The last submitted patch, 111: 2870194-4-111.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new5.15 KB
new34.86 KB

Oops.

dawehner’s picture

+++ b/core/scripts/run-tests.sh
@@ -305,6 +305,10 @@ function simpletest_script_help() {
+  --suppress-deprecations
+
+              Stops tests from failing if deprecation errors are triggered.

🙃 The other parameters are documented in the same line

I was worried quite a bit about custom/contrib code suddenly failing, but I guess @trigger_error isn't that used actually.

alexpott’s picture

+++ b/core/scripts/run-tests.sh
@@ -305,6 +305,10 @@ function simpletest_script_help() {
+  --suppress-deprecations
+
+              Stops tests from failing if deprecation errors are triggered.
+

Only when they are shorter... see

  --concurrency [num]

              Run tests in parallel, up to [num] tests at a time.

There's just no parameter for this.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Ah gotcha, no worries

wim leers’s picture

Look at all that technical debt being uncovered - this is pretty cool.

🎉👌❤️

How did I not find this issue until now!?

This may be my favorite patch of all of 2017, definitely in the top 10. (The patch looks great BTW.) This will single-handedly make the entire Drupal ecosystem more aware of deprecations, and therefor help the entire ecosystem to gradually update.

I had an early taste of how well that works in #2884337: Fix Symfony 3.2 deprecation notices, because it was a pure unit test that was triggering a Symfony deprecation notice, which caused DrupalCI to send me an e-mail about the failed test! Resulted in a very easy release: https://www.drupal.org/project/big_pipe_sessionless/releases/8.x-1.1. This sort of "fix the fail + tag release" is fun: it's trivial to do, encourages a new release, and allows you to gradually keep with the times. IOW: an important step towards https://dri.es/making-drupal-upgrades-easy-forever
Exciting! 🙃

mile23’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/composer.json
@@ -47,7 +47,7 @@
+        "symfony/phpunit-bridge": "^3.4.0-BETA2"

How about "symfony/phpunit-bridge": "~3.4.0@beta"? That way 'prefer-stable' will kick in once they release.

Other than that, I used PhpUnitBridgeIsolatedTest to figure out that isolated tests get their deprecation medicine properly by modifying the annotations. Also using the same technique I found that --suppress-deprecations turns the deprecation fails off properly.

So yay. :-)

Thanks to @alexpott for the excellent work on this.

Updated the change record to talk about how to turn it off and on from the command line, and included the new listener: https://www.drupal.org/node/2811561

Other than the version spec change, it's RTBC.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new823 bytes
new35.07 KB

@Mile23 but the tilde operator is much harder to grok. Here's the @beta with a carat.

mile23’s picture

Status: Needs review » Reviewed & tested by the community

Superduper. :-)

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 121: 2870194-4-121.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

alexpott’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new1.01 KB
new36.08 KB

Yay this patch works so nicely... #2917883: Rename 'migration_templates' directories in core modules to 'migrations' added a legacy test but didn't add the group or the @expectedDeprecationMessage...

mile23’s picture

It looks like MigrationDirectoryTest isn't testing for the deprecation, so it needs a follow-up to un-@legacy.

alexpott’s picture

@Mile23 huh? - that is literally the whole point of the test! In the test it states:

// Tests that a migration in directory 'migration_templates' is discovered.

And the deprecation message is:

Use of the /migration_templates directory to store migration configuration files is deprecated in Drupal 8.1.0 and will be removed before Drupal 9.0.0.

Support for scanning migration_templates is the legacy behaviour! See https://www.drupal.org/node/2920988

mile23’s picture

OK, so the change to the test still performs the migration even though it's the deprecated directory. I was mis-remembering phpunit tests short-circuiting on fail, but the deprecation tests don't work that way.

All the other test modules have the new directory after the change in #2917883: Rename 'migration_templates' directories in core modules to 'migrations' so we're still demoing that.

So it's still an out of scope change but it fixes the test and it allows the change here to pass. I guess we don't need a followup.

alexpott’s picture

@Mile23 well we either have to add @expectedDeprecationMessage to the test or add it to the list in getSkippedDeprecations() - adding it to the test means that there does not need to be a followup to remove that specific deprecation notice from the list - so in my mind that's a win. Handling the deprecation error in some way - either skipping it - or expecting it - it definitely in scope for this patch since without doing either we won't have a green test run.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 124: 2870194-4-124.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

mile23’s picture

Well it was out of scope in that the test was broken, but sort of in scope in that the test was broken because we don't have this patch in yet. :-)

Now it looks like we get to do the same thing with #2920001: Add cacheable HTTP exceptions: Symfony HTTP exceptions + Drupal cacheability metadata

Woot. :-)

alexpott’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new1.29 KB
new36.38 KB

Added the new deprecation message to the list to skip. We need this patch in so we can honest about the tech debt patches that add deprecations are introducing.

wim leers’s picture

It’s great to see this patch working so well!

It will also help me keep #2893804: Remove rest.module BC layers up-to-date!

catch’s picture

Status: Reviewed & tested by the community » Fixed

OK this looks great and the fact it keeps breaking shows how much we need it.

Committed 75dcf9a and pushed to 8.5.x. Thanks!

There's a tracking issue for removing all deprecated code usages here #2607260: [meta] Core deprecation message introduction, contrib testing etc., just slightly updated it now this has landed.

  • catch committed 75dcf9a on 8.5.x
    Issue #2870194 by alexpott, Mile23, jibran, larowlan, tim.plunkett:...
catch’s picture

Issue tags: +8.5.0 release notes
dawehner’s picture

Thank you! I almost think this should be a release highlight given how important this is for the longtime upgrade strategy of Drupal.

webchick’s picture

Agreed. Thanks for all the awesome work here, folks!

berdir’s picture

This is great, but I think it might also be a problem for contrib.

Once a message is removed from being excluded, it will fail on contrib. But unlike core, contrib can not just use the new API if it's not yet in a stable release. For example, what we are seeing here are I think such messages: https://www.drupal.org/node/2919408#comment-12335861, not even sure if they are even caused directly by us.

One solution might be that contrib uses only the supported or maybe pre-release core version, I think one of those two should be the default, not Development.

dawehner’s picture

One solution might be that contrib uses only the supported or maybe pre-release core version, I think one of those two should be the default, not Development.

Mh, on the other hand I think running tests for the next version also adds a lot of value in terms of catching bugs upfront.
I am wondering whether core should maybe not remove these checks for one minor version even it is fully compatible.

berdir’s picture

Well, but it's sometimes really hard to keep code and especially tests passing on multiple minor versions, so at least going for Pre-release would imho be preferable, that still gives you some warning a while before the next release. and you could still run a test development manually or on a schedule. But it's really annoying if all your patch testing is suddenly broken because core added some fancy new thing that ou can't yet use anyway :)

But yes, as a rule, only adding a trigger_error()/removing it from the exclusion list in the next minor might be a good idea.

catch’s picture

Just a note discussion from #138 to #140 now going on in #2607260: [meta] Core deprecation message introduction, contrib testing etc..

chr.fritsch’s picture

FYI: I opened #2922451: [policy no patch] Make it possible to mark plugins as deprecated to discuss how we should mark plugins as deprecated

wim leers’s picture

@Berdir: you can set up automated testing of both the current and development branch. The development branch will be failing more often indeed, because the non-deprecated successor to the deprecated API may indeed not yet be available on the current branch.

I think a follow-up to allow contrib modules to temporary skip certain deprecations would be very valuable indeed.

mile23’s picture

wim leers’s picture

Updating metadata for #144.

jonathan1055’s picture

From #138

Once a message is removed from being excluded, it will fail on contrib. But unlike core, contrib can not just use the new API if it's not yet in a stable release.

From #143

I think a follow-up to allow contrib modules to temporary skip certain deprecations would be very valuable indeed.

I have hit this exact problem in Rules module. #2883680: Force all route filters and route enhancers to be non-lazy was committed on 24th October, but from 10th November (after the commit in #134 above) the Rules tests fail at 8.5 because we were using the deprecated RouteEnhancerInterface. I can fix the code to use the new EnhancerInterface and the tests pass at 8.5 but now fail at 8.4 due Interface 'Drupal\Core\Routing\EnhancerInterface' not found

From #98 we had

We should clearly document for contrib that in case they trigger errors, they need to add @legacy now.

I would be interested to learn how we can make contrib tests pass at both 8.5 and 8.4 as we want to start using the correct new class.

dawehner’s picture

@jonathan1055
One thing we could do is the following:

  • Test contrib on the last minor instead by default
  • Once we add a deprecation error, also add it to the list
  • Remove it from the list at the beginning of the next minor cycle

Anyone has thoughts about it?

alexpott’s picture

@jonathan1055 thanks for reporting this - I think we should be discussing this over on #2607260: [meta] Core deprecation message introduction, contrib testing etc.. As an aside I think that @dawehner's suggestions make a kind of sense. But it is tricky - ideally we'd have a way for modules to know that they are free from using deprecated code and if everyone is using the same list then this is tricky.

jonathan1055’s picture

Thanks @dawehner and @alexpott. I am fine with contrib failing as soon as code is deprecated - my module runs daily tests at 8.3, 8.4 and 8.5 dev. I should have reported my problem on #2883680: Force all route filters and route enhancers to be non-lazy because that change has been committed to 8.5 but not 8.4. So now, if I leave the code unfixed it fails at 8.5 but if I fix it to run at 8.5 it fails at 8.3 and 8.4. That issue is now closed unfortunately because the commit was done a couple of weeks before deprecated code triggered a test failure.

tr’s picture

This is a disaster - most of my hundreds of tests now fail and there's nothing I can do about it because my tests DON'T use deprecated functions and my code DOESN'T use deprecated functions - I can't just mark @group legacy because the problem isn't in my code.

My module just has a DEPENDENCY on Rules - none of my tests actually use Rules or call Rules methods or services or anything. If I remove the dependency, all the tests run fine. If I add the dependency (and nothing else), most of my tests fail.

I don't see how this change provides a gradual and smooth path toward removing @deprecated code. The effect I see is that every module needs to remove this code immediately or all the tests break, and since you can break the tests of your dependant modules, basically an entire ecosystem of modules can be thrown into immediate failure.

I also share the concern of #147 - the change, at least in the case of RouteEnhancer, is not backwards compatible, so everyone using my module will immediately be forced to upgrade their core to get a fix for this.

This amounts to a major API change and a BC break. I don't see how this constitutes an allowed change for a core minor point release.

https://www.drupal.org/core/d8-allowed-changes

Minor releases provide new improvements and functionality without breaking backward compatibility (BC) for public APIs.

mile23’s picture

I can't just mark @group legacy because the problem isn't in my code.

Actually you can, if they're not WTB tests. I know that's not a great solution.

tr’s picture

All the *new* tests I add are PHPUnit tests, but I still have ~10,000 lines of tests with WebTestBase, developed over many years, that run just fine and perform an important role in making sure my modules run correctly. Converting them is a low priority because WebTestBase is SUPPOSED to be supported throughout D8. I don't need to have 40 hours of extra (unpaid volunteer) work dumped on me because converting to BrowserTestBase now seems to be a mandatory and immediate requirement in the middle of a minor point release.

jonathan1055’s picture

Can anyone take a look at my patch in #112 on #2883680-112: Force all route filters and route enhancers to be non-lazy - It adds the new replacement classes to core 8.4 and 8.3 and therefore allows contrib to remove the deprecated code usage. That issue is closed and there has been no respone to it yet, but given that this problem is having a knock-on effect with modules such as Scheduler and SMS Framework, amongst many others, I would like to know if my solution works, and could be committed to 8.4 and 8.3

Jonathan

alexpott’s picture

@jonathan1055 the thing is we shouldn't be adding the new classes to 8.4.x - new stuff is supposed to be in 8.5.x. Also this is a closed issue so discussion should be continuing in #2607260: [meta] Core deprecation message introduction, contrib testing etc. because that is an active issue discussing how we manage code deprecations.

jonathan1055’s picture

@alexpott OK, I get your point about the closed issue, but my patch is hardly "adding new stuff" it is simply creating a class of the same name as the new 8.5 classes, just using the already existing Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface, so no new active code. It seems like a very simple solution to solve this particular problem.

xjm’s picture

Issue tags: +8.5.0 release notes

This should also be mentioned in the release notes for the alpha and the minor, since it disrupts test suites/CI integrations/etc. So reverting @webchick's tag revert, or at least adding it to both lists. :)

jonathan1055’s picture

Just for reference, in relation to #150 and #156 above I have raised #2924899: Backport \Routing\EnhancerInterface to core 8.4 to discuss the backport of the replacement classes following the deprecations in #2883680: Force all route filters and route enhancers to be non-lazy

mile23’s picture

We have a follow-up here, to possibly backport some behavior from run-tests.sh --suppress-deprecations to 8.4.x: #2927636: Backport --supress-deprecations to run-tests.sh 8.4.x

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.