Problem/Motivation

Drupal 8 should fully support PHP 7. PHP 7 includes the ability to type hint primitives, and explicitly declare the return type of methods:

public function foo(string $bar) : string {
  // Implementation here.
}

However, this causes PHPUnit <= 5 to fail because it does not support these concepts. It will fail because <= 5, it cannot create mocks that have these explicit types.

Updating PHPUnit to version 5 does work in theory, but unit tests are littered with deprecation warnings because PHPUnit_Framework_TestCase::getMock() is deprecated, and this is used all over the place in Drupal base unit test classes. Also PHPUnit 5 does not support PHP 5.5. In #2927806: Use PHPUnit 6 for testing when PHP version >= 7.2 we are looking to use PHPUnit 6 to get PHP 7.2 support and this version does not even have a getMock() method.

Proposed resolution

Add a trait that:

  • adds a getMock wrapper that calls using MockBuilder on PHPUnit 6.
  • adds a createMock wrapper that calls getMock() on PHPUnit 4.

getMock will be @deprecated but won't contain a trigger_error(), see #71

Remaining tasks

User interface changes

None

API changes

API addition of createMock() to Drupal test API.

Data model changes

None

CommentFileSizeAuthor
#92 90-92-interdiff.txt1.57 KBalexpott
#92 2795317-2-92.patch13.02 KBalexpott
#90 2795317-2-90.patch12.94 KBalexpott
#90 87-90-interdiff.txt533 bytesalexpott
#87 2795317-2-87.patch12.97 KBalexpott
#87 78-87-interdiff.txt1.86 KBalexpott
#83 2795317-2-83.patch12.97 KBalexpott
#83 78-83-interdiff.txt11.54 KBalexpott
#78 2795317-2-77.patch13.82 KBalexpott
#78 72-77-interdiff.txt3.12 KBalexpott
#72 71-72-interdiff.txt1.2 KBalexpott
#72 2795317-72.patch12.38 KBalexpott
#71 69-71-interdiff.txt1.73 KBalexpott
#71 2795317-71.patch12.24 KBalexpott
#69 2795317-69.patch12.72 KBalexpott
#69 67-69-interdiff.txt4.48 KBalexpott
#65 2795317-65.patch12.12 KBdawehner
#59 drupal-8.4.x-phpunit_5.7-2795317-59.patch12.62 KBhswong3i
#58 2795317-49.patch12.3 KBlendude
#57 drupal-8.4.x-phpunit_5.7-2795317-57.patch22.2 KBhswong3i
#54 2795317-51-PHPUNIT-5.patch35.59 KBlendude
#51 2795317-51.patch39.13 KBbircher
#51 2795317-51.patch39.13 KBbircher
#49 interdiff-2795317-46-49.txt759 bytesbircher
#49 2795317-49.patch12.3 KBbircher
#46 interdiff-2795317-43-46.txt1.38 KBbircher
#46 2795317-46.patch12.3 KBbircher
#43 2795317-43.patch11.83 KBbircher
#43 interdiff-2795317-41-43.txt8.06 KBbircher
#41 2795317-41.patch6.89 KBjofitz
#41 interdiff-39-41.txt2.8 KBjofitz
#39 2795317-39.patch6.95 KBlendude
#39 interdiff-2795317-36-39.txt1.79 KBlendude
#36 2795317-36.patch6.41 KBlendude
#36 interdiff-2795317-34-36.txt2.48 KBlendude
#34 2795317-34.patch5.99 KBlendude
#34 interdiff-2795317-32-34.txt3.51 KBlendude
#32 2795317-32.patch3.01 KBlendude
#32 interdiff-2795317-29-32.txt2.98 KBlendude
#29 2795317-29.patch3.68 KBlendude
#29 interdiff-2795317-28-29.txt1.07 KBlendude
#28 2795317-28.patch3.67 KBlendude
#28 interdiff-2795317-27-28.txt3.6 KBlendude
#27 interdiff-2795317-26-27.txt1.39 KBmartin107
#27 2795317-27.patch1.54 KBmartin107
#26 2795317-26.patch1.53 KBdawehner
#22 2795317-22.patch384 bytesdawehner
#21 drupal_core-8.4.x-phpunit_5.7-2795317-21.patch523.65 KBhswong3i
#21 drupal_core-8.3.x-phpunit_5.7-2795317-21.patch520.64 KBhswong3i
#18 drupal_core-8.4.x-phpunit_5.7-2795317-18.patch523.79 KBhswong3i
#18 drupal_core-8.3.x-phpunit_5.7-2795317-18.patch520.8 KBhswong3i
#18 drupal-8.4.x-phpunit_5.7-2795317-18.patch618.07 KBhswong3i
#18 drupal-8.3.x-phpunit_5.7-2795317-18.patch617.35 KBhswong3i
#14 drupal_core-8.4.x-phpunit_5.7-2795317-14.patch522.58 KBhswong3i
#14 drupal_core-8.3.x-phpunit_5.7-2795317-14.patch520.41 KBhswong3i
#14 drupal-8.4.x-phpunit_5.7-2795317-14.patch593.12 KBhswong3i
#14 drupal-8.3.x-phpunit_5.7-2795317-14.patch674.72 KBhswong3i
#9 drupal_core-8.3.x-phpunit_5.7-2795317-9.patch665.72 KBhswong3i
#9 drupal_core-8.4.x-phpunit_5.7-2795317-9.patch669.95 KBhswong3i
#8 drupal-8.3.x-phpunit_5.7_no_composer_lock-2795317-8.patch667.16 KBhswong3i
#8 drupal-8.4.x-phpunit_5.7_no_composer_lock-2795317-8.patch740.51 KBhswong3i
#6 drupal-8.3.x-phpunit_5.7-2795317-6.patch745.31 KBhswong3i
#6 drupal-8.4.x-phpunit_5.7-2795317-6.patch740.51 KBhswong3i

Comments

chriscohen created an issue. See original summary.

dawehner’s picture

Sadly createMock doesn't exist in PHPUnit 4.8, so we would have to convert them all to use getMockBuilder or just go with prophecy directly.

For me its not a nice movement that phpunit has such a high PHP dependency. This causes problems for people out there which have some more restrictive version constrains, as you see ...

chriscohen’s picture

I'm not sure on that. Drupal 8 requires PHP >= 5.5.9, and PHPUnit 5.5 requires PHP >= 5.6 so they're actually pretty close.

The only possible issue is people using PHP 5.5.9 which is beyond end of life.

But this does raise the issue that without increasing Drupal 8's requirements from 5.5.9 to 5.6, it wouldn't be possible to use, say, PHPUnit 5.5.

I appreciate that it's always a balance between keeping things up to date, and stagnating so that Drupal can support all the many people who refuse or are unable to update.

dawehner’s picture

The only possible issue is people using PHP 5.5.9 which is beyond end of life.

Well, its the version supported by most linux distros out there.

#2524432: Suggest PHP 5.6 as the recommended version and linked issues are related to this topic.

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

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

hswong3i’s picture

Simply regex replace all existing getMock() into createMock(), for both 8.3.x and 8.4.x.

In between, since composer update in 8.4.x is now broken due to symfony 3.3.x released (see #2874909: Update Symfony components to 3.3.*), so here also give an additional change to all symfony/* and JUST depend on 3.2.x, statically.

hswong3i’s picture

Status: Active » Needs review
hswong3i’s picture

Another version that without changes to composer.lock, for distribution (e.g. https://github.com/drustack/drustack-standard) to apply patches.

hswong3i’s picture

Individual patches create for drupal/core.

The last submitted patch, 6: drupal-8.4.x-phpunit_5.7-2795317-6.patch, failed testing. View results

The last submitted patch, 6: drupal-8.3.x-phpunit_5.7-2795317-6.patch, failed testing. View results

hswong3i’s picture

Only change $this->getMock() into $this->createMock().

The last submitted patch, 14: drupal-8.3.x-phpunit_5.7-2795317-14.patch, failed testing. View results

The last submitted patch, 14: drupal-8.4.x-phpunit_5.7-2795317-14.patch, failed testing. View results

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.

hswong3i’s picture

Revoke #14 patches via latest dev

The last submitted patch, 18: drupal-8.3.x-phpunit_5.7-2795317-18.patch, failed testing. View results

The last submitted patch, 18: drupal-8.4.x-phpunit_5.7-2795317-18.patch, failed testing. View results

hswong3i’s picture

StatusFileSize
new520.64 KB
new523.65 KB

Recreate drupal/core patches via https://github.com/drupal/core

dawehner’s picture

Issue tags: +phpunit initiative
StatusFileSize
new384 bytes

We obviously can't do this kind of change as long we require php 5.5 as lowest version. Here is an alternative suggestion, we could make "createMock" available in our version of phpunit, convert all of the cases ...

What are your thoughts about that?

Status: Needs review » Needs work

The last submitted patch, 22: 2795317-22.patch, failed testing. View results

hswong3i’s picture

Status: Needs work » Needs review

The minimal dependency on PHP >=5.5.9 for Drupal 8.x looks a bit crazy from today point of view, especial as PHP 5.5.x already EOL on 2016-07-21 which was one years ago...

Even PHP 7.0.x will go into Security Update Only since 2017-12-03, which maybe just 1 - 2 months after initial scheduled Drupal 8.4.x released on October...

Moreover, when I am running with composer update on Drupal 8.4.x, Doctrine Annotations will be upgraded to 1.5.0 with our current composer.json, which also depends on PHP 7.1.x...

IMHO, as mentioned on original request of this issue:

Drupal 8 should fully support PHP 7. PHP 7 includes the ability to type hint primitives, and explicitly declare the return type of methods:

public function foo(string $bar) : string {
  // Implementation here.
}

Therefore upgrading our Drupal minimal PHP requirement to 7.1.x and so using PHPUnit 5.x (or even PHPUnit 6.x for the best PHP 7.x support and functionality) whenever our next major/minor release on coming October should be a good idea for answering #22.

dawehner’s picture

The minimal dependency on PHP >=5.5.9 for Drupal 8.x looks a bit crazy from today point of view, especial as PHP 5.5.x already EOL on 2016-07-21 which was one years ago...

Even PHP 7.0.x will go into Security Update Only since 2017-12-03, which maybe just 1 - 2 months after initial scheduled Drupal 8.4.x released on October...

Well, I simply believe this doesn't matter here :) We have dedicated discussions for that, see #2670966: Warn users of old PHP versions. Just complaining here isn't necessarily constructive.

Moreover, when I am running with composer update on Drupal 8.4.x, Doctrine Annotations will be upgraded to 1.5.0 with our current composer.json, which also depends on PHP 7.1.x...

Indeed, see #2898119: Doctrine/Common 2.8 requires PHP ~7.1

Making big changes isn't easy.

dawehner’s picture

StatusFileSize
new1.53 KB

I'm sorry, I just realized I haven't uploaded the full patch before.

martin107’s picture

StatusFileSize
new1.54 KB
new1.39 KB

Regarding the bulk of the coding standard fails ...

We are at the interface between two coding standards. So I have no problem with the phpcs errors with regard to method arguments
as they are a clear copy of something from another project.

I am ONLY correcting the remaining little coding standard err.

I agree with dawehner's train of through line from #25 ...

Speaking for myself.. I regard any project not using php7 as broken.. but I want to solve our phpunit issue now.

I would like to see this issue get resolved as soon as possible.

lendude’s picture

Issue tags: +Needs issue summary update
StatusFileSize
new3.6 KB
new3.67 KB

Creating a forward compatibility layer sounds like a good idea here. It will allow us to get existing tests ready before we move to PHPUnit 5.

Updated the trait to have a proper docblock and added some more explanation to the trait. Also converted one instance of getMock to createMock as a proof of concept/test case.

The IS needs an update to reflect the current fix. And we might want to do a follow up to convert getMock to createMock everywhere.

lendude’s picture

StatusFileSize
new1.07 KB
new3.68 KB

Bleh

dawehner’s picture

+++ b/core/tests/Drupal/Tests/Phpunit5FCTrait.php
@@ -0,0 +1,50 @@
+   *
+   * @param string $originalClassName
+   *   Name of the class to mock.
+   * @param array|null $methods
+   *   When provided, only methods whose names are in the array are replaced
+   *   with a configurable test double. The behavior of the other methods is not
+   *   changed. Providing null means that no methods will be replaced.
+   * @param array $arguments
+   *   Parameters to pass to the original class' constructor.
+   * @param string $mockClassName
+   *   Class name for the generated test double class.
+   * @param bool $callOriginalConstructor
+   *   Can be used to disable the call to the original class' constructor.
+   * @param bool $callOriginalClone
+   *   Can be used to disable the call to the original class' clone constructor.
+   * @param bool $callAutoload
+   *   Can be used to disable __autoload() during the generation of the test double class.
+   * @param bool $cloneArguments
+   * @param bool $callOriginalMethods
+   * @param object $proxyTarget
+   *
+   * @return PHPUnit_Framework_MockObject_MockObject

Let's maybe put an @see on here, so its clear that this is just a wrapper for another function?

dawehner’s picture

+++ b/core/tests/Drupal/Tests/Phpunit5FCTrait.php
@@ -0,0 +1,50 @@
+ * This trait makes tests forward compatible with PHPUnit 5 and above.
+ *
+ * The getMock method is deprecated in PHPUnit 5 but the createMock method is
+ * not available in PHPUnit 4. To provide forward compatibility this trait
+ * provides the createMock method and uses getMock if this method is not
+ * available on the parent class.
+ */
+trait Phpunit5FCTrait {

I could imagine it would be helpful to link from here to the official phpunit docs ... sadly they have splitted up the docs into one changelog per release.

lendude’s picture

Issue summary: View changes
Issue tags: -Needs issue summary update
StatusFileSize
new2.98 KB
new3.01 KB

Moved the explanation from the trait docblock to the method docblock since we might want to add more method to this trait in the future and added the @see

Also had a thought, that it would make more sense to wrap getMock and not createMock, this way all existing tests don't need to be updated to be compatible with PHPUnit 5, they just are. And then we can clean them up at our convenience. Or will this not work?
Took out the test case because all test will now run through the Trait.

dawehner’s picture

Don't you want to be able to call to createMock in phpunit 4 environments?

lendude’s picture

Issue summary: View changes
StatusFileSize
new3.51 KB
new5.99 KB

As discussed on Slack:
lendude [10:50 AM]
maybe we want to do both, getMock wrapper for BC, createMock wrapper for FC?
dawehner [10:50 AM]
@lendude Oh yeah that makes sense!

so something like this?

dawehner’s picture

  1. +++ b/core/tests/Drupal/Tests/Phpunit5FCTrait.php
    @@ -0,0 +1,93 @@
    +   *
    +   * @see \PHPUnit_Framework_TestCase::getMock
    +   *
    +   * @return PHPUnit_Framework_MockObject_MockObject
    +   */
    +  public function getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false, $callOriginalMethods = false, $proxyTarget = null) {
    

    Should we deprecate getMock here already and point to createMock?

  2. +++ b/core/tests/Drupal/Tests/UnitTestCase.php
    @@ -18,6 +18,8 @@
     
    +  use Phpunit5FCTrait;
    +
    

    Maybe its also useful in the kernel test ... what do you think?

lendude’s picture

StatusFileSize
new2.48 KB
new6.41 KB

#35.1 yeah was thinking about that too, lets do it, added a CR for that https://www.drupal.org/node/2907725
#35.2 Less mocking being done there, but yeah we should add it there too.

Delayed action on #31, added a @see to the phpunit release announcement https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-f... so people can see why this is needed at all.

dawehner’s picture

Nice! I guess this patch will fail due to the deprecation error message. I fear we can't trigger the error for now, given that so many contrib/custom tests will break.

Status: Needs review » Needs work

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

lendude’s picture

Status: Needs work » Needs review
StatusFileSize
new1.79 KB
new6.95 KB

Yeah ok, the trigger_error was excessive. Took it out, and put the test case for createMock back in.

dawehner’s picture

+++ b/core/tests/Drupal/Tests/Phpunit5FCTrait.php
@@ -0,0 +1,99 @@
+  public function createMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false, $callOriginalMethods = false, $proxyTarget = null) {

Can we create a dedicated test so we can test this trait. Maybe we want to add more later?

jofitz’s picture

StatusFileSize
new2.8 KB
new6.89 KB

Corrected coding standards errors.

dawehner’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests
bircher’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new8.06 KB
new11.83 KB

I like tests.
And I also like to use PHPUnit 5 in my testsuite.

Attached some changes:
* Test for PHPUnit 5 is changed to test for the parent class and not the literal phpunit class.
* invoke the createMock on the parent instead of calling the method statically.
* Added tests.

dawehner’s picture

Thank you @bircher!

+++ b/core/tests/Drupal/Tests/Phpunit5FCTrait.php
@@ -89,10 +84,25 @@ public function getMock($originalClassName, $methods = array(), array $arguments
+  private function isPhpunit5() {
+    $parent = get_parent_class($this);
+    // Loop over the parents to find the parent of where the trait is used.
+    while (method_exists($parent, 'isPhpunit5')) {
+      $parent = get_parent_class($parent);
+    }
+    // Finally we are not checking the method defined in this trait.
+    return method_exists($parent, 'createMock');
+  }

I think we should add some documentation why this is needed: Subclassing of test classes

dawehner’s picture

Status: Needs review » Needs work
bircher’s picture

StatusFileSize
new12.3 KB
new1.38 KB

rerolled the patch with more comments.

bircher’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

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

bircher’s picture

Status: Needs work » Needs review
StatusFileSize
new12.3 KB
new759 bytes

no magic...

dawehner’s picture

One nice thing we could do is to upload a test patch which updates phpunit to 5.x and then run the testbot against that version. With that we would kinda prove that the trait actually works as expected.

bircher’s picture

StatusFileSize
new39.13 KB
new39.13 KB

good idea!
I was testing it in my contrib project development environment and it worked there.
I am not sure I didn't just break all sorts of things with the attached patch.

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

Status: Needs review » Needs work

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

lendude’s picture

Status: Needs work » Needs review
StatusFileSize
new35.59 KB

LOL, I'd just rolled this too, lets see if mine sticks.

Status: Needs review » Needs work

The last submitted patch, 54: 2795317-51-PHPUNIT-5.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

lendude’s picture

checkForUnintentionallyCoveredCode has been deprecated in PHPUnit 5, see https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-f...

So that needs to be changed to beStrictAboutCoversAnnotation apparently. Any way to do that in a patch? No idea how the bot builds its phpunit.xml

hswong3i’s picture

StatusFileSize
new22.2 KB

Reroll patch from #54, remove changes to composer.lock, for distribution (e.g. https://github.com/drustack/drustack-standard) to apply patches.

lendude’s picture

Status: Needs work » Needs review
StatusFileSize
new12.3 KB

Well I think #54 proves that our BC/FC layer works, none of the fails there have anything to do with that. It just means we need to do some additional work when we actually go to PHPUnit 5, but that's fine and out of scope here.

So I'd say #49 is the patch that needs review, reupping @birchers patch here to have the latest patch in the issue be the one that is under review.

hswong3i’s picture

StatusFileSize
new12.62 KB

Reroll patch from #49, also update composer.json with "phpunit/phpunit": "^5.0"

dawehner’s picture

Reroll patch from #49, also update composer.json with "phpunit/phpunit": "^5.0"

Note: The point of this issue is NOT to update phpunit itself. Phpunit 5 requires PHP7, so we can't use that at this given point in time.

mile23’s picture

andypost’s picture

mile23’s picture

@andypost: Yes, but we should be as close as possible to dropping PHP 5.5 at any moment. As @dawehner points out, this issue does not change PHPUnit versions.

mondrake’s picture

Priority: Normal » Critical
Issue tags: +PHP 7.2

I think this becomes critical in light of #2927806: Use PHPUnit 6 for testing when PHP version >= 7.2

dawehner’s picture

StatusFileSize
new12.12 KB

Just a reroll of the right patch :)

lendude’s picture

Status: Needs review » Reviewed & tested by the community

Reroll looks good, this Iooks ready to me.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Another little one to help us on the PHPUnit upgrade path - #2928249: Introduce a PHPUnit 6+ compatibility layer for Drupal\Tests\Listeners classes

  1. +++ b/core/tests/Drupal/Tests/Phpunit5FCTrait.php
    @@ -0,0 +1,114 @@
    +  public function getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE, $callOriginalMethods = FALSE, $proxyTarget = NULL) {
    +    return $this->createMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, $proxyTarget);
    +  }
    

    This should trigger a silenced deprecated error.

  2. +++ b/core/tests/Drupal/Tests/Phpunit5FCTrait.php
    @@ -0,0 +1,114 @@
    +    while (method_exists($parent, 'isPhpunit5')) {
    +      $parent = get_parent_class($parent);
    +    }
    

    This is not covered by the tests.

The approach looks sane and will help people move tests to whichever PHPUnit version we end up on.

alexpott’s picture

Assigned: Unassigned » alexpott

I'm going to roll the patch from #67 and also merge in #2928249: Introduce a PHPUnit 6+ compatibility layer for Drupal\Tests\Listeners classes which will also get us ready for PHPUnit 6 as this issue is about 5+

alexpott’s picture

Assigned: alexpott » Unassigned
Status: Needs work » Needs review
StatusFileSize
new4.48 KB
new12.72 KB

On looking at all the work to make the listeners 6+ compatible I decided against rolling it into here. Although to get PHPUnit truly 7.2 compatible we need to do that I think might be better to have narrower scoped issues.

Addressed #67 - I made the loop a little bit easier to understand as well and have added tests that fail when the loop is removed.

Status: Needs review » Needs work

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

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new12.24 KB
new1.73 KB

Hmmm the deprecation is not going to work unless we put it in the skipped deprecations since PHPUnit calls it itself in \PHPUnit_Framework_MockObject_MockBuilder...

    /**
     * Creates a mock object using a fluent interface.
     *
     * @return PHPUnit_Framework_MockObject_MockObject
     */
    public function getMock()
    {
        return $this->testCase->getMock(
            $this->type,
            $this->methods,
            $this->constructorArgs,
            $this->mockClassName,
            $this->originalConstructor,
            $this->originalClone,
            $this->autoload,
            $this->cloneArguments,
            $this->callOriginalMethods,
            $this->proxyTarget
        );
    }

Hmmm and skipping doesn't work either because that logic only fires for KernelTestBase/WebTestBase/BrowserTestBase. So fire the deprecation here but instead open a follow issue to fire a deprecation once core and it's use of PHPUnit does not use it. At least we tried :)

alexpott’s picture

StatusFileSize
new12.38 KB
new1.2 KB
+++ b/core/tests/Drupal/Tests/Phpunit5FCTrait.php
@@ -0,0 +1,110 @@
+    while (in_array(__TRAIT__, class_uses($parent), TRUE)) {
+      $parent = get_parent_class($parent);
+    }

This change was incorrect too. Because class_uses only return what the current class uses - not it and its parents. So I've reverted the code to #65. I've tried to improve the comment to be clearer about what is actually happening here.

The last submitted patch, 71: 2795317-71.patch, failed testing. View results

lendude’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community

@alexpott thanks for taking a look at this. The added test coverage and the updated comment address your feedback, so back to RTBC.

Added the purposefully not setting of the trigger_error() to the IS.

mondrake’s picture

Status: Reviewed & tested by the community » Needs review

@alexpott in #2927806-33: Use PHPUnit 6 for testing when PHP version >= 7.2 is using a combined patch including the one here, and he spotted a bug. Since we are targetting a PHPUnit 6 compatibility layer there I think this needs to wait until the various pieces of the puzzle come together

alexpott’s picture

@mondrake yep you're right...

    /**
     * Returns a test double for the specified class.
     *
     * @param string $originalClassName
     *
     * @return MockObject
     *
     * @throws Exception
     */
    protected function createMock($originalClassName)
    {
        return $this->getMockBuilder($originalClassName)
                    ->disableOriginalConstructor()
                    ->disableOriginalClone()
                    ->disableArgumentCloning()
                    ->disallowMockingUnknownTypes()
                    ->getMock();
    }

This is the createMock in PHPUnit 6 so we're going to need to do something a bit more complex with all the args to support that and use getMockBuilder() too.

dawehner’s picture

So we need a separate code path for PHPUnit 5 and 6?

alexpott’s picture

StatusFileSize
new3.12 KB
new13.82 KB

So here's a version that copes with the PHPUnit 6 changes to createMock and has been tested with it - see #2927806: Use PHPUnit 6 for testing when PHP version >= 7.2

@dawehner tbh I think we just skip PHPUnit 5 altogether.

mondrake’s picture

Just a note if we skip PHPUnit 5 altogether -

phpunit.xml.dist has

<phpunit bootstrap="tests/bootstrap.php" colors="true"
         beStrictAboutTestsThatDoNotTestAnything="true"
         beStrictAboutOutputDuringTests="true"
         beStrictAboutChangesToGlobalState="true"
         checkForUnintentionallyCoveredCode="false">

checkForUnintentionallyCoveredCode is deprecated in favor of beStrictAboutCoversAnnotation in PHPUnit 5.2.0 and was eventually removed in PHPUnit 6.0.

Since we'll be jumping from PHPUnit 4.8.36 to 6.5.2, this setting will become stale with no warnings unless we remember to do something about it (add a @todo?)

dawehner’s picture

+++ b/core/tests/Drupal/Tests/Phpunit5FCTrait.php
@@ -0,0 +1,147 @@
+trait Phpunit5FCTrait {

Let's rename it to Phpunit6FCTrait then?

alexpott’s picture

@dawehner well I'm pretty sure that the code would actually still work on PHPUnit 5 because it has the same MockBuilder class as 4 and 6 but I think you're right that renaming the trait is in order. Maybe to something like PHPUnitCompatibilityTrait? Atm this trait is providing stuff for both PHPUnit 4 and 6 so that you could use createMock() in PHPUnit 4 if you like too. That's actually one of the things I'm kinda unsure about - I like getting getMock() to work on PHPUnit 6 but do we really need to make createMock() work on PHPUnit 4?

Also if we have to support other newer versions of PHPUnit we might not be able to do it in the same trait so I can imagine some funky class aliasing in the future.

dawehner’s picture

but do we really need to make createMock() work on PHPUnit 4?

Well, it would have been a nice transition path for people switching over, but now that we seem to have made the decision to jump on a newer phpunit version anyway, this is indeed less helpful.

alexpott’s picture

Issue summary: View changes
StatusFileSize
new11.54 KB
new12.97 KB

I've done more thinking about #81 - I think we need to provide a createMock() in PHPUnit 4 that works like PHPUnit 6 and not change the behaviour of createMock() in PHPUnit 6 which is what the previous patches are doing. Once we do #2927806: Use PHPUnit 6 for testing when PHP version >= 7.2 then we can improve the test because we actually will be doing testing on different PHP Versions.

Patch attached renames things, completes and fixes the docs and changes the trait to use a supports() method instead to allow for other forward compatibility methods and to make it easier to grok what's happening.

The interdiff is not that useful cause renames.

mondrake’s picture

Status: Needs review » Reviewed & tested by the community

Renaming is good, keeps it open for the future (PHPUnit 7 is out in Feb 2018, and 8 planned for Feb 2019...).

I found supernits below, but in general this seems RTBC to me.

  1. +++ b/core/tests/Drupal/Tests/PhpunitCompatibilityTrait.php
    @@ -0,0 +1,142 @@
    +   * The getMock method is does not exist in PHPUnit 6. To provide backward
    

    'is' should go away

  2. +++ b/core/tests/Drupal/Tests/PhpunitCompatibilityTraitTest.php
    @@ -0,0 +1,113 @@
    + * Test class for \PHPUnit\Framework\TestCase in PHPUnit 5.
    

    PHPUnit 6

  3. +++ b/core/tests/Drupal/Tests/PhpunitCompatibilityTraitTest.php
    @@ -0,0 +1,113 @@
    + * Test class for \Drupal\Tests\UnitTestCase with PHPUnit 5.
    

    same

  4. +++ b/core/tests/Drupal/Tests/PhpunitCompatibilityTraitTest.php
    @@ -0,0 +1,113 @@
    + * Test class for \Drupal\Tests\UnitTestCase with PHPUnit 5.
    

    same

mondrake’s picture

Updated CR.

mondrake’s picture

Title: Allow PHPUnit 5+ support » Allow PHPUnit 6+ support for object mocking
alexpott’s picture

StatusFileSize
new1.86 KB
new12.97 KB

Addressing #84

larowlan’s picture

+++ b/core/tests/Drupal/Tests/PhpunitCompatibilityTraitTest.php
@@ -0,0 +1,113 @@
+ * @group simpletest

is this correct?

alexpott’s picture

@larowlan well we have lots of unit tests with this - like \Drupal\Tests\simpletest\Unit\TestDiscoveryTest and we have the other more generic Tests too.

+++ b/core/tests/Drupal/Tests/PhpunitCompatibilityTraitTest.php
@@ -0,0 +1,113 @@
+ * @group simpletest
+ * @group Tests

Our test groups are a bit of a mess. There are also tests in the group Test... confusing.

alexpott’s picture

StatusFileSize
new533 bytes
new12.94 KB

@larowlan mind you the only one outside simpletest module itself is \Drupal\Tests\AssertHelperTraitTest - so perhaps you're onto something. Anyway there is no harm in removing it and this does have nothing to do with Simpletest so one less thing to remove when simpletest is removed.

catch’s picture

+++ b/core/tests/Drupal/Tests/PhpunitCompatibilityTraitTest.php
@@ -0,0 +1,112 @@
+ * Test the PHPUnit forward compatibility trait.

Nit, but shouldn't this be 'Tests the', and if so that applies to method summaries for the rest of the file.

I really like the approach in general.

alexpott’s picture

StatusFileSize
new13.02 KB
new1.57 KB

Here's some updated docs. Thanks for the reviews @catch and @larowlan.

alexpott’s picture

I've updated the CR for the move to PHPUnit 6 and opened a followup #2929133: Replace all usages of getMock() to replace all our usages of getMock() so we can actually add an @trigger_error().

mile23’s picture

so we can actually add an @trigger_error()

I suggest that be an issue targeted to Drupal 9.1.0. :-)

larowlan’s picture

Adding mondrake to commit credits for reviews that helped shape the patch

larowlan’s picture

Queued testing on 5.5, 5.6 and 7.1.

Are we sure this a feature request?

A feature request can't be critical and a feature request can't go into the stable branch.

bircher’s picture

Category: Feature request » Bug report

Well it started out as a feature request, but with the advent of php 7.2 and its incompatibilities this becomes a bug of course.

mondrake’s picture

Looking back in the comments, what about #79? Anything to be done here, followup, nothing :)?

alexpott’s picture

@mondrake I think that that is part of the issue that makes us use PHPUnit 6... that happens in #2927806: Use PHPUnit 6 for testing when PHP version >= 7.2

mondrake’s picture

  • larowlan committed f320141 on 8.5.x
    Issue #2795317 by hswong3i, alexpott, Lendude, bircher, dawehner,...

  • larowlan committed f9a4241 on 8.4.x
    Issue #2795317 by hswong3i, alexpott, Lendude, bircher, dawehner,...
larowlan’s picture

Status: Reviewed & tested by the community » Fixed

Committed f320141 and pushed to 8.5.x.

As this is a critical bug, I cherry-picked as f9a4241 and pushed to 8.4.x.

Because we're not adding the trigger_error() here, this deprecation should have minimal disruption.

Published change record.

Updated the postponed issue to indicate this is in, see you there.

Thanks all

Status: Fixed » Closed (fixed)

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