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?

CommentFileSizeAuthor
#12 3034015-12.patch1.55 KBmondrake
#10 3034015-10.patch3.39 KBmondrake

Comments

mondrake created an issue. See original summary.

wim leers’s picture

With which test? Because \Drupal\Tests\serialization\Unit\Normalizer\TimestampItemNormalizerTest doesn't trigger it:

/usr/local/bin/php /private/var/folders/4l/5sndwsz50tqgxjh2525n10br0000gp/T/ide-phpunit.php --configuration /Users/wim.leers/Work/d8/core/phpunit.xml Drupal\Tests\serialization\Unit\Normalizer\TimestampItemNormalizerTest /Users/wim.leers/Work/d8/core/modules/serialization/tests/src/Unit/Normalizer/TimestampItemNormalizerTest.php
#!/usr/bin/env php
PHPUnit 6.5.14 by Sebastian Bergmann and contributors.

Testing Drupal\Tests\serialization\Unit\Normalizer\TimestampItemNormalizerTest
...........                                                       11 / 11 (100%)

Time: 695 ms, Memory: 10.00MB

OK (11 tests, 58 assertions)

Process finished with exit code 0
mondrake’s picture

Title: TimeStampItemNormalizerTrait deprecation message in UnitTestSuite::suite when running PHPUnit testts from console » TimeStampItemNormalizerTrait deprecation message in UnitTestSuite::suite when running PHPUnit tests from console
Issue summary: View changes

It 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 Database

Updating IS.

wim leers’s picture

Title: TimeStampItemNormalizerTrait deprecation message in UnitTestSuite::suite when running PHPUnit tests from console » Class to test deprecation error for deprecated trait triggers deprecation error itself

That's helpful, thanks.

I suspect this is because \Drupal\Tests\serialization\Unit\Normalizer\TimeStampItemNormalizerTraitDeprecatedTestClass exists. 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:

  1. This wasn't very straightforward. In fact, this is the first deprecated trait with explicit deprecation test coverage. A lot of traits have been deprecated, but none of them have explicit test coverage.

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.

wim leers’s picture

Issue tags: +Drupal 9

This is crucial to solve on the way to Drupal 9.

mondrake’s picture

Probably 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?

wim leers’s picture

Probably 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.

My thoughts exactly. I've seen similar problems before.

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?

But nothing in core was using this deprecated trait anymore. That's why I was asked to add an explicit test.

mondrake’s picture

But nothing in core was using this deprecated trait anymore. That's why I was asked to add an explicit test.

How 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.

?

mondrake’s picture

Status: Active » Needs review
StatusFileSize
new3.39 KB

The 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.

wim leers’s picture

The 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.

mondrake’s picture

StatusFileSize
new1.55 KB

I 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.

mondrake’s picture

Priority: Normal » Major

Major since

Cause test failures in environments not supported by the automated testing platform

bn_code’s picture

Issue tags: +epam-contrib-2019.03

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.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

Status: Needs review » Reviewed & tested by the community

The giveaway is this, from the error message:

1x in UnitTestSuite::suite from Drupal\Tests\TestSuites

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 TestDiscovery will reflect TimeStampItemNormalizerTraitDeprecatedTestClass, which then loads the trait. Since discovery time is outside of a @group legacy context, it pops up as an outstanding deprecation error.

+1 on #12 because it moves TimeStampItemNormalizerTraitDeprecatedTestClass to a place that is not scanned during discovery but is then autoloadable for the test.

mile23’s picture

Version: 8.8.x-dev » 8.7.x-dev

Actually this is a test fix, so we can (should, must...) move this to 8.7.x.

mondrake’s picture

Thanks @Mile23.

I was wondering whether we should also add a deprecation @trigger_error to the TimeStampItemNormalizerTraitDeprecatedTestClass class, and capture the @expectedDeprecation for the class in TimeStampItemNormalizerTraitDeprecatedTest?

mile23’s picture

Re: #18: I don't think we should. We're only testing whether the trait triggers the expected error, not classes that use it.

wim leers’s picture

#12 that is genius in its simplicity! I wish I had thought of that :)

wim leers’s picture

Component: phpunit » serialization.module

Moving back to the actually affected component — thank you phpunit people for taking a look at this 🙏 Once this is committed, we'll have One Correct Example in core :)

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 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).

  • alexpott committed 7555529 on 8.8.x
    Issue #3034015 by mondrake, Wim Leers, Mile23: Class to test deprecation...

  • alexpott committed c45d44b on 8.7.x
    Issue #3034015 by mondrake, Wim Leers, Mile23: Class to test deprecation...

Status: Fixed » Closed (fixed)

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