#30249: Deprecate re-raising view exceptions from test client in tests
-------------------------------------+-------------------------------------
Reporter: Jon Dufresne | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Testing framework | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Jon Dufresne):
Hi Carlton, thanks for the response.
> It's both longer ...
If you feel this is a matter of ergonomics, then I'm happy to add a helper
assert method. Something this like `assertResponseException` such that
{{{
response = self.client.get('/detail/author/invalid/qs/')
self.assertEqual(response.status_code, 500)
_, exc_value, _ = response.exc_info
self.assertIsInstance(exc_value, ImproperlyConfigured)
self.assertEqual(str(exc_value), msg)
}}}
Becomes:
{{{
response = self.client.get('/detail/author/invalid/qs/')
self.assertResponseException(response, response, msg)
}}}
I could then document it and use it throughout the Django test suite.
WDYT?
> ... and less clear in intent.
IMO, the previous version is less clear of the ''actual behavior'' under
test. If I didn't already know how the Django test client works, when
reading:
{{{
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.client.get('/detail/author/invalid/qs/')
}}}
Upon first read (again, if I didn't already know how the Django test
client works) this leads me to believe that making a GET request on the
provided URL results in an '''unhandled''' exception. However, this is not
the case. The exception is handled by the default error handler,
`django.core.handlers.exception.handle_uncaught_exception` and a 500
response is returned. Obviously, this is wrong as the test client has
modified the code under test to make it appear as if the exception is
unhandled. IMO, it is normally bad practice to modify the code under test
unless testing for a very specific implementation detail. It should not be
the default state of testing. Instead, we should be testing code as close
to production as reasonable. By modifying the code under test, we've
slightly moved away from the production code.
> Raising the exception is a great behaviour in most cases. It's a great
default behaviour.
Normally, I agree. But keep in mind, we're in the context of a test.
''Something'' will be asserted after the middleware + view executes
(otherwise, what's the point of the test?) It could even be something as
simple as `self.assertEqual(response.status_code, 200)`. In the event of
an unwanted view exception, these assertions will fail.
If you prefer the re-raising of exceptions for your project, then you can
and should set the existing setting `DEBUG_PROPAGATE_EXCEPTIONS` to `True`
in the test's `settings.py`. Then, the old behavior will be restored to
eagerly throw exceptions.
I've created an alternate form of the PR with this set during Django's
test suite here:
https://github.com/django/django/compare/master...jdufresne:raise-request-
exception-default-on
As you can see, this version has many fewer adjustments to tests. If this
version is more agreeable, I'm happy to replace the PR with it.
> The @override_settings(DEBUG_PROPAGATE_EXCEPTIONS=False) is bad API.
This setting already exits. I didn't invent it. It is documented here:
https://docs.djangoproject.com/en/2.1/ref/settings/#debug-propagate-
exceptions
I don't care much for this setting on its own, I only noticed that it
already existed so I didn't invent a new mechanism. Having multiple ways
to re-raise request exceptions seems unnecessary to me. I've never used it
prior to this PR.
> Beyond all that I don't think it's worth the churn.
To be clear, this isn't about churn. It is about moving the test client
closer to simulating a real world HTTP client by avoiding modifying code
under test, which I believe will result in more productive tests.
--
Ticket URL: <https://code.djangoproject.com/ticket/30249#comment:3>
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/067.05564a891b942810175f77c1f46ceed8%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.