Follow-up to #2560729: Cast objects implementing SafeStringInterface to string in TestBase / WebTestBase
In #2560729: Cast objects implementing SafeStringInterface to string in TestBase / WebTestBase we did not convert TestBase::assertIdentical(), so we will need to fix the tests themselves for comparisons where the comparison may include an object implementing SafeStringInterface.
Usuallly an equality check would be enough for a simple string comparison, or array comparison where the order doesn't matter. If the order of the array matters, we can use TestBase::castSafeStrings() before testing identicalness.
Beta evaluation: part of a major issue
| Comment | File | Size | Author |
|---|---|---|---|
| #56 | interdiff-53-56.txt | 2.21 KB | stefan.r |
| #56 | 2566447-56.patch | 40.14 KB | stefan.r |
| #53 | 48-53-interdiff.txt | 1.15 KB | alexpott |
| #53 | 2566447.53.patch | 38.89 KB | alexpott |
| #49 | 2566447.48.patch | 38.5 KB | alexpott |
Comments
Comment #2
stefan.r commentedfor review-ability it may be useful to post another patch that does explicit failures with the values of the compared variables in them - just so we can check that we don't lose test coverage by switching to assertEqual().
Comment #3
stefan.r commentedComment #4
stefan.r commentedAdding a few more that were also breaking
Comment #7
stefan.r commentedComment #8
stefan.r commentedComment #9
stefan.r commentedParent issue is green so seems we have them all now. Not sure the suggestion in #2 is even needed as these clearly didn't need to be identical checks. Maybe someone can do a manual review to confirm we're not losing any test coverage here?
Comment #10
joelpittet@stefan.r there may be a chance here that we are making a test less reliable to detect changes. I usually prefer identical if I can get away with it.
It would be nice to see how many of these are still failing and remove the unnecessary changes, what do you think?
Is this still needed?
Like all the format_date ones shouldn't need this right?
Comment #11
stefan.r commented@joelpittet I am aware of this potentially making tests less reliable but if we're comparing two arrays of strings where the order doesn't matter, or just two strings we often don't need to be doing an identical check...
I don't think any of these conversions are unnecessary, all of them were caused by specific test fails - neither are any failing anymore.
As to your review:
1. I believe we do need it - this is a case where an equality check would not be appropriate, as the comment says "Ensure the order is as expected. Should be sorted by label." So in those cases we can cast the safe strings and then check identicalness.
2. Maybe not all of them, but date_format can return a t()'ed string under some circumstances, and I remember at least one of those did.
Comment #12
stefan.r commentedTo help review-ability I've annotated the conversions. So as we think we have them all right, we can remove them and mark RTBC?
The views ones should arguably be identical checks if we want to check for the order (same for the CKEditor settings), but then we'd have to do an ugly $this->castSafeStrings() everywhere and assign the values to be compared to separate variables...
Comment #14
wim leersWe never do this, and it's really rather pointless, because that's already what the variable name indicates?
The changes in CKEditor look fine — I manually checked: https://3v4l.org/ei98N. I dislike that we're making tests less strict though, but if it's done for The Better Good overall, then +1.
Comment #15
stefan.r commented@WimLeers the pointless comments were added because the patch is otherwise unreview-able - they would be taken out later :)
But actually this is all way too complicated, @dawehner came up with a much more review-able solution:
Comment #16
stefan.r commentedComment #17
stefan.r commentedComment #20
stefan.r commentedComment #21
dawehnerIts sad that we need that, but hey, at least it adds some semanticness into our tests, which makes it clearer what is going on!
+1 for introducing a helper assertion.
Comment #22
joelpittetMy test results https://www.drupal.org/pift-ci-job/32267
Show this is not needed.
Comment #23
joelpittetThis removes some unnecessary changes. Here's the whole patch green #2465399-82: IGNORE: Patch testing issue
Comment #24
lauriiiWhy is these necessary? Array key can never be an object..
This should be @return bool
Comment #25
stefan.r commentedNice catch @lauriii, let's remove those as it'd just be confusing. That file had a search & replace for consistency back when we did assertEqual.
Comment #26
joelpittetFixes #24 thanks @lauriii
Comment #27
lauriiiThis is good for me. I tested all the changed tests locally with the fix given in #2557113: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list and a little custom logic so that it would fail if assertIdenticalWithSafeStrings is called for no reason.
I guess bool was added to wrong place. Can be fixed on commit
This is over 80chars. Can be also fixed on commit.
Comment #28
joelpittetWhoops, fixed that too. Thanks @lauriii
Comment #29
lauriiiChanges looks good so still RTBC :)
Comment #32
lauriiiUnrelated test fail. Drupal\user\Tests\UserCancelTest has GET http://ec2-54-191-110-230.us-west-2.compute.amazonaws.com/checkout/user/... returned 0 (0 bytes).
Comment #33
alexpottI'm not sure about this. Especially adding a method calling assertIdenticalAnything that actually doesn't assert identical-ness.
Discussed quickly with @xjm who said "it is a hack for bad tests"
I'm trying to think of alternatives.
Comment #34
stefan.r commentedHaving already thought about this a fair bit I think we should either keep it and rename it to something more "correct" or introduce another helper.
The helper is a hack, but it's a hack to work around PHP limitations and for developer convenience, where they want to compare an expected and an actual value without too much hassle, in cases where a simple equality check is not enough because of PHP, such as when the array order matters or type conversions matter.
The problem we mostly have is that when comparing two arrays we aren't actually interested in checking "identicalness" per se, but equality is not enough either. So we check for identicalness anyway because it does the job and meets our needs... as long as one of the arrays doesnt contain any safe string objects (which conceptually are no different than strings in /all/ of these comparisons).
So we should have a helper that caters to this use case - if not this helper, renamed, then another one. This will help us in writing future tests, as well as help contrib developers in test conversions (due to the parent) when they had used similar identicalness checks for the same reasons.
Comment #35
dawehnerI just had a look at many of those examples ...
So for example this case. Why do we care about identicalness at all? IMHO we care about equalness, in which case you can define a comparator for your own, in which the t() and ((string) t()) are equal.
Comment #36
stefan.r commentedYes, in most of those cases assertEqual() may have sufficed as well, even though PHP will say that ('foo' == TRUE) and (['foo' => 1, 'bar' => 1] == ['bar' => 1, 'foo' => 1]) and such.
We tried that in #8 and later but then we get into discussions about where we lose test coverage (as == is less strict), it makes the patch harder to review and it makes conversions for contrib harder as well, as it's more convenient to just change a function call where we compare something with t() in it than to make the larger effort of fixing the actual test.
Comment #37
alexpottI think we can fix
TestBase::castSafeStrings()to help us. And make it the responsibility of the test to call it. Also we should replaceassertIdenticalwhere it just is not necessary - for example - single element arrays where order is just not an issue.Comment #38
stefan.r commentedThat'll work as well, it's more explicit about where we are casting.
Comment #39
stefan.r commentedGave this a closer review and this looks fine to me, those equality conversions didn't need the identical-ness check as far as I can see.
My only remark is that in a lot of these cases
$expectedisn't really the value we expect to be identical to$actual(as we do with other helpers), as$expectedisn't really the value we're expecting, i.e. we're doing(f($expected) === f($actual))and ($expected !== $actual). But I think we can live with this, it's quite clear what we're doing.Comment #40
stefan.r commentedComment #41
alexpottThis is blocking #2557113: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list
Comment #42
dawehner+1, I mean we don't have locale module enabled on those tests anyway
Isn't the point that this works simply because we don't have a translation wrapper for t() in place yet? @see core/lib/Drupal/Core/Config/ConfigImporter.php:871 for example
Nitpick: I think we don't need this particular change, right?
What about expanding the unit test coverage here? Ideally we would have that particular method available as trait, so the other tests could profit from it as well
Comment #43
stefan.r commented1. Good!
2. assertEqual() ought to be fine here, right?
3. Reverted.
4. Added a
AssertionHelperTraitfor use inKernelTestBaseas well asTestBase, leaving this in the same namespace asAssertContentTrait.Comment #44
stefan.r commentedComment #45
dawehnerAh you are totally right about that.
Comment #47
joelpittetHad a review through the test changes and everything seems copacetic with me.
Casting seems a bit more explicit which is nice and leaves most of the identicals alone.
Comment #48
dawehnerWhile this for example certainly works, it feels wrong, because do we actually care about the identicalness (this is just one random example), or are actually just interested in the equalness. I totally agree that this is NOT the default of this patch, but I think we need to think more about these things. Some code probably just has it because it is more strict, without thinking whether its actually needed.
Thank you
Comment #49
alexpottNo use for SafeStringInterface so this does not work. Also AssertContentTrait and AssertionHelperTrait seems messy so renamed this to AssertHelperTrait. Added unit tests too.
Comment #50
stefan.r commented#49 looks great!
Comment #51
lauriiiChanges in #49 looks good. Also +1 for the new trait and the new version of castSafeStrings().
Comment #52
stefan.r commentedTested this in the parent and the var_export with TranslationWrappers in it causes problems. We'll need to have castSafeStrings() applied $first and $second there as well. If I get a green patch there I'll upload revised one here.
Comment #53
alexpottOkay fixed.
Comment #54
lauriiiShouldn't we remove the second castSafeStrings call from the assertion?
Comment #55
stefan.r commented#54 yes...
This may arguably out of scope here but let's see if we can fix DerivativeTest and InspectionTest here as well? It's adding a bit of noise in the parent issue and the assertEqual()/assertIdentical() calls have a problem with the TranslationWrappers introduced in Drupal\plugin_test\Plugin\MockBlockManager
Comment #56
stefan.r commentedSticking to just casting the labels in the block definitions. The t() in the ContextDefinitions for MockBlockManager also pose a problem but let's fix those in the parent. Tests are green so I think we're good to go here...
Comment #57
joelpittetBack to RTBC
Comment #58
xjmThat approach seems much better to me too.
Comment #59
wim leersThis looks great! And much better than earlier approaches indeed. Nothing to remark.
Comment #60
effulgentsia commentedI agree with both counts. In general, I don't like assertEqual(). PHPUnit's assertEquals() is better in that at least it corrects for
0 == 'foo'problems, but Simpletest's assertEqual(), which other than fixing for safe strings comes with all of PHP's==faults, is icky.But, I looked over all the ones in this patch and they all seem fine, so in the grand scheme of things, definitely better to unblock #2557113: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list, so I'll commit this shortly. First though, checking the credit boxes for @lauriii and @dawehner for their substantive reviews.
If anyone at any point is inspired to open issues to change any of these or other assertEqual() assertions to something stricter, please go for it.
Comment #61
effulgentsia commentedPushed to 8.0.x. Thanks for the great work on this and the careful reviews!
Comment #63
xjmI added this issue to the issues for https://www.drupal.org/node/2564451 -- can we update the third item there with a few different examples?