-
Notifications
You must be signed in to change notification settings - Fork 263
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
PHPLIB-1541: Include specs repository as a submodule #1429
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a pre-install/pre-update hook in composer.json to update the submodule? So that we don't have to think about it.
Added this command. I've used |
#### Handling test failures on updates | ||
|
||
Failures on updates can occur for multiple reasons, and the remedy to this will | ||
depend on the type of failure. Note that only tests for implemented | ||
specifications are run in the test runner. | ||
|
||
* If a specification is not fully implemented (e.g. a recent change to the spec | ||
has not been applied yet), skip the test in question with a reference to the | ||
ticket that covers the change | ||
* If a test fails because it uses features not yet implemented in the unified | ||
test runner, skip the corresponding test with a reference to the ticket that | ||
covers implementing the new features | ||
* If the test failure points to a bug in the spec, consider the effort required | ||
to fix the failure. If it's a small change, commit and push the fix directly | ||
to the pull request. Otherwise, skip the test with a reference to a ticket to | ||
fix the failing test. | ||
|
||
The goal is that the library passes tests with the latest spec version at all | ||
times, either by implementing small changes quickly, or by skipping tests as | ||
necessary. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jmikola this is a first shot at covering potential failures in a dependabot PR. Let me know if I missed something or if we should change the guidance. Either way, this would be a learning experience from us and might require some care when implementing spec changes (e.g. don't modify existing test cases when adding functionality).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The three bullets above seem sufficient.
I'm not sure what you mean by "don't modify existing test cases when adding functionality". I assume you're not talking about making custom modifications to the JSON files, as I've never done that (although I recall libmongoc has).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm referring to when changes are made in the specs repository. For example, new functionality should rely on new tests as much as possible, without changing existing tests. This allows skipping new tests without sacrificing code coverage because we'd have to skip a test that we were previously able to run.
e50458e
to
bdb64a7
Compare
Updated to include changes for PHPLIB-1458. |
6f1cac1
to
f40f9a6
Compare
@@ -38,6 +38,8 @@ class Prose22_RangeExplicitEncryptionTest extends FunctionalTestCase | |||
private ?Client $encryptedClient = null; | |||
private $key1Id; | |||
|
|||
private static string $specDir = __DIR__ . '/../../specifications/source/client-side-encryption'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason not to use a const
or readonly
here? Doesn't make much difference -- just curious. The important thing is that it's concise to reference later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No real reason other than using private static
in other places. Note that readonly
wouldn't work, as readonly
properties cannot have a default value but have to be initialised in the constructor.
I suppose we could change this property, as well as a number of other properties in UnifiedSpecTest private constants.
tests/UnifiedSpecTests/Operation.php
Outdated
@@ -235,6 +235,10 @@ private function executeForChangeStream(ChangeStream $changeStream) | |||
|
|||
private function executeForClient(Client $client) | |||
{ | |||
if ($this->name === 'clientBulkWrite') { | |||
Assert::markTestSkipped('clientBulkWrite operation is not implemented'); | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was going to ask why you implemented the check here, but then realized that Util::assertArgumentsBySchema()
asserts that that the operation is supported. That actually makes the switch
statement's default case unreachable; although I'm not sure if tooling is smart enough to not complain about that.
I do think we should revisit how we track skipped tests, as splitting logic between the Operation class and test runner will ultimately make things harder to track. I've long wanted to support regex patterns to avoid enumerating individual test files and cases. This kind of feature detection also makes sense, although it would ideally be consolidated in a single place. Opened PHPLIB-1540 to track that idea.
]; | ||
|
||
private static array $duplicateTests = ['crud/client bulkWrite partial results: partialResult is set when first operation fails during an unordered bulk write (summary)']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this is related to a non-unique test name. Consider adding a comment here, as this should ultimately be temporary and something we can revisit after enforcing uniqueness in the specs repo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Asked about the offending test in https://github.com/mongodb/specifications/pull/1665/files#r1790278528
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! This was fixed in the meantime, but I've kept the duplicateTests
variable as a quick way to skip tests in future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some suggestions but LGTM. Please create a ticket for this (and amend the commit message) before merging.
9604272
to
cb5f43f
Compare
cb5f43f
to
b0269f6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more suggestions/questions.
@@ -166,6 +184,7 @@ private function execute() | |||
$object = $this->entityMap[$this->object]; | |||
assertIsObject($object); | |||
|
|||
$this->skipIfOperationIsNotSupported($object::class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize Util::assertArgumentsBySchema()
accepts either a class name or Operation::OBJECT_TEST_RUNNER
; however, an internal skip method could solicit the object and operation names as strings (i.e. $o->object
and $o->name
). If so, it could be a static
method that's called immediately after the type assertions in the constructor:
assertIsString($o->name);
$this->name = $o->name;
assertIsString($o->object);
$this->isTestRunnerOperation = $o->object === self::OBJECT_TEST_RUNNER;
$this->object = $this->isTestRunnerOperation ? null : $o->object;
self::skipIfOperationIsNotSupported($o->object, $o->name);
Just a suggestion. Feel free to disregard if you prefer the current approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started implementing this approach, unfortunately the object we have here is not an actual object, but a name of an object in the entity map. Since this object may not even exist at the time the operation instance is created (e.g. if it's only created later using createEntities
), I also can't get a class name for the object being used. I'm afraid we'll have to skip when we get to execute
.
yield $group . '/' . $name => [$test]; | ||
$testKey = $testGroup . '/' . $name; | ||
|
||
if (isset($duplicateTests[$testKey])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I understand correctly that the duplicate test name is only a problem because PHPUnit asserts that the data provider yields unique keys?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is correct. PHPUnit asserts that each key is unique. While this was always true for arrays as data providers, using generators would allow one to yield the same key multiple times. I'm not sure why PHPUnit enforces this, but here we are 🤷
]; | ||
|
||
private static array $duplicateTests = ['crud/client bulkWrite partial results: partialResult is set when first operation fails during an unordered bulk write (summary)']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Asked about the offending test in https://github.com/mongodb/specifications/pull/1665/files#r1790278528
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with phpcs
warnings addressed.
@@ -14,8 +14,7 @@ | |||
use function basename; | |||
use function dirname; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note the phpcs
warnings for basename
and dirname
.
* v1.x: (101 commits) PHPLIB-1541: Include specs repository as a submodule (#1429) PHPLIB-1548 Inherit `typeMap` option in `Collection::listSearchIndexes()` (#1482) Fix array shape for `Collection::listSearchIndex($options)` (#1480) PHPLIB-1545: Deprecate CreateCollection flags option and related constants (#1477) Fix junit logging (#1475) Deprecate typeMap on operations without meaningful result (#1473) PHPLIB-1369 Upgrade to PHPUnit 10 (#1412) Higher phpunit version required (#1463) Fix deprecations in tests (#1458) Deprecate functionality to be removed (#1441) Expect BulkWriteException (#1455) Merge v1.20 into v1.x (#1447) PHPLIB-1525 Removes dependency to Symfony PHPUnit bridge (#1413) Change deprecated assertObjectHasAttribute to assertObjectHasProperty (#1432) Performance: Keep collections and indexes between GridFS tests (#1421) Add final annotations to non-internal Operation classes (#1410) Fix types accepted by $round (#1401) Replace arrayHasKey with assertArrayHasKey in tests (#1403) PHPLIB-1514 Make data providers static (#1404) PHPLIB-1515 Replace assertObjectHasAttribute with assertObjectHasProperty (#1405) ...
This is a proof of concept that I'd like to try out for a few weeks. The idea is to do away with manual spec test updates and automate the process in a simple manner. To achieve this, we include the specifications as a git submodule and run the tests directly from there. Using dependabot, we get a weekly PR to update the submodule if any changes have been merged, and as long as the build is green we can merge the PR and close any PHP tickets associated to the linked drivers tickets.
The downside to this is that all our specs will be at the same versions. It should be possible to leverage test skips to work around any issues, but only time will tell. Note that undoing this will be relatively straightforward: we can copy the last set of tests that passed to the original test locations, then revert all of the commits from this PR.