Problem/Motivation
As title
Proposed resolution
Example:
- $this->assertTrue(isset($ids['entity_test.entity_test.field_test_import']));
+ $this->assertNotNull($ids['entity_test.entity_test.field_test_import']);
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|
Issue fork drupal-3131807
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3131807-replace-assertions-involving
changes, plain diff MR !316
Comments
Comment #2
mondrakeNice one. Imho
A) need to make sure this is for arrays only (isset on scalar will not apply here)
B) besides checking the existence ofthe array key, we need to ensure also that the key value is not null, since it could be. Maybe we can just
assertNotNullinstead, if the array key is missing we will get an exception anywayComment #3
jungleThanks @mondrake. Updating IS and mentioning to remove redundant assertion messages
Comment #4
quietone commentedJust a wee start. This makes the changes to Unit tests. Used this to find the files to edit,
egrep -r "this->assert.+isset" core | grep Unit | awk -F: '{print $1}' | sort -u.Comment #6
jungle@quietone, thanks! BTW, 1 coding standards message
core/tests/Drupal/KernelTests/Core/Database/ConnectionUnitTest.php line 5 Unused use statement
Comment #7
spokjeQuick "Reroll-n-Run" patch attached (hopefully) fixing Test Failures and addressing #6
Comment #8
andrewsizz commentedreviewed patch - Looks good for me.
Comment #9
andrewsizz commentedno, in last patch missing return
Comment #10
andrewsizz commentedComment #11
spokje@AndrewsizZ All
assertfunctions returnvoid. A return isn't needed IMHO, if it fails it will throw an Exception. So I removed it on purpose.Comment #12
jungleThank you all!
@quietone already said it was just a start, and only made changes to Unit tests.
There are many more to do, checked with regex
assert.+issetgot over 100+ matches.Comment #13
quietone commentedAnother installment, still much work to do. I was working off the patch in #4 so the interdiff is against that.
For now I have restored the assertions in ConnectionUnitTest.php
Comment #14
andrewsizz commented@Junge, than you man
Do we have list of issues where we still need work?
Comment #15
jungleRe @AndrewsizZ
What I meant is this issue still having a lot of assertions to replace, as you can see from the new patch @quietone just uploaded.
About similar/relevant/sibling issues, you can check out the parent issue #3128573: [meta] Replace assertions with more appropriate ones for more if you are interested in.
Comment #17
quietone commentedI want to fix the tests before going further. So, fixing typos and stray characters.
Comment #18
quietone commentedAnother installments and this is enough for today on this.
Comment #19
mondrakePer #2.B,
in case you have
will result in
isset($links[0])return FALSE. SoassertTruewill fail. But,$linksDOES have a 0 key, soassertArrayHasKey(0, $links)will pass, which is wrong vs the original intention.I think in this case
$this->assertNotNull($links[0])would fit better here, because if the array has not the key 0 we will have an exception, if the key is there but associated to NULL, we would fail as well.Comment #21
spokjeWow, much work done there @quietone!
I've (tried to) fix(ed) 4 out of the 5 fails and the codesniffer issue.
The remaining failure is addressed by @mondrake in #19. I happily leave that to people with Bigger Brains than mine :)
Here's a patch based on #18
Comment #22
quietone commented@mondrake, thanks for getting me to think more about this. I don't like the idea of getting an exception in a test, I'd rather have assertions catch the errors.
But the point is that replacing assertions on isset() with just arrayHasKey/arrayNotHasKey won't work. isset does two checks, that the variable exists and that it is not NULL whereas arrayHasKey/arrayNotHasKey just checks that they key exists, using array_key_exists. To remove the isset() there needs to be two assertions, arrayHasKey/arrayNotHasKey followed by an assertNull/assertNotNull. However, that too is problematic. One needs to know if the test always fails on the existence or absence of the key or the value of the variable.
Just to see I changed two tests in ConnectionUnitTest.php:
But that works for this file. There could be other tests, in a loop, where the isset() fails in one case on the existence of the key and in other where it fails because the fail it NULL.
Comment #23
daffie commentedPatch looks good. I have 2 remarks:
Change is wrong. We should use
assertArrayNotHasKey().The removal of the return value for the methods
Drupal\KernelTests\Core\Database\ConnectionUnitTest::assertConnection(),Drupal\KernelTests\Core\Database\ConnectionUnitTest::assertNoConnection()andDrupal\Tests\system\Functional\Form\ConfirmFormTest::assertCancelLinkUrl()is not a problem, because those returns values are never used.Comment #24
jungleRe #23, see #3131946: [policy] Remove PHPUnit assertion messages when possible, and standardize remaining messages for more about the reason of removing redundant assertion messages.
Comment #25
daffie commented@jungle: Thank you for the answer.
I have looked at the issue and I also looked again at the patch from comment #21. The changes for the assert message text are for me correct.
Still open are comments #22 and #23.1.
Comment #26
spokjeReroll of patch in #21
Also addresses #23.1
Still needs addressing #22
Comment #27
sja112 commentedReroll of patch in #26
Still needs addressing #22
Comment #28
sja112 commentedAddressed #22.
Also includes change recommended by @xjm, https://www.drupal.org/project/drupal/issues/3128815#comment-13593362 [#25.1],
Comment #29
sja112 commentedUpdated the patch to fix a nitpick. Updated inline comments, included
// Verify that... (etc.).Comment #30
jungleThanks, @sja112 for working on this.
over 80 chars
Comment #31
sja112 commentedComment #32
sja112 commented@jungle addressed your review points.
Thanks!
Comment #33
jungleThanks, @sja112. All changes are wrong. see https://www.drupal.org/docs/develop/standards/api-documentation-and-comm...
If you are using PHPStorm, you can enable the 80 columns guideline.
Comment #34
sja112 commented@jungle,
Thanks for the review and suggestion.
I have addressed
#33 and updated the patch accordingly.
Please review.
Comment #35
jungleThanks again, but NW still.
must wrap AS CLOSE TO 80 CHARACTERS AS POSSIBLE WITHOUT GOING OVER
Examples:
// Verify that body field created when using the UI to create block content
// types.
// Verify that field has been deleted and needs purging before configuration
// synchronization.
// Verify that the field currently being deleted is not shown in the entity
// deletions.
Comment #36
sja112 commented@jungle,
I have gone through all the added strings.
I have fixed the #35.1, #35.3, and other related strings.
Haven't fixed #35.2 as the change was leading to 81 characters.
Hopefully, this change fixes all the issues.
Thanks!
Comment #37
sja112 commentedComment #38
jungleThanks, @sja112. assigning to myself to fix them.
Comment #39
jungleContinue addressing #35
Comment #40
mondrakeComment #41
mrinalini9 commentedComment #42
mrinalini9 commentedRerolled patch #39, please review.
Comment #43
daffie commentedPatch was rerolled.
I have only 1 remark:
Missing the "assertNotNull()" for this change.
Comment #44
daffie commentedSome more remarks:
Comment #45
hardik_patel_12 commentedAdding assertNotNull()
as suggested at #43.
Comment #46
naresh_bavaskarComment #47
naresh_bavaskarAddressed many of
assertTrue(isset*, assert(isset*as per #44 comment still there are occurrences which needs to be fixed
Comment #48
naresh_bavaskarComment #50
naresh_bavaskarPlease ignore #47 patch....it messed existing changes of #45...
Kindly consider #45 whoever picking and going ahead.
Comment #51
mohrerao commentedWorking on remaining replacements
Comment #52
msutharsI'm working on it.
Comment #53
pratik_kambleTagging for DIA contribution sprint.
Comment #54
mohrerao commentedApologies. Couldnt complete it earlier.
I did few more replacements and fixed failing tests.
@msuthars, Please review if possible.
Comment #55
mohrerao commentedFixed lint errors.
Comment #57
mohrerao commentedFixed failing tests and CS errors.
Comment #58
msutharsComment #59
mondrakeI understand that in this patch
assertTrue(isset())is generally converted to two separate assertions - aassertArrayHasKeyand aassertNotNull. Although a bit redundant (assertNotNull would fail if the array has not the key), fine with me. That needs to be done conistsently though.assertSame (invert the order of arguments)
'was' or 'is' created
same
needs a assertArrayHasKey also, for consistency
out of scope here
needs a assertNotNull also, for consistency
same
same
same
same
same
same
same
assertArrayHasKey - wrong method name, and misses assertNull
needs a assertArrayHasKey also, for consistency
out of scope
assertEquals
assertNotEmpty
add a
return TRUE;at the end, keep the return @bool in the doc. Removing the return is a good idea, but there's another issue for that.out of scope
Comment #60
ravi.shankar commentedWorking on this.
Comment #61
ravi.shankar commentedHere I have tried to made changes as suggested in comment #59, please review.
Comment #63
mondrakeshould be
$this->assertSame('Hiya!<br>', $build['#prefix'], 'A cached block without content is altered.');exceeds the 80 chars per row comment limit
$this->assertEquals($value, $elements[0]->getValue(), "Field $key is set to $value");
$this->assertNotEmpty($elements[0]->getAttribute('checked'), "Field $key is checked");
Comment #64
msutharsI'm working on the suggested changes and failed test cases.
Comment #65
msutharsUpdated the patch with suggested changes. Please review.
Comment #66
msutharsComment #67
mondrakeI tried grepping the code base with the following regexp,
>assert.*\(.*isset\(, and found 232 more results in 87 files. Maybe some are false positives, but at a first glance there are many that still can be converted.Nit:
This adds a whitespace at the end of the line.
Comment #68
msutharsComment #69
msutharsCovers almost isset(), but there some use case in which we can't replace them.
Comment #70
msutharsComment #71
msutharsRevert some isset() changes. Fixed test cases issue.
Comment #72
mondrake@msuthars I started reviewing #71 and there were too many unexpected changes. Here restarting from #65 that was almost ready IMHO. 137 more instances to check based on #67.
Comment #73
mondrakeComment #74
mondrakeComment #76
mondrakeComment #77
mondrakeComment #78
jungleThanks @mondrake for pushing this forward!
Fixing failed tests in #77
Above this assertFalse(), there is
$this->assertArrayNotHasKey('type', $data['entity_test_mul']);. The assertion assertFalse() is unnecessary to me, but instead of removing it, got it reverted.Comment #79
mondrakeThanks. Approx ~90 more cases to check.
Comment #80
mondrakeAlternative fixes for #78
Comment #81
mondrakeComment #82
mondrakeThis should be it, the remaining ones IMHO should stay as is.
Comment #84
mondrakeSome fixes.
Comment #85
mondrakeWhen
$this->xpathis used, it's enough to check if an element with the specific index exists in the array - no need to also check if it's not null.Comment #86
jungleThanks, @mondrake!
According to the output of
egrep -r "assert.+\(isset|assert.+\(\!isset"above after rerolled the patch, it looks like there are a few left to replace/double-check, marked ❌ at the end for those ones, FYI. Attaching the rerolled patch.Comment #87
mondrakeon this
Comment #88
mondrake./core/tests/Drupal/KernelTests/Core/Database/SelectComplexTest.php: $this->assertFalse(isset($tables['test']['all_fields']), 'Count query correctly unsets \'all_fields\' statement.');./core/modules/views/tests/src/Kernel/EventSubscriber/ViewsEntitySchemaSubscriberIntegrationTest.php: $this->assertFalse(isset($display['display_options']['fields']['id_broken']));./core/modules/views/tests/src/Unit/EntityViewsDataTest.php: $this->assertFalse(isset($data['entity_test_mul']['type']['relationship']));./core/modules/views/tests/src/Kernel/EventSubscriber/ViewsEntitySchemaSubscriberIntegrationTest.php: $this->assertFalse(isset($display['display_options']['fields']['id_broken']));in these cases, the array would miss even keys earlier than the last sub-key, the test would fail on missing index, so I preferred to keep as is for readibility
./core/modules/comment/tests/src/Functional/CommentEntityTest.php: $this->assertFalse(isset($settings['history']['lastReadTimestamps']) && in_array($term->id(), array_keys($settings['history']['lastReadTimestamps'])), 'history.lastReadTimestamps is present.');this and the other ones that have an ANDed assertion I'd rather leave to a follow-up
Comment #89
mondrakeComment #90
longwaveReviewed about half this before I ran out of steam. Detailed comments are below.
I have a feeling that this is getting too big and complicated to try and solve in one issue as there is a lot of subtle changes here and reviewing it is already hard. I suggest that we can break some of this out into separate issues:
assertTrue(... && ...)which can be broken into multiple assertionswhich would be much better off as $this->assertSession()->elementExists() or similar
The latter case I feel most strongly about, as all we are doing in this issue is rearranging assertTrue to assertArrayHasKey when in fact the assertion really feels like it should be rewritten entirely - elementExists is far more readable.
If we don't do any of those, or if it is still too big after that, how about breaking it down by test type, e.g. splitting out Kernel and Functional tests?
Do we need a followup to change this sort of thing to $this->assertSession()->linkByHrefExists()?
assertNotNull seems redundant here
assertNotNull seems redundant here
Is the not null check strictly necessary here? Feels better to either just assertArrayHasKey or also assert a specific type rather than just "not null".
Same
Same
Same
This feels like it should be assertInstanceOf
Same
Extracting $uuid to a variable might feel cleaner
Again I don't understand the not null check here. I realise that assertTrue(isset()) will do a non NULL check and assertArrayHasKey doesn't care if the value is NULL, but while that is the semantics of the existing test, is that really what was intended?
More like this that I think should just be e.g. $this->assertSession()->elementExists()?
Second comment just duplicates the first IMO
I wonder if a way of breaking this down is to do assertTrue(... && ...) in a separate issue? These are all quite similar and would simpler to get in.
I don't think we need to care about assertNotNull here if we are checking the type in the following loop.
Should we drop the $message arguments here?
Can headers even be NULL? I think they are always strings?
This would be so much more readable as some kind of elementExists check.
Did we miss the assertFalse() here?
Comment #91
mondrakeThanks a lot @longwave.
I agree, this has become too large for a single issue.
I’ll think a way to spin off some separate issues, the one for xpath to start with.
AFK at the moment, if anyone feels like taking that feel free.
Comment #92
mondrakeUnpostponed #3129002: Replace usages of deprecated AssertLegacyTrait::assert() since I think that's the better currently open issue where to start tackling
when that's agreed a lot of similar instance could be addressed similarly.
Comment #93
mondrakeComment #94
mondrakeComment #95
mondrakeJust a reroll.
Comment #97
mondrake#3166450: Split assertTrue using && into multiple assertions is in, maybe this can be worked on again
Comment #98
mondrakeActually no, this one is still too much overlapping with #3167880: [meta] Convert assertions involving use of xpath to WebAssert, where possible.
Comment #99
mondrakeA reroll anyway.
Comment #101
mondrakeRerolled and chenged to MR workflow
Comment #103
mondrakeRerolled
Comment #104
mondrakeComment #105
longwaveFixed all cases that I can find by looking for
>assert.*isset, except EntityFieldTest which I think makes more sense left alone and a few with complex boolean assertions.CommentEntityTest has been simplified to such an extent I'm not sure it was ever testing anything useful.
Comment #106
mondrakeI started reviewing the MR, then I realized we probably better discuss here first:
IMHO we should:
a) avoid using
assertArrayHasKey()with an immediately followingassertNotNull(). The latter also includes check for the former.b) revert the removals of the $message argument where it is supported by the method - we do not have any consensus to remove them massively and when we could get there we could have a separate issue.
Comment #107
longwaveAgree with both points. There is no need for two assertions;
assertNotNullwill also fail if the key doesn't exist. And yes, let's deal with the messages elsewhere. I think it's fair to replacet()orFormattableMarkupwith plain strings if you find it here though.Comment #108
longwaveI think all issues are addressed.
Pleased that we also found a bug in UserAccountFormFieldsTest here where we were testing a nonexistent form element all along.
Comment #109
daffie commentedThe testbot is failing.
Comment #110
longwaveFixed test failures, I hope.
Comment #111
mondrakeJust a few more checks please, then this is pretty much ready.
Comment #112
mondrakeFound a few more instances, in
core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.phpandcore/modules/views/tests/src/Unit/EntityViewsDataTest.phpComment #113
longwaveThanks for reviewing. I think I've fixed up everything except EntityFieldTest. I noted this in #105; to me this makes sense to leave as it is, as the comment above the section in question states "Test using isset(), empty() and unset()" and this is explicitly checking the magic methods
__isset()and friends on the entity field objects. Apart from the use of FormattableMarkup the test reads well to me and I think would lose readability by changing it to use other assertions.EntityViewsDataTest was a strange one, I have just deleted this assertion. It wasn't testing anything and should have been removed in https://git.drupalcode.org/project/drupal/-/commit/376fb615d7f862aade6e7... as far as I can see - the
typeproperty was removed fromentity_test_mulhere as were two other assertions checking this, but the negative assertion was left in place.The errors we have found while fixing this makes me think a good use of static analysis would be to detect asserting for non-existence in arrays when we don't assert for existence of the parent item first. This would have caught at least two bugs that were discovered here.
Comment #114
mondrakeThanks for the explanations @longwave. This looks great to me now. I'd be +1 on RTBC but I do not think I can set it myself.
Comment #115
longwaveI went through the whole patch as of #104 and fixed or upgraded parts that I thought needed to be changed, so to me that counts as a review of an earlier version. I think if you have reviewed the whole patch again since I made the recent changes, it's OK for you to mark RTBC - as it's quite a large set of changes I'm not sure if we will recruit anyone else to look at it before it ends up with merge conflicts.
Comment #116
mondrakeAgreed. Let’s see if core committers do as well.
Comment #117
mondrakeNeeds a reroll.
Comment #118
mondrakeRerolled, waiting for test run as recent runs were red
Comment #119
mondrakeon this
Comment #120
mondrakeFixed the test failure.
Comment #121
longwaveChanges by @mondrake look good to me. We only care about the header keys and not their values in the debug_cacheability_headers test (the header values themselves are tested in a number of elsewhere) so I think this change is OK.
Comment #122
mondrakeRerolled
Comment #123
mondrakeRerolled
Comment #124
mondrakeRerolled
Comment #125
mondrakeThere's one fail now
Comment #126
mondrakeFixed, one line was changed to comment in EntityViewsDataTest before being moved from Unit to Kernel, reflected here.
Comment #127
mondrakeThere's no explict input from core committers here, but I assume given the size of this patch it has to wait for a beta disruptive patch window.
Comment #128
longwaveBumping for visibility, patch still applies cleanly for me.
Comment #129
larowlanThis one needs a re-roll after the other three disruptive issues went in.
Tried a 3-way merge but to no avail.
Comment #130
mondrakeCorrected IS example, thanks @berdir on Slack
Comment #131
mondrakeRerolled. I agree with @Berdir a lot of these assertions should be improved with more strict checks, but I am afraid it will too big a change to be done here.
My suggestion would be to wait for #3131348: Replace assertions involving calls to empty() with assertEmpty()/assertNotEmpty()/assertArrayNotHasKey(), too, then have appropriate issues to convert instances of assertNotNull, assertArrayHasKey, assertNotEmpty with more strict ones.
Rome was not built in a day. :)
Comment #132
longwaveHad another scan through the MR and added some comments to ones. I think I agree with @Berdir here that the
assertNotNull()is not really meaningful in a lot of cases; it feels like eitherassertArrayHasKey()is what we really want in the simple case (especially if nearby weassertArrayNotHasKey()as well) or an actual value assertion if we want a more thorough test.There is a lot of good cleanup here - the response header and any xpath ones for example - but I wonder if we could maybe split the scope of this and that would make it easier to get in outside of a disruptive patch window and also give us more time to think about the non-trivial cases and fix them properly?
Comment #133
mondrakeAlright, let's make a meta of this issue then, and split issues with smaller scope.
Comment #135
mondrakeI have split the WebAssert changes into an issue of its own, #3253715: Replace assertions involving calls to isset() on xpath results in functional tests with WebAssert calls.
Comment #138
mondrakeA few things were fixed in spin-offs, and what's left out is probably not worth pursuing based on the comments. Wontfix then, if anyone disagrees please open a new issue with new scope. Thx
Comment #140
mondrakeProbably outdated is a better status.
Comment #141
longwaveClosing as fixed and assigning credit to all contributors.
Comment #142
longwave