For some reasons I can't figure out, since #2926508: Add DateTimeNormalizer+TimestampNormalizer, deprecate TimestampItemNormalizer: @DataType-level normalizers are reusable by JSON:API, when running PHPUnit tests from the console, I started getting the following message
$ .../vendor/bin/phpunit --group Database
PHPUnit 6.5.14 by Sebastian Bergmann and contributors.
Testing
............................................................... 63 / 297 ( 21%)
....................................................SSSS....... 126 / 297 ( 42%)
............................................................... 189 / 297 ( 63%)
......................................S........................ 252 / 297 ( 84%)
............................................. 297 / 297 (100%)
Time: 2.63 minutes, Memory: 731.00MB
OK, but incomplete, skipped, or risky tests!
Tests: 297, Assertions: 1964, Skipped: 5.
Remaining deprecation notices (1)
1x: Drupal\serialization\Normalizer\TimeStampItemNormalizerTrait is deprecated in Drupal 8.7.0 and will be removed in Drupal 9.0.0. Use \Drupal\serialization\Normalizer\TimestampNormalizer instead.
1x in UnitTestSuite::suite from Drupal\Tests\TestSuites
Am I the only one?
| Comment | File | Size | Author |
|---|---|---|---|
| #12 | 3034015-12.patch | 1.55 KB | mondrake |
Comments
Comment #2
wim leersWith which test? Because
\Drupal\Tests\serialization\Unit\Normalizer\TimestampItemNormalizerTestdoesn't trigger it:Comment #3
mondrakeIt probably does not trigger if one test file only is run like in #2. It apparently does if you run a test group
$ .../vendor/bin/phpunit --group DatabaseUpdating IS.
Comment #4
wim leersThat's helpful, thanks.
I suspect this is because
\Drupal\Tests\serialization\Unit\Normalizer\TimeStampItemNormalizerTraitDeprecatedTestClassexists. And that exists precisely to assert the deprecation error is thrown.Like I wrote at #2926508-183: Add DateTimeNormalizer+TimestampNormalizer, deprecate TimestampItemNormalizer: @DataType-level normalizers are reusable by JSON:API:
This is a first of its kind, and I probably did something wrong. Would love to understand how I should then do this instead. The conclusion will also serve as an example for other deprecated traits.
Comment #5
wim leersThis is crucial to solve on the way to Drupal 9.
Comment #6
wim leers@catch just pointed out that this may be caused by #3031577: \Drupal\Tests\Listeners\DeprecationListenerTrait::getSkippedDeprecations() does not work in unit tests.
Comment #7
mondrakeProbably the problem is with PHPUnit autoloading, that is loading the deprecated trait (dunno why) and hence the @trigger_error, that sits outside of the trait code, fires.
I wonder if it's really necessary to test the deprecation of the trait in isolation. Since that @trigger_error fires on autoloading, the first deprecation test of a deprecated method of the deprecated trait (phew :)) may be intercepted by an @expectedDeprecation of the trait itself?
Comment #8
wim leersMy thoughts exactly. I've seen similar problems before.
But nothing in core was using this deprecated trait anymore. That's why I was asked to add an explicit test.
Comment #9
mondrakeHow about then
1. add a deprecation trigger to one of the methods that are in the trait
2. change the deprecation test to test deprecation of the method
3. that test to have 2 @expectedDeprecation annotations, one for the class (=trait) and one for the deprecated method
Then autoloader should kick in only while in-test - so autoloader loads the trait only when the method is invoked and triggers the trait-level deprecation, then the execution of the method triggers the method-level deprecation.
?
Comment #10
mondrakeThe problem is definitely with autoloading - the
use TimeStampItemNormalizerTrait;statement in the class autoloads the trait and fires the trigger, and apparently the load occurs before PHPUnit can intercept the triggered error.I know the attached is ugly, but it passes locally. Just for sharing the idea.
Comment #11
wim leersThe problem with this is that it is changing the message. It's saying that the trait is not deprecated but a method is.
I could see how it can work if we make it a rule to never deprecate a trait but always deprecate all methods on the trait. But that's still weird and unclear.
I think there's a much simpler option: don't require tests for deprecated traits that only test that the deprecation error is triggered.
Comment #12
mondrakeI think this, or something similar, can do. We take away the deprecated class from the testing namespaces. So PHPUnit when discovering tests for groups does not autoload it (it has to do it to parse the annotations). The class is loaded only when the test method calls
$test = new TimeStampItemNormalizerTraitDeprecatedTestClass();, and only at that time the trait is consequently loaded.Comment #13
mondrakeMajor since
Comment #14
bn_code commentedComment #16
mile23The giveaway is this, from the error message:
The test suites are where discovery happens for the phpunit tool. Test suites are not consulted during run-tests.sh, which is why this isn't a fail on the testbot.
I think #12 is correct, because during discovery time
TestDiscoverywill reflectTimeStampItemNormalizerTraitDeprecatedTestClass, which then loads the trait. Since discovery time is outside of a@group legacycontext, it pops up as an outstanding deprecation error.+1 on #12 because it moves
TimeStampItemNormalizerTraitDeprecatedTestClassto a place that is not scanned during discovery but is then autoloadable for the test.Comment #17
mile23Actually this is a test fix, so we can (should, must...) move this to 8.7.x.
Comment #18
mondrakeThanks @Mile23.
I was wondering whether we should also add a deprecation @trigger_error to the
TimeStampItemNormalizerTraitDeprecatedTestClassclass, and capture the @expectedDeprecation for the class inTimeStampItemNormalizerTraitDeprecatedTest?Comment #19
mile23Re: #18: I don't think we should. We're only testing whether the trait triggers the expected error, not classes that use it.
Comment #20
wim leers#12 that is genius in its simplicity! I wish I had thought of that :)
Comment #21
wim leersMoving back to the actually affected component — thank you
phpunitpeople for taking a look at this 🙏 Once this is committed, we'll have One Correct Example in core :)Comment #22
alexpottCommitted and pushed 7555529a7e to 8.8.x and c45d44b3f8 to 8.7.x. Thanks!
As a test only change backported to 8.7.x - I discussed backporting test-only changes with @catch (as a release manager).