Problem/Motivation
In PHPUnit tests, we can use assertEquals() to compare MarkupInterface objects via the MarkupInterfaceComparator. Often, we only care about the text of the markup, and not the specific HTML tags.
Proposed resolution
This issue changes MarkupInterfaceComparator so it strips tags before comparing; this way only the text of the markup is considered for equality.
To provide a backward compatibility safety net, if both the expected and actual values contain markup (that is, the test is sensitive to the full markup and not just the text), a deprecation is issued informing the user that they should explicitly cast to string and use assertSame() instead.
Remaining tasks
User interface changes
None
API changes
In tests, assertEquals() will issue a deprecation if both the expected and actual values contain markup. Tests that are markup-sensitive should use assertSame() instead.
Data model changes
None
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #80 | 3153468-76.patch | 73 KB | mondrake |
| #80 | interdiff_73-76.txt | 993 bytes | mondrake |
Issue fork drupal-3153468
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:
- 3153468-remove-uses-of
changes, plain diff MR !1207
Comments
Comment #2
hardik_patel_12 commentedKindly review the patch.
Comment #3
meena.bisht commentedComment #4
meena.bisht commentedComment #5
meena.bisht commentedPlease find the below patch with the required changes.
Comment #6
meena.bisht commentedComment #7
hash6 commentedComment #9
naresh_bavaskarI think let's wait for https://www.drupal.org/project/drupal/issues/3131281 to be fixed then we should remove t() from
assertEqualsComment #10
hash6 commented@meena.bisht Thanks for the patch.
- Updated the patch with fixes for third argument in assertEqual().
@naresh_bavaskar
- As mentioned by Naresh, have removed just the t() from assertEqual() and other patch would update it to assertEquals()
If needed will re roll the patch once https://www.drupal.org/project/drupal/issues/3131281 is marked as fixed and commited.
Comment #11
hash6 commentedComment #12
mohrerao commentedFixed failing tests and missed removal of t() in assertTrue()
Comment #13
longwaveThe two strings here can be joined together rather than using the concatenation operator.
Why are we using string interpolation here when in other places we use concatenation?
Comment #14
ravi.shankar commentedHere I have tried to address comment #13.
Comment #15
mohrerao commented@longwave,
Comment #17
mohrerao commentedFixed failing test in #15
Comment #18
mohrerao commentedComment #19
longwaveNeeds reroll, and a few places seem to have been missed:
core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php
core/modules/views/tests/src/Functional/Plugin/DisplayTest.php
core/modules/file/tests/src/Kernel/FileManagedUnitTestBase.php
core/modules/file/tests/src/Functional/FileManagedTestBase.php
Comment #20
mohrerao commentedThanks for the review @longwave
Rerolled #17 and fixed missed files core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php
core/modules/views/tests/src/Functional/Plugin/DisplayTest.php
core/modules/file/tests/src/Kernel/FileManagedUnitTestBase.php
core/modules/file/tests/src/Functional/FileManagedTestBase.php
Comment #22
mohrerao commentedFixed failing test in #20
Comment #23
mohrerao commentedFixed CS issues in #22
Comment #24
longwaveThis looks almost there, I found two more cases:
Comment #25
naresh_bavaskarComment #26
naresh_bavaskaraddressed the #24 changes. Please review
Comment #27
longwaveLooking at the amount of calls to strip_tags() added here, wondering if we should either include the raw HTML in the expected string, or add a helper like
assertTextEquals()which calls strip_tags() on the actual value?Comment #30
longwaveIf #27 is making this too complicated we could split this out into two issues, one for
t()that don't use % arguments (as these cases should be simple) and then handle the ones that do use % arguments separately?Comment #31
mondrakeThis badly needs a reroll now,
assertEqual()is gone.+1 on #30, let's do first t() with no args where t() is one of the two compared variables, plus I'd say all the t() that are in the $message - these can be simply removed sometimes. The rest we can address later.
Comment #32
mondrakeBTW things like these could IMO just stay as-is, because $violations[] will be probably an array of t() objects built by the runtime code.
Comment #33
longwaveOpened #3226008: Remove simple uses of t() in assertEquals() calls for #31, postponing this on that.
Comment #34
longwave#33 is in, this just leaves about 75 cases that mostly use
t('%something')or are actual multilingual tests of t(). Maybe we just do nothing with these remaining ones?Regex for searching;
assertEquals.*\Wt\(Comment #36
mallezieFound 66 instances remaining. 23 of them were testing the t() function so those are not adjusted.
The other ones are adjusted. I compared values with the raw html instead of the strip_tags apporach, since the last one loses some of the assert testing (does not spot changed tags offcourse).
Comment #38
mallezieComment #39
vikashsoni commentedI test the patch but patch not working in 9.3.x-dev
Patch needs to re-roll
Comment #43
smustgrave commentedMR needs to be updated to 10.1
Comment #44
smustgrave commentedFor some reason couldn't create a branch off 10.1.x (says it doesn't exist)
So uploading a patch for 10.1
Comment #46
smustgrave commentedChanged some back as they were doing variable replacements.
Comment #48
smustgrave commentedThink it's a random layout builder javascript failure.
Comment #49
longwaveSent it for a retest, this all looks OK to me now, assuming it comes back green this time. After sitting on it for a while I think checking the full explicit string is better than using
strip_tags(), we are unlikely to ever change the placeholder HTML and if we consider it then the more test fails that it catches the better.Comment #50
mondrakeIf at least one of the expected or the actual value are a MarkupInterface object, our
MarkupInterfaceComparatorkicks in to evaluate theassertEquals. I wonder whether we should strip tags in the comparator instead.Comment #51
longwaveI think that's a dangerous assumption to make in the comparator, we probably want to explicitly test full markup in most cases? Tests can and should be specific about what they are testing, and I think adding "magic" in comparisons leads to difficulty later in understanding and maintaining the tests.
Comment #52
mondrakeI see your point @longwave, but we already went half way with magic and assumptions introducing our own comparator that resolves MarkupInterface objects to strings.
It all goes back to the intent of each test assertion IMHO. If the intent is to check that two texts are equal, then we should not care of HTML tags that are added in. That was the intent covered by the introduction of the comparator, and it would make sense to me to enhance the comparator to strip tags before comparing. So that we have something like:
Viceversa, if the intent is to verify the actual markup, we should be stricter: use
assertSame()and cast explicitly to string the actual MarkupInterface object:Comment #53
longwaveYeah, it comes down to what "equals" means when markup is involved, and that is not clearly defined either way. However I think that stripping tags in the comparator would be a BC break? Maybe worth a test patch to see how much is broken? Or, as suggested in #27, we could add something like
assertTextEquals()to strip tags first?Comment #54
mondrakeHere's a test patch. Let's see.
Comment #55
longwaveThe issue with this is that we might just be comparing two empty strings in some cases now, which invalidates the test? Should we add an extra check for this?
Comment #57
mondrake@longwave not sure I grasp #55, can you please elaborate?
Comment #58
longwaveImaginary test case:
With
strip_tags()in the comparator, this is now just comparing two empty strings, so if we later breakoutputHtml()in some way, the test will still pass as a false positive?Again this is really just defining what "equals" means in terms of markup, but I don't think we can assume that all existing cases should consider only the text from the markup.
We could possibly try calling
strip_tags()on $actual, only if $expected contains no tags? Or only if it is a MarkupInterface object? But that seems like even more "magic" behaviour.Comment #59
mondrakeSo the problem would be when BOTH expected and actual values contain HTML tags and we may be expecting them to be significant in the comparison. Let's try this. Note that if we now compare with stripped values, assertEquals will test successfully when differences are in the markup tags only (different tags will no longer differentiate), so we leave to the deprecation to notify the need to tighten the test.
Comment #61
mondrakeIf BOTH expected and actual are MarkupInterface though, we should not flag it... no need to test MarkupInterface itself here. So this only applies between a string and a MarkupInterface object.
Comment #63
mondrakeI tried to fix some of the test failures and, look, I start liking the concept a lot...
Comment #65
mondrakeI am pausing now. Waiting for feedback.
Comment #66
longwaveI like it! This simplifies the more basic assertions but forces us to explicitly say in the test whether markup is significant or not in more complex cases. It would also be good to add extra cases to MarkupInterfaceComparatorTest to cover this change.
Comment #67
mondrakeWill do. Thanks!
Comment #68
mondrakeAdded CR placeholder https://www.drupal.org/node/3334057
Comment #69
mondrakeComment #70
mondrakeComment #71
mondrakeComment #72
mondrakeAdded tests extra cases to MarkupInterfaceComparatorTest.
Comment #73
mondrakespell fixes
Comment #74
smustgrave commentedChanges look good.
Comment #75
longwaveLooks great - one nitpick that could go either way:
I think it's somewhat less verbose to just use
strval()?or if you want to be more strictly typed
Comment #76
longwave...so while this solves the issue of assertEquals() comparing markup, it no longer solves the actual issue of removing
t()inassertEquals()- there are a whole bunch of cases left:Comment #77
xjmSo the title and IS don't seem to be describing what's actually being done in this issue.
The scope of the parent meta was intended to be removing unnecessary direct uses of
t()and friends in test fixture data. However, this issue's primary scope seems to be that of convertingassertEquals()calls toassertSame()(and therefore adding a string cast on passed-in markup objects, wheret()is already not called directly in the assertions).If the goal is to remove use of
assertEquals()with translatable strings and markup objects, then the IS should be completely rewritten and the issue retitled.Thanks for working on this!
Comment #78
smustgrave commentedWith such a large number of changes would it make sense to breakup?
Comment #79
longwaveI don't think it can be broken up easily but we might want to spin off a child issue for the changes to
MarkupInterfaceComparatorand then come back here to fix theassertEquals()calls.Comment #80
mondrakeAddressed #75.
Comment #81
xjm@smustgrave, actually this issue is about the perfect size for a mostly 1:1 replacement on a single line that requires some limited thinking about each change. Edit: There is relevant text in the issue scope policy section on patch side.
FWIW re: #77, I chatted with @longwave about this. The current scope is fine if we update the title and IS, but we would need a followup for the original scope?
Comment #82
mondrake#80 xposted with #76, reset status to NW.
Comment #83
longwaveOpened #3337295: Remove remaining uses of t() in assertEquals() calls to handle the remainder, and retitled and updated the IS of this issue.
The change record still needs work.
Comment #84
mondrakeFleshed the CR.
Comment #85
smustgrave commentedReviewed the change record and looks great. The examples were super helpful
Comment #86
longwaveRTBC +1, the change record is nice and clear to me.
edit: I didn't work on this directly so could actually commit it, but would like another core committer opinion on the changes first.
Comment #87
catch+1 from me.
Comment #89
longwaveCommitted and pushed c187cc6339 to 10.1.x. Thanks!