Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
In #3131186-14: Replace assertions involving calls to drupalGetHeader() with session-based assertions, where possible we discovered we are missing a straightforward method to determine if a response's named header exists, or does not exist.
Proposed resolution
- Introduce WebAssert::responseHeaderExists and WebAssert::responseHeaderDoesNotExist methods.
- Use recommended PHPUnit assertion extensions logic with constraints and use of \PHPUnit\Framework\Assert::assertThat, instead of throwing exceptions.
- Use 'DoesNot{verb}' for the negative assertion since gut feeling says that will be the direction taken by PHPUnit for future developments, see https://github.com/sebastianbergmann/phpunit/issues/4067 and https://github.com/sebastianbergmann/phpunit/issues/4068 (and, actually, it *is* better readable).
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
Comment | File | Size | Author |
---|---|---|---|
#28 | interdiff.3133355.24-28.txt | 4.36 KB | longwave |
#28 | 3133355-28.patch | 6.85 KB | longwave |
#28 | 3133355-28-test-only.patch | 4.96 KB | longwave |
Comments
Comment #2
mondrakeStart here.
Comment #3
mondrakeComment #5
mondrakeon this
Comment #6
mondrakeWith tests. Conversions of existing tests could be done here, but I'd rather do them in #3131186: Replace assertions involving calls to drupalGetHeader() with session-based assertions, where possible.
Comment #7
mondrakeComment #8
mondrakeComment #9
jungleLooks great! two nitpicks:
Use {@inheritdoc} ?
Replace with stark? see [#3083055], classy is not recommended to use anymore.
Comment #10
jungleComment #11
mondrakeThanks @jungle. Fixed #9.
Comment #12
jungleTo me, the patch for 9.x is an RTBC and this should be eligible backporting to 8.x.
Comment #13
longwaveIs it worth the effort of creating brand new Constraint classes? If this was a new ResponseHeaderExists class then we can customise the "Failed asserting that an array has the key" message. Unfortunately ArrayHasKey is final so we can't just extend it, but Constraint is quite straighforward to implement.
Comment #14
longwaveTrying #13, unsure if this is overkill though - comments welcome.
This is ineligible for backport to 8.x due to the void return type not being compatible with PHP 7.0.
Comment #15
longwaveFixed a couple of minor errors in #14. Interdiff from #11.
Comment #16
jungleEven better, besides 3 coding standards messages
core/tests/Drupal/Tests/Constraints/ResponseHeaderExists.php
- line 52 Expected 1 blank line after function; 0 found
- line 53 The closing brace for the class must have an empty line before it
core/tests/Drupal/Tests/WebAssert.php
- line 15 Unused use statement
You are right.
Thank you @longwave!
Comment #17
ravi.shankar CreditAttribution: ravi.shankar at OpenSense Labs commentedHere I have added a patch which might address comment #16.
Comment #18
jungleThanks, @ravi.shankar! No more CS violations.
#17 is the one RTBCed, And this is ineligible to 8.x as @longwave said "due to the void return type not being compatible with PHP 7.0."
Comment #19
mondrakeReviewing.
Comment #20
mondrakeConceptually +1 for #13 and following, but I think we should do that in a separate issue, because:
Failed asserting that the {array_represents} has a {key_represents} named '{key_name}'.
In code, something like
or maybe using setters
so that the constraint can be re-used for other purposes.
namespace Drupal\TestTools\Constraint
.final
... this would have been a nice extension ofPHPUnit\Framework\Constrain\ArrayHasKey
.Comment #21
jungle@mondrake, thanks for your review!
Should proper design pattern(s) be taken into account here for reusing existed code? Such as: builder, decorator, composite etc.
Comment #22
mondrake#21 no idea - even stronger reason for a separate issue.
Comment #23
longwaveJust spotted that Symfony ships with some very similar constraints - e.g. https://github.com/symfony/http-foundation/blob/4.4/Test/Constraint/Resp... - but we can't use them directly because they expect a Symfony Response object which Mink doesn't use.
Comment #24
mondrakeFiled #3134671: Introduce a PHPUnit Constraint to check existence of a response header to deep dive into #13 and following, and reuploading #11 that was RTBC already.
Comment #25
xjmComment #26
xjmSo in #3131186-16: Replace assertions involving calls to drupalGetHeader() with session-based assertions, where possible, part of the reason we're introducing these methods is that a response header may exist but have a null value.
Based on that, I think that we should have test coverage that
responseHeaderExists()
passes if it exists and is set toNULL
, and thatresponseHeaderNotExists()
fails in the same circumstance.It tests quite a bit less than that. :) Let's give it a more specific name and document it?
Technically, these should both still have one-line summaries.
Documentation of
$message
is missing.Finally, can we include with the updated patch an updated test-only patch to expose the fails of the final version? Thanks!
Comment #27
longwave#26.2 None of WebAssert has tests. I think this class should exist with the aim to add further WebAssert tests to it in the future.
#26.3 There is an exception in our PHPunit coding standards: "PHPUnit tests MAY skip the PHPDoc summary line if their PHPDoc specifies a @coversDefaultClass"Actually does this only apply to the *class* comment and not the method comment?Comment #28
longwaveAddressed #26.1, #26.3, #26.4, Not sure what a test-only patch adds in this case, but uploading one anyway.
Comment #30
xjm@longwave, I hear all the time that such-and-such class is intended to be extended with more tests for X, and then it isn't. :) If the test is to be expanded, we'll want a followup issue that specifies adding other coverage to the test in order for that to be likely to happen. Thanks!
Comment #31
xjmCouple questions from reviewing this from an architectural standpoint rather than just "is this committable" tunnel vision:
Interesting, I did not notice before that this is a "Failure message" rather than the "Pass" message. Definitely upside-down from our historical tests, at least maybe the SimpleTest ones. Is that the convention for PHPUnit assertions and I just never realized?
Something I opened an issue for many, many years ago was to concatenate the user-supplied message (if any) with the default message, so that (a) people did not obscure real debugging with less specific or misleading messages but also (b) They could add more information without having to also ensure that the generic message details were included. That was back in pre-PHPUnit days, but it's still relevant to this patch.
I'm not sure how much we're trying to closely follow specific upstream conventions here, but it's worth considering at least whether that's something we'd want to do.
Comment #32
mondrake#30 I would need the test class in #3143870: Calls to AssertLegacyTrait::assertUrl() have wrong number of arguments to add a test for WebAssert::addressEquals to ensure that querystring, if present in the address to be tested, are taken into account.
Comment #33
mondrakeDid not mean to change to major, sorry.
Comment #34
mondrakeNot sure I understand what is still left to do here.
Comment #36
mondrakeRandom test failure in #35.
Comment #37
alexpottWe still need the followup to add tests for the rest of our methods in WebAssert - it would be great to add similar test coverage for them.
Also the questions in #31 have not been addressed
Comment #38
mondrakeFiled #3159783: [meta] Add tests for the WebAssert class.
#31.1 - there's no guidance in PHPUnit as to the
$message
argument. Actually, there's thinking to eventually remove them for good. See https://github.com/sebastianbergmann/phpunit/issues/4198. PHPUnit's default messages always start with 'Failed asserting that...' so they're somewhat negative. For Drupal we're proposing a convention in #3131946: [META] [policy] Remove PHPUnit assertion messages when possible, and standardize remaining messages.#31.2 - AFAICS in PHPUnit there's no way to concatenate default and custome message, they're two separate things that are both printed when a test fails. If no custom message is given, only the default is printed.
Comment #39
catchAll the feedback has been addressed, so I think this is ready to go in.
Committed 6e7d0d9 and pushed to 9.1.x. Thanks!