Skip to content

PHPLIB-294: Make test suite compatible with PHPUnit 6.4 #489

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 12, 2018

Conversation

kvwalker
Copy link
Contributor

@kvwalker kvwalker commented Feb 7, 2018

@kvwalker kvwalker requested a review from jmikola February 7, 2018 20:55
@@ -108,14 +110,34 @@ public function provideFileIdAndExpectedBytes()
];
}

public function provideFilteredFileIdAndExpectedBytes()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like there is no way to chain data providers so I thought this would be the most straightforward way to provide data to testReadBytesCalledMultipleTimes()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to avoid duplicating the datasets from provideFileIdAndExpectedBytes, you could either call that data provider and run its return value through array_filter. Altternatively, testReadBytesCalledMultipleTimes could just skip all datasets that don't apply with markTestSkipped. Not sure if any of those sound better to you, just providing some ideas.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like there is no way to chain data providers

Were you by chance reading about @depends? That's the only form of test chaining I'm aware of, where the return value of one test can be used as input for a subsequent test case.

Anywho, I think I mentioned using array_filter() earlier this week, which is exactly what @alcaeus is proposing here. Since provideFileIdAndExpectedBytes() returns an array of argument arrays, and we just want to filter out any argument arrays where the length (i.e. second argument) is zero by using an anonymous function as our filter callback:

function(array $args) { return $args[1] > 0; }

Using provideFileIdAndExpectedBytes() as the array_filter() input, each of its 20 argument arrays will be run through our callback and only those where the callback returns true will be kept. This allows us to re-use most of the existing data without duplicating it in the test sources.

@@ -27,6 +27,7 @@ public function testConstructorUpdateArgumentTypeCheck($update)

/**
* @dataProvider provideUpdateDocuments
* @doesNotPerformAssertions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL @doesNotPerformAssertions is a thing.

Perhaps we can use this for the Bucket and WritableStream testValidConstructorOptions() tests?

ReadableStream's testValidConstructorFileDocument() test looks OK with the change you made in this PR (also because no other tests appear to call ReadableStream::getFile()).

composer.json Outdated
@@ -16,7 +16,7 @@
"ext-mongodb": "^1.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36"
"phpunit/phpunit": "^6.4"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This causes the 5.x jobs on Travis to fail, since there is no longer a compatible version of PHPUnit:

  Problem 1
    - phpunit/phpunit 6.5.6 requires php ^7.0 -> your PHP version (5.6.32) does not satisfy that requirement.
    - phpunit/phpunit 6.5.5 requires php ^7.0 -> your PHP version (5.6.32) does not satisfy that requirement.
    - phpunit/phpunit 6.5.4 requires php ^7.0 -> your PHP version (5.6.32) does not satisfy that requirement.
    - phpunit/phpunit 6.5.3 requires php ^7.0 -> your PHP version (5.6.32) does not satisfy that requirement.
    - phpunit/phpunit 6.5.2 requires php ^7.0 -> your PHP version (5.6.32) does not satisfy that requirement.
    - phpunit/phpunit 6.5.1 requires php ^7.0 -> your PHP version (5.6.32) does not satisfy that requirement.
    - phpunit/phpunit 6.5.0 requires php ^7.0 -> your PHP version (5.6.32) does not satisfy that requirement.
    - phpunit/phpunit 6.4.4 requires php ^7.0 -> your PHP version (5.6.32) does not satisfy that requirement.
    - phpunit/phpunit 6.4.3 requires php ^7.0 -> your PHP version (5.6.32) does not satisfy that requirement.
    - phpunit/phpunit 6.4.2 requires php ^7.0 -> your PHP version (5.6.32) does not satisfy that requirement.
    - phpunit/phpunit 6.4.1 requires php ^7.0 -> your PHP version (5.6.32) does not satisfy that requirement.
    - phpunit/phpunit 6.4.0 requires php ^7.0 -> your PHP version (5.6.32) does not satisfy that requirement.
    - Installation request for phpunit/phpunit ^6.4 -> satisfiable by phpunit/phpunit[6.4.0, 6.4.1, 6.4.2, 6.4.3, 6.4.4, 6.5.0, 6.5.1, 6.5.2, 6.5.3, 6.5.4, 6.5.5, 6.5.6].

I'd suggest using "^4.8.36 || ^6.4", which should support PHP 5.x while still allowing PHP 7 to use PHPUnit 6. That syntax is discussed in Version Range in the Composer docs.

@@ -9,3 +9,5 @@
} else {
throw new Exception('Can\'t find autoload.php. Did you install dependencies with Composer?');
}

class_alias("PHPUnit\Framework\Error\Warning", "PHPUnit_Framework_Error_Warning");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to fail on PHPUnit 4 (PHP 5.x), as the original class (first argument) doesn't exist. You'll also get a warning because class_alias() will try to autoload that class and fail to find it (controlled by its third boolean argument).

Instead, I'd suggest using the PHPUnit 6 class names in our tests and only creating the alias when needed for compatibility with PHPUnit 4:

if ( ! class_exists('PHPUnit\Framework\Error\Warning')) {
    class_alias('PHPUnit_Framework_Error_Warning', 'PHPUnit\Framework\Error\Warning');
}

This condition should only be hit by PHPUnit 4, when the new class isn't found (even after an autoloading attempt). It will then create the PHPUnit\Framework\Error\Warning alias for the old PHPUnit_Framework_Error_Warning class, which will also be autoloaded by default.

AFAIK, the only references to "PHPUnit_Framework_Error_Warning" are in:

  • tests/GridFS/BucketFunctionalTest.php
  • tests/GridFS/SpecFunctionalTest.php

Most are in @expectedException annotations but at least one is a string.

@@ -108,14 +110,34 @@ public function provideFileIdAndExpectedBytes()
];
}

public function provideFilteredFileIdAndExpectedBytes()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like there is no way to chain data providers

Were you by chance reading about @depends? That's the only form of test chaining I'm aware of, where the return value of one test can be used as input for a subsequent test case.

Anywho, I think I mentioned using array_filter() earlier this week, which is exactly what @alcaeus is proposing here. Since provideFileIdAndExpectedBytes() returns an array of argument arrays, and we just want to filter out any argument arrays where the length (i.e. second argument) is zero by using an anonymous function as our filter callback:

function(array $args) { return $args[1] > 0; }

Using provideFileIdAndExpectedBytes() as the array_filter() input, each of its 20 argument arrays will be run through our callback and only those where the callback returns true will be kept. This allows us to re-use most of the existing data without duplicating it in the test sources.

@jmikola
Copy link
Member

jmikola commented Feb 8, 2018

We're skipping PHPUnit 5 entirely and are keeping PHPUnit 4 compat, so I might also rephrase the commit and PR as:

Make test suite compatible with PHPUnit 6.4

@jmikola jmikola changed the title PHPLIB-294: Make test suite compatible with PHPUnit 4.8, 5.7, and 6.4 PHPLIB-294: Make test suite compatible with PHPUnit 6.4 Feb 8, 2018
@@ -17,6 +17,9 @@
*/
class BucketFunctionalTest extends FunctionalTestCase
{
/*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing a second * in order to be considered a doc block. Without it, ReflectionFunction::getDocComment() is not able to pick it up for parsing by PHPUnit.

return $args[1] > 0;
}
);
return $filteredFiles;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be factored out so you simply return array_filter(...);.

@@ -19,6 +19,9 @@ public function setUp()
$this->collectionWrapper = new CollectionWrapper($this->manager, $this->getDatabaseName(), 'fs');
}

/*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also needs another *.


if ( ! class_exists('PHPUnit\Framework\Error\Warning')) {
class_alias('PHPUnit_Framework_Error_Warning', 'PHPUnit\Framework\Error\Warning');
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ensures that any reference to PHPUnit\Framework\Error\Warning will alias to PHPUnit_Framework_Error_Warning, which doesn't currently affect anything. The GridFS tests still use PHPUnit_Framework_Error_Warning, so they work for PHPUnit 4 but fail in 6.

See the renaming I suggested at the bottom of #489 (comment)

Copy link
Member

@jmikola jmikola left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting a rename of one test. LGTM otherwise.

@@ -40,7 +40,9 @@ public function setUp()

public function testValidConstructorFileDocument()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last minute request: can we change the test name to testGetFile()?

@kvwalker kvwalker merged commit a8b4862 into mongodb:master Feb 12, 2018
kvwalker added a commit that referenced this pull request Feb 12, 2018
@kvwalker kvwalker deleted the PHPLIB-294 branch February 12, 2018 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants