#29098: Allow assertRedirects to handle regex matches.
-------------------------------------+-------------------------------------
Reporter: Dan J Strohl | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Testing framework | Version: 1.11
Severity: Normal | Resolution:
Keywords: unittest redirect | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Dan J Strohl):
Replying to [comment:3 Tim Graham]:
> It sounds like you'd like `assertRedirects()` to be able to do the
`reverse()` itself. I don't see much advantage to that (complicating
things by allowing `assertRedirects()` to take all the parameters of
`reverse()`). If I misunderstood, can you clarify what API change you're
proposing?
Ummm, not totally, the reverse() expects enough parameters to be able to
create the url, I am proposing being able to validate without knowing the
specific variables needed to complete the reverse.
basically, at something like the changes below... (all I did was pull out
the last assertion lines and put them into their own method.)
Taking this a bit further, you could also pull out the assertion for the
response codes and make them into their own assertion (which would be
called by the assertRedirects) and/or even put the code to pull the
response codes and response url into a helper function (like
"get_redirected_url(response, fetch_redirect_response=True)" ) further
modularizing it into even simpler pieces, and allowing for more
flexibility in usage.
{{{
#!div style="font-size: 80%"
Code highlighting:
{{{#!python
def _assertRedirects(self, response, expected_url, status_code=302,
target_status_code=200, msg_prefix='',
fetch_redirect_response=True):
"""
Assert that a response redirected to a specific URL and that the
redirect URL can be loaded.
Won't work for external links since it uses the test client to do
a
request (use fetch_redirect_response=False to check such links
without
fetching them).
"""
if msg_prefix:
msg_prefix += ": "
if hasattr(response, 'redirect_chain'):
# The request was a followed redirect
self.assertTrue(
len(response.redirect_chain) > 0,
msg_prefix + "Response didn't redirect as expected:
Response code was %d (expected %d)"
% (response.status_code, status_code)
)
self.assertEqual(
response.redirect_chain[0][1], status_code,
msg_prefix + "Initial response didn't redirect as
expected: Response code was %d (expected %d)"
% (response.redirect_chain[0][1], status_code)
)
url, status_code = response.redirect_chain[-1]
scheme, netloc, path, query, fragment = urlsplit(url)
self.assertEqual(
response.status_code, target_status_code,
msg_prefix + "Response didn't redirect as expected: Final
Response code was %d (expected %d)"
% (response.status_code, target_status_code)
)
else:
# Not a followed redirect
self.assertEqual(
response.status_code, status_code,
msg_prefix + "Response didn't redirect as expected:
Response code was %d (expected %d)"
% (response.status_code, status_code)
)
url = response.url
scheme, netloc, path, query, fragment = urlsplit(url)
# Prepend the request path to handle relative path redirects.
if not path.startswith('/'):
url = urljoin(response.request['PATH_INFO'], url)
path = urljoin(response.request['PATH_INFO'], path)
if fetch_redirect_response:
# netloc might be empty, or in cases where Django tests
the
# HTTP scheme, the convention is for netloc to be
'testserver'.
# Trust both as "internal" URLs here.
domain, port = split_domain_port(netloc)
if domain and not validate_host(domain,
settings.ALLOWED_HOSTS):
raise ValueError(
"The test client is unable to fetch remote URLs
(got %s). "
"If the host is served by Django, add '%s' to
ALLOWED_HOSTS. "
"Otherwise, use assertRedirects(...,
fetch_redirect_response=False)."
% (url, domain)
)
redirect_response = response.client.get(path,
QueryDict(query), secure=(scheme == 'https'))
# Get the redirection page, using the same client that was
used
# to obtain the original response.
self.assertEqual(
redirect_response.status_code, target_status_code,
msg_prefix + "Couldn't retrieve redirection page '%s':
response code was %d (expected %d)"
% (path, redirect_response.status_code,
target_status_code)
)
return url
def assertRedirects(self, response, expected_url, status_code=302,
target_status_code=200, msg_prefix='',
fetch_redirect_response=True):
url = self._assertRedirects(
response,
expected_url,
status_code=status_code,
target_status_code=target_status_code,
msg_prefix=msg_prefix,
fetch_redirect_response=fetch_redirect_response)
self.assertEqual(
url, expected_url,
msg_prefix + "Response redirected to '%s', expected '%s'" %
(url, expected_url)
)
def assertRedirectsRegex(self, response, expected_url_regex,
status_code=302,
target_status_code=200, msg_prefix='',
fetch_redirect_response=True):
url = self._assertRedirects(
response,
expected_url,
status_code=status_code,
target_status_code=target_status_code,
msg_prefix=msg_prefix,
fetch_redirect_response=fetch_redirect_response)
self.assertRegex(
url, expected_url_regex,
msg_prefix + "Response redirected to '%s', expected '%s'" %
(url, expected_url)
)
}}}
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/29098#comment:4>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/065.a18a40f301777e594b4f2cc40d1da325%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.