Problem/Motivation
Spin off of #3523614: [CI] Collect and report deprecation statistics and details.
The DeprecationHandler class was implemented as a replacement of Symfony's PHPUnit-bridge component, and uses initialization logic that is now outdated by more recent PHPUnit developments.
Proposed resolution
In this issue, we will
- convert the DeprecationHandler class into a proper PHPUnit 'extension', using the bootstrap logic introduced in PHPUnit 10
- introduce proper extension parameters in the phpunit.xml to configure the extension, and a new environment variable that could override the xml configuration at runtime in CI pipelines
- deprecate the legacy
SYMFONY_DEPRECATIONS_HELPERvariable
The DeprecationHandler stopped working on PHPUnit 13.2; PHPUnit 13.3 will make parts of the handler obsolete, this issue will prepare for its adoption by deprecating SYMFONY_DEPRECATIONS_HELPER.
Remaining tasks
User interface changes
Introduced terminology
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|
Issue fork drupal-3589108
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
mondrakeComment #4
mondrakeComment #5
mondrakeComment #6
mondrakeComment #7
mondrakeComment #8
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #9
mondrakerebased
Comment #10
mondrakeWe need to more aggressively stop using
SYMFONY_DEPRECATION_HELPER, since PHPUnit 13.2 has broken our deprecations ignore approach and 13.3 will ship with a feature (Deprecation Filters) that is not compatible with our ownBootstrapErrorHandlerany more.On that.
For more info: PHPUnit 13.2 breaks Drupal's approach for ignoring deprecations
Comment #11
mondrakeComment #12
mondrakeComment #13
mondrakeComment #14
mondrakeComment #15
mondrakeComment #16
mondrakeIn light of Deprecation Filters #6710 we should probably give a better name to the new environment variable, to make it a better fit for PHPUnit 13 when it comes.
On it.
Comment #17
mondrakeComment #18
mondrakeComment #19
mondrakeThis is a blocker for adopting PHPUnit 13.
Comment #20
dcam commentedSo this is about bootstrapping the extension with well-defined configuration that's defined with individual variables in
phpunit.xmlfiles, not about implementingExtension::bootstrap(). After studying the PHPUnit docs on extensions I was a little surprised to find that we don't actually do anything in that method. That's alright. I figured it out.I only found a couple of minor, almost nit-picky grammatical problems in comments. If there's a logic problem in the code or something that could cause larger issues in the test system, then I lack the understanding to anticipate them. After studying the changes in detail they look OK to me.
Testing the new deprecation message is simple. Add
<env name="SYMFONY_DEPRECATIONS_HELPER" value="ignoreFile=core/.deprecation-ignore.txt"/>to yourphpunit.xmland run a Unit test. The deprecation message will be issued.I added the new configuration XML to test the extension:
Toggling the
enableProjectIgnoresparameter correctly turns the deprecation handling on and off. While disabled, deprecation warnings like this are issued:...which is what the deprecation handler is intended to silence. While enabled they do not appear in the test results. Similarly,
projectIgnoreFilealso works as expected or it wouldn't be able to ignore deprecations. But I mangled it just to test what happens and got an/InvalidArgumentExceptionin response.I don't know how to test the
enableDebugClassLoaderthough. If someone can enlighten me, then I'll work on it.I'm setting the status to Needs Work for the minor issues I found.
Comment #21
mondrakeThanks for the review @dcam.
Yes, a bit of explanation would help here.
Deprecations like
Method "Drupal\Core\Field\FormatterInterface::settingsSummary()" might add "array" as a native return type declaration in the future. [...]are triggered by the DebugClassloader, not through the tests themselves. When during a test a class is needed, it gets loaded, the DebugClassloader inspects it and triggers deprecations for missing type declarations. This starts happening as soon as the DebugClassloader is enabled. In Drupal core, since #3486376: Extend Symfony DebugClassLoader to report missing cross-module @return types this happens a lot, 3.5-4 million deprecations are triggered on each pipeline run. For this reason we have the 'deprecation ignore file' that shields that from being reported. We need to enable the DebugClassloader and the ignore file in strict sequence (otherwise we may have deprecations reported as not yet shielded), and as early as possible during the test runner initialization (we want to also shield deprecations that are triggered by test framework extended features during the setups before actual test runs).Right now in HEAD, this is all initialized in the
bootstrap.phpfile that PHPUnit includes before it orderly bootstraps each extension. So moving the initialization to the extension::bootstrap()would mean 'losing' on the current logic, because other extensions may be bootstrapped earlier than ours, and if they trigger deprecations we might be missing the shield. So in the MR I kept doing a 'pre-boostrap' initialization of the extension during the bootstrap.php inclusion as we know this will happen first. When we reach PHPUnit 13 (and here why this is important to this now so we can prepare), this pre-boostrap will have to happen during the instantiation of the new DeprecationFilter i.e. separately from the extension bootstrap itself.FWIW, if we ever get to #3523614: [CI] Collect and report deprecation statistics and details, this issue's parent and where part of the MR here is taken from, you can see that we will have also some logic implemented within
::bootstrap()as that will not be sequence critical. But that part is not relevant to the deprecation ignore logic that is in scope of this issue.You can try by setting
enableProjectIgnorestotrueandenableDebugClassLoadertofalseon the test that triggered the error in #20. No errors should be reported. ThenenableDebugClassLoaderto true and you should get the error. Also, you may try to remove the#[IgnoreDeprecations]from a test of your choice that has them, and see withenableProjectIgnoresset to false how togglingenableDebugClassLoaderwould change your results.I thought it would be useful to have an explicit parameter for enabling/disabling the DebugClassloader (it's not an option now), because I predict in the next couple of Drupal majors contrib will struggle a lot to align to #3486376: Extend Symfony DebugClassLoader to report missing cross-module @return types. Type hint deprecations will mix with 'normal' deprecations, and it may be useful for contrib to just disable the former in some cases to focus on the latter. This option will facilitate that.
Comment #22
mondrakeComment #23
dcam commentedThank you very much for that explanation. I didn't realize that it was the
DebugClassLoaderthat causes those warnings to be issued. I was under the impression that it was caused by PHPUnit. Now I have more complete understanding.Per my testing, these are the results I got:
enableProjectIgnoresandenableDebugClassLoaderset to FALSE no warnings are issued.enableProjectIgnoresset to FALSE andenableDebugClassLoaderto TRUE the warnings are issued.enableProjectIgnoresandenableDebugClassLoaderset to TRUE no warnings are issued.enableProjectIgnoresbeing TRUE andenableDebugClassLoaderbeing FALSE doesn't make much sense, I think. But for the record no warnings are issued.As I understand it, this is the correct behavior. This one looks good to me.
Comment #24
mondrakeRe the 4th case, we also want to ignore deprecations that are NOT triggered by the DebugClassloader. That's the 'normal' case actually. ATM in HEAD there are few of them, but during a major's lifecycle these pile up to be cleaned later when
mainstarts deviating from the last minor branch.Right now, in HEAD only these patterns relate to ignoring 'normal' deprecations
but in 11.4.x, a much bigger list is present as 11.4.x has not gone through the cleanup to prepare for 12
Comment #25
mondrakeGiven it's on the path to PHPUnit 13, I think this is a task rather than a feature.
Comment #27
catchCommitted/pushed to main, thanks!
This needs a backport MR for 11.x, although wondering how much we definitely need a backport here, it might be OK to let things diverge at this point with the test runner.
Comment #30
mondrakeI think we need to backport in this case, to give people the chance to react to
@trigger_error("Using the SYMFONY_DEPRECATIONS_HELPER environment variable to configure test runs is deprecated in drupal:11.5.0 and is removed from drupal:12.0.0. See https://www.drupal.org/node/3594014", E_USER_DEPRECATED);still in D11.
Comment #32
mondrakeComment #33
dcam commentedThe 11.x diff is nearly identical to the main branch diff. The only differences are the removal property hooks and the change from
DrupalDebugClassLoadertoDebugClassLoader. As noted above, there is noDrupalDebugClassLoaderin D11.Per my testing, these are the results I got:
phpunit.xmlconfiguration no deprecation warnings were issued.So the backport looks good to me.
Comment #36
catchCommitted/pushed to 11.x, thanks!
Comment #38
mondrakePublished CR after chaning the target branch.
Comment #39
acbramley commentedI think this has broken phpunit (next major) jobs for contrib projects until the gitlab template is updated https://git.drupalcode.org/project/diff/-/jobs/10935984
Comment #40
mondrakehttps://git.drupalcode.org/project/gitlab_templates/-/work_items/3572422 is the gitlab_templates issue about making necessary adjustments for #39.
Comment #41
fjgarlin commentedDoes it really need to trigger an error? It can be just ignored and maybe, optionally, throw a warning, but throwing an error because a variable exists might be too much.
Is there any chance of changing this behaviour?
Comment #42
mondrake#41 it's not an error, it's a deprecation (E_USER_DEPRECATED). You can disable failing on deprecations by passing
--suppress-deprecationsto run-tests.sh command line. But that obviously means that all E_USER_DEPRECATED and E_DEPRECATED "errors" will be skipped.Comment #43
fjgarlin commentedDoh! My bad, I didn't see the E_USER_DEPRECATED part. You are correct. Sorry for the noise.
Comment #46
acbramley commentedConfirming that adding
_PHPUNIT_EXTRA: '--suppress-deprecations'fixes it https://git.drupalcode.org/project/diff/-/jobs/10954987