Skip to content
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

dev/core#4088 Convert api4 helper functionality to a trait & make available #25412

Merged
merged 5 commits into from
Jan 25, 2023

Conversation

eileenmcnaughton
Copy link
Contributor

Overview

Convert api4 helper functionality to a trait & make available

First - ask jenkins....

Before

What is the old user-interface or technical-contract (as appropriate)?
For optimal clarity, include a concrete example such as a screenshot, GIF (LICEcap, SilentCast), or code-snippet.

After

What changed? What is new old user-interface or technical-contract?
For optimal clarity, include a concrete example such as a screenshot, GIF (LICEcap, SilentCast), or code-snippet.

Technical Details

If the PR involves technical details/changes/considerations which would not be manifest to a casual developer skimming the above sections, please describe the details here.

Comments

Anything else you would like the reviewer to note

@civibot
Copy link

civibot bot commented Jan 24, 2023

No issue was found matching the number given in the pull request title. Please check the issue number.

@civibot
Copy link

civibot bot commented Jan 24, 2023

(Standard links)

@civibot civibot bot added the master label Jan 24, 2023
@eileenmcnaughton eileenmcnaughton force-pushed the api4trait branch 3 times, most recently from 2340aa8 to be7acd2 Compare January 24, 2023 22:13
unset($record);
$saved = civicrm_api4($entityName, 'save', $saveParams);
foreach ($saved as $item) {
$this->testRecords[] = [$entityName, [[$idField, '=', $item[$idField]]]];
Copy link
Member

Choose a reason for hiding this comment

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

Can this $testRecords property be extracted too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

as in setTestRecords & addTestRecord?

Copy link
Member

@totten totten Jan 24, 2023

Choose a reason for hiding this comment

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

As in public $testRecords = []; or protected $testRecords = [];

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm yeah ok - I'll add the getters & setters too if I'm going that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually - it can be private so I don't need them

* @param int $len
* @return string
*/
protected function randomLetters(int $len = 10): string {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is called from one child class - tbh I'd rather make it private & have that class do it's own thing

* @return array
* @throws \CRM_Core_Exception
*/
public function getRequiredValuesToCreate(string $entity, array &$values = []): array {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is protected as the Conformance calls it directly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we return $values - maybe we can not pass-by-ref as well....

*
* @package Civi\Test
*
* This trait defines a number of helper functions for testing APIv4.
Copy link
Member

Choose a reason for hiding this comment

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

I'd find it easier to understand with some kind of pointer about how to use the class. (Which of the 8 helpers should I care about?) Maybe like:

Suggested change
* This trait defines a number of helper functions for testing APIv4.
* Define helpers for generating, tracking, and cleaning test-data with APIv4. Specifically:
* - `createTestRecord()` will autofill a new record with example data.
* - `deleteTestRecords()` will batch-delete all the test-data created by `createTestRecord()`

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep - I think those might be the only ones we would encourage people to use so that's probably right - I'm trying to privatise as much else as I can

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@totten I've updated this but what I found is there are 2 functions

createTestRecord()
saveTestRecords()

I suppose that's consistent with apiv4 but it feels like they should use the same verb - given it would be work to change I am VERY happy to be convinced otherwise

Copy link
Member

Choose a reason for hiding this comment

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

Yea, they both use the APIv4 save action, so changing to saveTestRecord() would be more consistent all-round.

@seamuslee001
Copy link
Contributor

@eileenmcnaughton once you have resolved the comments from Tim I would say this is MOP

@eileenmcnaughton
Copy link
Contributor Author

@seamuslee001 thanks -

I got one fail - not sure if it is co-incidental or related - trying again

api\v4\Entity\ManagedEntityTest::testRevertSavedSearch
Failed asserting that '2023-01-24 22:33:06' is equal to '2023-01-24 22:33:07' or is greater than '2023-01-24 22:33:07'.

/home/jenkins/bknix-dfl/build/build-1/web/sites/all/modules/civicrm/tests/phpunit/api/v4/Entity/ManagedEntityTest.php:119
/home/jenkins/bknix-dfl/extern/phpunit8/phpunit8.phar:1721

@eileenmcnaughton
Copy link
Contributor Author

Hmm - well I made it worse there! Fortunately local fails too so I'll find & fix

It was doing both pass-by-ref and return to give back the value - this
settles on using return.
I'm not sure if the test fail was an intermittent or related but this seems cleaner
@eileenmcnaughton
Copy link
Contributor Author

@seamuslee001 @totten it is passing now - the only hesitation I have is #25412 (comment) - but that is also ok for a follow up if we dither

@colemanw
Copy link
Member

@eileenmcnaughton +1 on changing createTestRecord to saveTestRecord, but otherwise my only beef with this PR is that:

  • Before: saved test records would be automatically cleaned up during teardown; the author of the test doesn't have to think about it.
  • After: now the trait provides a cleanup function, but no guidance on how to use it.

I've seen a lot of unit-test authors struggle with the concept of cleanup. A lot of people try to clean stuff (if they do it at all) by putting some delete calls at the end of their test, which makes sense to a procedural thought-process but doesn't work for unit tests. I worry about people calling deleteTestRecords from within their tests, or forgetting to call it at all.
My recommendation would be to add a tearDown function to this trait. That will cause annoying collisions with any tearDown function implemented in a class using this trait, which IMO is a good thing because it forces the dev to think about cleanup! To resolve the conflict they can simply do:

use  Api4TestTrait {
  tearDown as testRecordTearDown;
}

public function tearDown() {
  $this->testRecordTearDown();
  // other stuff
}

@eileenmcnaughton
Copy link
Contributor Author

@colemanw ok - I think both the rename & the tearDown fix are going to each involve touching quite a few classes so I think it would be helpful if we can merge this first

@colemanw colemanw merged commit 4e14bc4 into civicrm:master Jan 25, 2023
@colemanw colemanw deleted the api4trait branch January 25, 2023 23:05
@totten
Copy link
Member

totten commented Jan 26, 2023

Yeah, I agree the tear-down protocol is the fiddly thing. Let's verbalize some options:

  1. Continue emphasizing Api4TestBase as the main way to use this. Do whatever you need to make it seem more official. Api4TestTrait is the more advanced tool (for someone wiring-up their own base-class).
  2. Encourage test-classes to resolve function conflicts (use Api4TestTrait { tearDown as testRecordTearDown; }).
  3. Move the cleanup into CiviTestListener. If a class includes Api4TestTrait, then automatically call deleteTestRecords().
  4. Move the cleanup into CiviTestListener. Automatically call setup/teardown functions based on prefixes. (Any test-trait can define a tear down - eg Api4TestTrait::tearDown_api4()).

#1 is simplest but doesn't go very far to encourage trait decomposition. #2+#3+#4 would go further to encouraging traits, but they're more complicated. #2 puts the complexity on the test-authors. #3+#4 put the complexity on the trait-authors.

@eileenmcnaughton
Copy link
Contributor Author

I took a look at another place the require_once is used and now I think we should rename the apiv4TestTrait - it really is just an EntityProviderTrait or something like that. There is nothing especially apiv4 about it. Given that it makes me think a bit differently - ie it's not an equivalent to the v3Trait

I also hit the fact that the test was using #25432 yet another class for managing custom fields - which feels like it should be combined with the more heavily used CRMTraits_Custom_CustomDataTrait and made generally available to extensions.

We have 10 traits in various stages of maturity in the tests directory - so I feel like we should be a bit clearer on what we are working towards than my initial 'this is like apiv3Trait' - although actually implementing feels out of scope of this round

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants