summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2023-01-13 08:31:30 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-01-17 11:49:15 +0100
commit71d1203b07d3092062aa9ebc0ab198abfc144d54 (patch)
tree8ed6e2818f1db31e1f064f8a4317ca08ed360324
parentd6816bff73b37af05c968c009419c7c608e37307 (diff)
Refs #33348 -- Removed support for passing response object and form/formset name to SimpleTestCase.assertFormError()/assertFormSetError().
Per deprecation timeline.
-rw-r--r--django/test/testcases.py131
-rw-r--r--docs/releases/5.0.txt4
-rw-r--r--docs/topics/testing/tools.txt12
-rw-r--r--tests/test_utils/tests.py248
4 files changed, 6 insertions, 389 deletions
diff --git a/django/test/testcases.py b/django/test/testcases.py
index c37e99cded..23148537f5 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -1,5 +1,4 @@
import difflib
-import inspect
import json
import logging
import posixpath
@@ -42,7 +41,6 @@ from django.db import DEFAULT_DB_ALIAS, connection, connections, transaction
from django.forms.fields import CharField
from django.http import QueryDict
from django.http.request import split_domain_port, validate_host
-from django.http.response import HttpResponseBase
from django.test.client import AsyncClient, Client
from django.test.html import HTMLParseError, parse_html
from django.test.signals import template_rendered
@@ -53,7 +51,7 @@ from django.test.utils import (
modify_settings,
override_settings,
)
-from django.utils.deprecation import RemovedInDjango50Warning, RemovedInDjango51Warning
+from django.utils.deprecation import RemovedInDjango51Warning
from django.utils.functional import classproperty
from django.utils.version import PY310
from django.views.static import serve
@@ -168,127 +166,6 @@ class _DatabaseFailure:
raise DatabaseOperationForbidden(self.message)
-# RemovedInDjango50Warning
-class _AssertFormErrorDeprecationHelper:
- @staticmethod
- def assertFormError(self, response, form, field, errors, msg_prefix=""):
- """
- Search through all the rendered contexts of the `response` for a form named
- `form` then dispatch to the new assertFormError() using that instance.
- If multiple contexts contain the form, they're all checked in order and any
- failure will abort (this matches the old behavior).
- """
- warning_msg = (
- f"Passing response to assertFormError() is deprecated. Use the form object "
- f"directly: assertFormError(response.context[{form!r}], {field!r}, ...)"
- )
- warnings.warn(warning_msg, RemovedInDjango50Warning, stacklevel=2)
-
- full_msg_prefix = f"{msg_prefix}: " if msg_prefix else ""
- contexts = to_list(response.context) if response.context is not None else []
- if not contexts:
- self.fail(
- f"{full_msg_prefix}Response did not use any contexts to render the "
- f"response"
- )
- # Search all contexts for the error.
- found_form = False
- for i, context in enumerate(contexts):
- if form not in context:
- continue
- found_form = True
- self.assertFormError(context[form], field, errors, msg_prefix=msg_prefix)
- if not found_form:
- self.fail(
- f"{full_msg_prefix}The form '{form}' was not used to render the "
- f"response"
- )
-
- @staticmethod
- def assertFormSetError(
- self, response, formset, form_index, field, errors, msg_prefix=""
- ):
- """
- Search for a formset named "formset" in the "response" and dispatch to
- the new assertFormSetError() using that instance. If the name is found
- in multiple contexts they're all checked in order and any failure will
- abort the test.
- """
- warning_msg = (
- f"Passing response to assertFormSetError() is deprecated. Use the formset "
- f"object directly: assertFormSetError(response.context[{formset!r}], "
- f"{form_index!r}, ...)"
- )
- warnings.warn(warning_msg, RemovedInDjango50Warning, stacklevel=2)
-
- full_msg_prefix = f"{msg_prefix}: " if msg_prefix else ""
- contexts = to_list(response.context) if response.context is not None else []
- if not contexts:
- self.fail(
- f"{full_msg_prefix}Response did not use any contexts to render the "
- f"response"
- )
- found_formset = False
- for i, context in enumerate(contexts):
- if formset not in context or not hasattr(context[formset], "forms"):
- continue
- found_formset = True
- self.assertFormSetError(
- context[formset], form_index, field, errors, msg_prefix
- )
- if not found_formset:
- self.fail(
- f"{full_msg_prefix}The formset '{formset}' was not used to render the "
- f"response"
- )
-
- @classmethod
- def patch_signature(cls, new_method):
- """
- Replace the decorated method with a new one that inspects the passed
- args/kwargs and dispatch to the old implementation (with deprecation
- warning) when it detects the old signature.
- """
-
- @wraps(new_method)
- def patched_method(self, *args, **kwargs):
- old_method = getattr(cls, new_method.__name__)
- old_signature = inspect.signature(old_method)
- try:
- old_bound_args = old_signature.bind(self, *args, **kwargs)
- except TypeError:
- # If old signature doesn't match then either:
- # 1) new signature will match
- # 2) or a TypeError will be raised showing the user information
- # about the new signature.
- return new_method(self, *args, **kwargs)
-
- new_signature = inspect.signature(new_method)
- try:
- new_bound_args = new_signature.bind(self, *args, **kwargs)
- except TypeError:
- # Old signature matches but not the new one (because of
- # previous try/except).
- return old_method(self, *args, **kwargs)
-
- # If both signatures match, decide on which method to call by
- # inspecting the first arg (arg[0] = self).
- assert old_bound_args.args[1] == new_bound_args.args[1]
- if hasattr(
- old_bound_args.args[1], "context"
- ): # Looks like a response object => old method.
- return old_method(self, *args, **kwargs)
- elif isinstance(old_bound_args.args[1], HttpResponseBase):
- raise ValueError(
- f"{old_method.__name__}() is only usable on responses fetched "
- f"using the Django test Client."
- )
- else:
- return new_method(self, *args, **kwargs)
-
- return patched_method
-
-
class SimpleTestCase(unittest.TestCase):
# The class we'll use for the test client self.client.
@@ -711,9 +588,6 @@ class SimpleTestCase(unittest.TestCase):
self.assertEqual(field_errors, errors, msg_prefix + failure_message)
- # RemovedInDjango50Warning: When the deprecation ends, remove the
- # decorator.
- @_AssertFormErrorDeprecationHelper.patch_signature
def assertFormError(self, form, field, errors, msg_prefix=""):
"""
Assert that a field named "field" on the given form object has specific
@@ -738,9 +612,6 @@ class SimpleTestCase(unittest.TestCase):
)
return self.assertFormSetError(*args, **kw)
- # RemovedInDjango50Warning: When the deprecation ends, remove the
- # decorator.
- @_AssertFormErrorDeprecationHelper.patch_signature
def assertFormSetError(self, formset, form_index, field, errors, msg_prefix=""):
"""
Similar to assertFormError() but for formsets.
diff --git a/docs/releases/5.0.txt b/docs/releases/5.0.txt
index 9ae70cbf75..87755fdfc1 100644
--- a/docs/releases/5.0.txt
+++ b/docs/releases/5.0.txt
@@ -334,3 +334,7 @@ to remove usage of these features.
* The ``django.utils.timezone.utc`` alias to ``datetime.timezone.utc`` is
removed.
+
+* Passing a response object and a form/formset name to
+ ``SimpleTestCase.assertFormError()`` and ``assertFormSetError()`` is no
+ longer allowed.
diff --git a/docs/topics/testing/tools.txt b/docs/topics/testing/tools.txt
index 7c8dd39cfb..f3e5ec982f 100644
--- a/docs/topics/testing/tools.txt
+++ b/docs/topics/testing/tools.txt
@@ -1601,12 +1601,6 @@ your test suite.
which means that ``errors='error message'`` is the same as
``errors=['error message']``.
- .. deprecated:: 4.1
-
- Support for passing a response object and a form name to
- ``assertFormError()`` is deprecated and will be removed in Django 5.0.
- Use the form instance directly instead.
-
.. method:: SimpleTestCase.assertFormSetError(formset, form_index, field, errors, msg_prefix='')
Asserts that the ``formset`` raises the provided list of errors when
@@ -1624,12 +1618,6 @@ your test suite.
``field`` and ``errors`` have the same meaning as the parameters to
``assertFormError()``.
- .. deprecated:: 4.1
-
- Support for passing a response object and a formset name to
- ``assertFormSetError()`` is deprecated and will be removed in Django
- 5.0. Use the formset instance directly instead.
-
.. deprecated:: 4.2
The ``assertFormsetError()`` assertion method is deprecated. Use
diff --git a/tests/test_utils/tests.py b/tests/test_utils/tests.py
index f0c8735087..aa58b47a94 100644
--- a/tests/test_utils/tests.py
+++ b/tests/test_utils/tests.py
@@ -46,7 +46,7 @@ from django.test.utils import (
setup_test_environment,
)
from django.urls import NoReverseMatch, path, reverse, reverse_lazy
-from django.utils.deprecation import RemovedInDjango50Warning, RemovedInDjango51Warning
+from django.utils.deprecation import RemovedInDjango51Warning
from django.utils.log import DEFAULT_LOGGING
from django.utils.version import PY311
@@ -1383,44 +1383,6 @@ class TestFormset(formset_factory(TestForm)):
class AssertFormErrorTests(SimpleTestCase):
- @ignore_warnings(category=RemovedInDjango50Warning)
- def test_non_client_response(self):
- msg = (
- "assertFormError() is only usable on responses fetched using the "
- "Django test Client."
- )
- response = HttpResponse()
- with self.assertRaisesMessage(ValueError, msg):
- self.assertFormError(response, "form", "field", "invalid value")
-
- @ignore_warnings(category=RemovedInDjango50Warning)
- def test_response_with_no_context(self):
- msg = "Response did not use any contexts to render the response"
- response = mock.Mock(context=[])
- with self.assertRaisesMessage(AssertionError, msg):
- self.assertFormError(response, "form", "field", "invalid value")
- msg_prefix = "Custom prefix"
- with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
- self.assertFormError(
- response,
- "form",
- "field",
- "invalid value",
- msg_prefix=msg_prefix,
- )
-
- @ignore_warnings(category=RemovedInDjango50Warning)
- def test_form_not_in_context(self):
- msg = "The form 'form' was not used to render the response"
- response = mock.Mock(context=[{}])
- with self.assertRaisesMessage(AssertionError, msg):
- self.assertFormError(response, "form", "field", "invalid value")
- msg_prefix = "Custom prefix"
- with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
- self.assertFormError(
- response, "form", "field", "invalid value", msg_prefix=msg_prefix
- )
-
def test_single_error(self):
self.assertFormError(TestForm.invalid(), "field", "invalid value")
@@ -1523,35 +1485,6 @@ class AssertFormErrorTests(SimpleTestCase):
class AssertFormSetErrorTests(SimpleTestCase):
- @ignore_warnings(category=RemovedInDjango50Warning)
- def test_non_client_response(self):
- msg = (
- "assertFormSetError() is only usable on responses fetched using "
- "the Django test Client."
- )
- response = HttpResponse()
- with self.assertRaisesMessage(ValueError, msg):
- self.assertFormSetError(response, "formset", 0, "field", "invalid value")
-
- @ignore_warnings(category=RemovedInDjango50Warning)
- def test_response_with_no_context(self):
- msg = "Response did not use any contexts to render the response"
- response = mock.Mock(context=[])
- with self.assertRaisesMessage(AssertionError, msg):
- self.assertFormSetError(response, "formset", 0, "field", "invalid value")
-
- @ignore_warnings(category=RemovedInDjango50Warning)
- def test_formset_not_in_context(self):
- msg = "The formset 'formset' was not used to render the response"
- response = mock.Mock(context=[{}])
- with self.assertRaisesMessage(AssertionError, msg):
- self.assertFormSetError(response, "formset", 0, "field", "invalid value")
- msg_prefix = "Custom prefix"
- with self.assertRaisesMessage(AssertionError, f"{msg_prefix}: {msg}"):
- self.assertFormSetError(
- response, "formset", 0, "field", "invalid value", msg_prefix=msg_prefix
- )
-
def test_rename_assertformseterror_deprecation_warning(self):
msg = "assertFormsetError() is deprecated in favor of assertFormSetError()."
with self.assertRaisesMessage(RemovedInDjango51Warning, msg):
@@ -1762,185 +1695,6 @@ class AssertFormSetErrorTests(SimpleTestCase):
self.assertFormSetError(formset, 2, "field", "error")
-# RemovedInDjango50Warning
-class AssertFormErrorDeprecationTests(SimpleTestCase):
- """
- Exhaustively test all possible combinations of args/kwargs for the old
- signature.
- """
-
- def _assert_form_error_old_api_cases(self, form, field, errors, msg_prefix):
- response = mock.Mock(context=[{"form": TestForm.invalid()}])
- return (
- ((response, form, field, errors), {}),
- ((response, form, field, errors, msg_prefix), {}),
- ((response, form, field, errors), {"msg_prefix": msg_prefix}),
- ((response, form, field), {"errors": errors}),
- ((response, form, field), {"errors": errors, "msg_prefix": msg_prefix}),
- ((response, form), {"field": field, "errors": errors}),
- (
- (response, form),
- {"field": field, "errors": errors, "msg_prefix": msg_prefix},
- ),
- ((response,), {"form": form, "field": field, "errors": errors}),
- (
- (response,),
- {
- "form": form,
- "field": field,
- "errors": errors,
- "msg_prefix": msg_prefix,
- },
- ),
- (
- (),
- {"response": response, "form": form, "field": field, "errors": errors},
- ),
- (
- (),
- {
- "response": response,
- "form": form,
- "field": field,
- "errors": errors,
- "msg_prefix": msg_prefix,
- },
- ),
- )
-
- def test_assert_form_error_old_api(self):
- deprecation_msg = (
- "Passing response to assertFormError() is deprecated. Use the form object "
- "directly: assertFormError(response.context['form'], 'field', ...)"
- )
- for args, kwargs in self._assert_form_error_old_api_cases(
- form="form",
- field="field",
- errors=["invalid value"],
- msg_prefix="Custom prefix",
- ):
- with self.subTest(args=args, kwargs=kwargs):
- with self.assertWarnsMessage(RemovedInDjango50Warning, deprecation_msg):
- self.assertFormError(*args, **kwargs)
-
- @ignore_warnings(category=RemovedInDjango50Warning)
- def test_assert_form_error_old_api_assertion_error(self):
- for args, kwargs in self._assert_form_error_old_api_cases(
- form="form",
- field="field",
- errors=["other error"],
- msg_prefix="Custom prefix",
- ):
- with self.subTest(args=args, kwargs=kwargs):
- with self.assertRaises(AssertionError):
- self.assertFormError(*args, **kwargs)
-
- def _assert_formset_error_old_api_cases(
- self, formset, form_index, field, errors, msg_prefix
- ):
- response = mock.Mock(context=[{"formset": TestFormset.invalid()}])
- return (
- ((response, formset, form_index, field, errors), {}),
- ((response, formset, form_index, field, errors, msg_prefix), {}),
- (
- (response, formset, form_index, field, errors),
- {"msg_prefix": msg_prefix},
- ),
- ((response, formset, form_index, field), {"errors": errors}),
- (
- (response, formset, form_index, field),
- {"errors": errors, "msg_prefix": msg_prefix},
- ),
- ((response, formset, form_index), {"field": field, "errors": errors}),
- (
- (response, formset, form_index),
- {"field": field, "errors": errors, "msg_prefix": msg_prefix},
- ),
- (
- (response, formset),
- {"form_index": form_index, "field": field, "errors": errors},
- ),
- (
- (response, formset),
- {
- "form_index": form_index,
- "field": field,
- "errors": errors,
- "msg_prefix": msg_prefix,
- },
- ),
- (
- (response,),
- {
- "formset": formset,
- "form_index": form_index,
- "field": field,
- "errors": errors,
- },
- ),
- (
- (response,),
- {
- "formset": formset,
- "form_index": form_index,
- "field": field,
- "errors": errors,
- "msg_prefix": msg_prefix,
- },
- ),
- (
- (),
- {
- "response": response,
- "formset": formset,
- "form_index": form_index,
- "field": field,
- "errors": errors,
- },
- ),
- (
- (),
- {
- "response": response,
- "formset": formset,
- "form_index": form_index,
- "field": field,
- "errors": errors,
- "msg_prefix": msg_prefix,
- },
- ),
- )
-
- def test_assert_formset_error_old_api(self):
- deprecation_msg = (
- "Passing response to assertFormSetError() is deprecated. Use the formset "
- "object directly: assertFormSetError(response.context['formset'], 0, ...)"
- )
- for args, kwargs in self._assert_formset_error_old_api_cases(
- formset="formset",
- form_index=0,
- field="field",
- errors=["invalid value"],
- msg_prefix="Custom prefix",
- ):
- with self.subTest(args=args, kwargs=kwargs):
- with self.assertWarnsMessage(RemovedInDjango50Warning, deprecation_msg):
- self.assertFormSetError(*args, **kwargs)
-
- @ignore_warnings(category=RemovedInDjango50Warning)
- def test_assert_formset_error_old_api_assertion_error(self):
- for args, kwargs in self._assert_formset_error_old_api_cases(
- formset="formset",
- form_index=0,
- field="field",
- errors=["other error"],
- msg_prefix="Custom prefix",
- ):
- with self.subTest(args=args, kwargs=kwargs):
- with self.assertRaises(AssertionError):
- self.assertFormSetError(*args, **kwargs)
-
-
class FirstUrls:
urlpatterns = [path("first/", empty_response, name="first")]