#35727: Add `response.text_content` to responses
------------------------------+-----------------------------------------
Reporter: Adam Johnson | Type: New feature
Status: new | Component: HTTP handling
Version: dev | Severity: Normal
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+-----------------------------------------
A common pattern in tests is to make assertions on the response content.
[
https://docs.djangoproject.com/en/stable/ref/request-
response/#django.http.HttpResponse.content HttpResponse.content] is
`bytes`, requiring a call to `.decode()` for assertions with `str` values:
{{{
class DiggerLogTests(TestCase):
def test_get(self):
response = self.client.get('/digger/logs')
assert 'Good digging' in response.content.decode()
assert '2022-01-01 12:00:00' in response.content.decode()
}}}
This is suboptimal for a few reasons:
* It requires extra code.
* Mixed bytes/str errors may confuse beginners.
* `decode()` imparts a small but measurable overhead, especially if
repeated for each assertion as above.
* `.decode()` defaults to UTF-8. Whilst this is by far the most common
encoding, the response may actually use a different encoding, as per
[
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
the content-type header].
I propose that responses from the test client include a new attribute,
called `text_content`. This would be cached property returning `content`
decoded into a `str`, per any `charset` in `content-type`.
This new attribute would allow the above test to be written as:
{{{
class DiggerLogTests(TestCase):
def test_get(self):
response = self.client.get('/digger/logs')
assert 'Good digging' in response.text
assert '2022-01-01 12:00:00' in response.text
}}}
`text_content` could be added either in `HttpResponse` directly or
attached by the test client, like `response.json()`. I favour the first
option a little more as it may come in useful outside of tests, and the
cache invalidation when `content` is mutated would be easier.
The new attribute could also be used to simplify `assertContains`,
[
https://github.com/django/django/blob/387475c5b2f1aa32103dbe21cb281d3b35165a0c/django/test/testcases.py#L586
which decodes on every call]
I have wanted this for a while and Simon Willison suggested this feature
[
https://x.com/simonw/status/1728104536898957425 to me on Twitter].
--
Ticket URL: <
https://code.djangoproject.com/ticket/35727>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.