Ticket #11603: assertFormsetError.diff

File assertFormsetError.diff, 20.6 KB (added by martin_speleo, 13 years ago)
  • AUTHORS

     
    211211    pradeep.gowda@gmail.com
    212212    Collin Grady <collin@collingrady.com>
    213213    Gabriel Grant <g@briel.ca>
     214    Martin Green
    214215    Simon Greenhill <dev@simon.net.nz>
    215216    Owen Griffiths
    216217    Espen Grindhaug <http://grindhaug.org/>
  • docs/topics/testing.txt

     
    14961496
    14971497    ``errors`` is an error string, or a list of error strings, that are
    14981498    expected as a result of form validation.
     1499 
     1500.. method:: TestCase.assertFormsetError(response, formset, form, field, errors, msg_prefix='')
    14991501
     1502    .. versionadded:: 1.4
     1503   
     1504    Asserts that the formset raises the provided list of errors when rendered.
     1505
     1506    ``formset`` is the name the ``Formset`` instance was given in the template
     1507    context.
     1508
     1509    ``form`` is the number of the form within the ``Formset``.  If ``form``
     1510    has a value of ``None``, non-form errors (errors you can access via
     1511    ``formset.non_form_errors()``) will be checked.
     1512
     1513    ``field`` is the name of the field on the form to check. If ``field``
     1514    has a value of ``None``, non-field errors (errors you can access via
     1515    ``form.non_field_errors()``) will be checked.
     1516
     1517    ``errors`` is an error string, or a list of error strings, that are
     1518    expected as a result of form validation.
     1519
    15001520.. method:: TestCase.assertTemplateUsed(response, template_name, msg_prefix='')
    15011521
    15021522    Asserts that the template with the given name was used in rendering the
  • docs/releases/1.4.txt

     
    192192* In the documentation, a helpful :doc:`security overview </topics/security>`
    193193  page.
    194194
     195* Added an `assertFormsetError` into the unittest framework
     196
    195197.. _backwards-incompatible-changes-1.4:
    196198
    197199Backwards incompatible changes in 1.4
  • django/test/testcases.py

     
    504504            self.fail(msg_prefix + "The form '%s' was not used to render the"
    505505                      " response" % form)
    506506
     507    def assertFormsetError(self, response, formset, form, field, errors,
     508                           msg_prefix=''):
     509        """
     510        Asserts that a formset used to render the response has a specific error.
     511
     512        For field errors specify the number of the form and the field.
     513        For non-field errors specify the number of the form and the field
     514        as None.
     515        For non-form errors specify form as None and the field as None.
     516        """
     517        if msg_prefix:
     518            msg_prefix += ": "
     519
     520        # Put context(s) into a list to simplify processing.
     521        contexts = to_list(response.context)
     522        if not contexts:
     523            self.fail(msg_prefix + 'Response did not use any contexts to '
     524                      'render the response')
     525
     526        # Put error(s) into a list to simplify processing.
     527        errors = to_list(errors)
     528
     529        # Search all contexts for the error.
     530        found_formset = False
     531        for i,context in enumerate(contexts):
     532            if formset not in context:
     533                continue
     534            found_formset = True
     535            for err in errors:
     536                if field is not None:
     537                    if field in context[formset].forms[form].errors:
     538                        field_errors = \
     539                                     context[formset].forms[form].errors[field]
     540                        self.assertTrue(err in field_errors,
     541                                msg_prefix + "The field '%s' on formset '%s', "
     542                                "form %d in context %d does not contain the "
     543                                "error '%s' (actual errors: %s)" %
     544                                        (field, formset, form, i, err,
     545                                        repr(field_errors)))
     546                    elif field in context[formset].forms[form].fields:
     547                        self.fail(msg_prefix + "The field '%s' "
     548                                  "on formset '%s', form %d in "
     549                                  "context %d contains no errors" %
     550                                        (field, formset, form,i))
     551                    else:
     552                        self.fail(msg_prefix + "The formset '%s', form %d in "
     553                                 "context %d does not contain the field '%s'" %
     554                                        (formset, form, i, field))
     555                elif form is not None:
     556                    non_field_errors = \
     557                                context[formset].forms[form].non_field_errors()
     558                    self.assertFalse(len(non_field_errors) == 0,
     559                                msg_prefix + "The formset '%s', form %d in "
     560                                "context %d does not contain any non-field "
     561                                "errors." % (formset, form, i))
     562                    self.assertTrue(err in non_field_errors,
     563                                    msg_prefix + "The formset '%s', form %d "
     564                                    "in context %d does not contain the "
     565                                    "non-field error '%s' "
     566                                    "(actual errors: %s)" %
     567                                        (formset, form, i, err,
     568                                         repr(non_field_errors)))
     569                else:
     570                    non_form_errors = context[formset].non_form_errors()
     571                    self.assertFalse(len(non_form_errors) == 0,
     572                                     msg_prefix + "The formset '%s' in "
     573                                     "context %d does not contain any "
     574                                     "non-form errors." % (formset, i))
     575                    self.assertTrue(err in non_form_errors,
     576                                    msg_prefix + "The formset '%s' in context "
     577                                    "%d does not contain the "
     578                                    "non-form error '%s' (actual errors: %s)" %
     579                                      (formset, i, err, repr(non_form_errors)))
     580        if not found_formset:
     581            self.fail(msg_prefix + "The formset '%s' was not used to render "
     582                      "the response" % formset)
     583
     584
    507585    def assertTemplateUsed(self, response, template_name, msg_prefix=''):
    508586        """
    509587        Asserts that the template with the provided name was used in rendering
  • tests/modeltests/test_client/views.py

     
    44from django.template import Context, Template
    55from django.http import HttpResponse, HttpResponseRedirect, HttpResponseNotFound
    66from django.contrib.auth.decorators import login_required, permission_required
    7 from django.forms.forms import Form
     7from django.forms.forms import Form, ValidationError
     8from django.forms.formsets import formset_factory, BaseFormSet
    89from django.forms import fields
    910from django.shortcuts import render_to_response
    1011from django.utils.decorators import method_decorator
     
    9192    value = fields.IntegerField()
    9293    single = fields.ChoiceField(choices=TestChoices)
    9394    multi = fields.MultipleChoiceField(choices=TestChoices)
     95    def clean(self):
     96        cleaned_data = self.cleaned_data
     97        if cleaned_data.get("text") == "Raise non-field error":
     98            raise ValidationError(u"Non-field error.")
     99        # Always return the full collection of cleaned data.
     100        return cleaned_data
    94101
    95102def form_view(request):
    96103    "A view that tests a simple form"
     
    127134        }
    128135    )
    129136
     137class BaseTestFormSet(BaseFormSet):
     138    def clean(self):
     139        """Checks that no two E-mail addresses are the same."""
     140        if any(self.errors):
     141               # Don't bother validating the formset unless each form is valid
     142               # (form.cleaned_data will not exist)
     143               return
     144        emails = []
     145        for i in range(0, self.total_form_count()):
     146            form = self.forms[i]
     147
     148            email = form.cleaned_data['email']
     149            if email in emails:
     150                raise ValidationError, \
     151                      "Forms in a set must have distinct E-mail addresses."
     152            emails.append(email)
     153
     154TestFormSet = formset_factory(TestForm, BaseTestFormSet)
     155
     156def formset_view(request):
     157    "A view that tests a simple formset"
     158    if request.method == 'POST':
     159        formset = TestFormSet(request.POST)
     160        if formset.is_valid():
     161            t = Template('Valid POST data.', name='Valid POST Template')
     162            c = Context()
     163        else:
     164            t = Template('Invalid POST data. {{ my_formset.errors }}',
     165                         name='Invalid POST Template')
     166            c = Context({'my_formset': formset})
     167    else:
     168        formset = TestForm(request.GET)
     169        t = Template('Viewing base formset. {{ my_formset }}.',
     170                     name='Formset GET Template')
     171        c = Context({'my_formset': formset})
     172    return HttpResponse(t.render(c))
     173
    130174def login_protected_view(request):
    131175    "A simple view that is login protected."
    132176    t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')
  • tests/modeltests/test_client/urls.py

     
    1717    (r'^bad_view/$', views.bad_view),
    1818    (r'^form_view/$', views.form_view),
    1919    (r'^form_view_with_template/$', views.form_view_with_template),
     20    (r'^formset_view/$', views.formset_view),
    2021    (r'^login_protected_view/$', views.login_protected_view),
    2122    (r'^login_protected_method_view/$', views.login_protected_method_view),
    2223    (r'^login_protected_view_custom_redirect/$', views.login_protected_view_changed_redirect),
  • tests/regressiontests/test_client_regress/models.py

     
    22"""
    33Regression tests for the Test Client, especially the customized assertions.
    44"""
     5from __future__ import with_statement
    56import os
    67import warnings
    78
     
    478479        except AssertionError, e:
    479480            self.assertIn("abc: The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )", str(e))
    480481
     482class AssertFormsetErrorTests(TestCase):
     483    msg_prefixes = [("", {}), ("abc: ", {"msg_prefix": "abc"})]
     484    def setUp(self):
     485        """Makes response object for testing field and non-field errors"""
     486        #For testing field and non-field errors
     487        self.response_form_errors = self.getResponse(
     488           {'form-TOTAL_FORMS': u'2',
     489            'form-INITIAL_FORMS': u'2',
     490            'form-0-text': 'Raise non-field error',
     491            'form-0-email': 'not an email address',
     492            'form-0-value': 37,
     493            'form-0-single': 'b',
     494            'form-0-multi': ('b','c','e'),
     495            'form-1-text': 'Hello World',
     496            'form-1-email': 'email@domain.com',
     497            'form-1-value': 37,
     498            'form-1-single': 'b',
     499            'form-1-multi': ('b','c','e'),
     500        })
     501        #For testing non-form errors
     502        self.response_nonform_errors = self.getResponse(
     503           {'form-TOTAL_FORMS': u'2',
     504            'form-INITIAL_FORMS': u'2',
     505            'form-0-text': 'Hello World',
     506            'form-0-email': 'email@domain.com',
     507            'form-0-value': 37,
     508            'form-0-single': 'b',
     509            'form-0-multi': ('b','c','e'),
     510            'form-1-text': 'Hello World',
     511            'form-1-email': 'email@domain.com',
     512            'form-1-value': 37,
     513            'form-1-single': 'b',
     514            'form-1-multi': ('b','c','e'),
     515        })
     516
     517    def getResponse(self, post_data):
     518        response = self.client.post('/test_client/formset_view/',
     519                                    post_data)
     520        self.assertEqual(response.status_code, 200)
     521        self.assertTemplateUsed(response, "Invalid POST Template")
     522        return response
     523
     524    def test_unknown_formset(self):
     525        "An assertion is raised if the formset name is unknown"
     526        for prefix, kwargs in self.msg_prefixes:
     527            with self.assertRaises(AssertionError) as cm:
     528                self.assertFormsetError(self.response_form_errors,
     529                                        'wrong_formset',
     530                                        0,
     531                                        'Some_field',
     532                                        'Some error.',
     533                                        **kwargs)           
     534            self.assertEqual(str(cm.exception),
     535                             prefix + "The formset 'wrong_formset' was not "
     536                             "used to render the response")
     537
     538    def test_unknown_field(self):
     539        "An assertion is raised if the field name is unknown"
     540        for prefix, kwargs in self.msg_prefixes:
     541            with self.assertRaises(AssertionError) as cm:
     542                self.assertFormsetError(self.response_form_errors,
     543                                        'my_formset',
     544                                        0,
     545                                        'Some_field',
     546                                        'Some error.',
     547                                        **kwargs)
     548            self.assertEqual(str(cm.exception),
     549                             prefix + "The formset 'my_formset', "
     550                             "form 0 in context 0 "
     551                             "does not contain the field 'Some_field'")
     552
     553    def test_noerror_field(self):
     554        "An assertion is raised if the field doesn't have any errors"
     555        for prefix, kwargs in self.msg_prefixes:
     556            with self.assertRaises(AssertionError) as cm:
     557                self.assertFormsetError(self.response_form_errors,
     558                                        'my_formset',
     559                                        1,
     560                                        'value',
     561                                        'Some error.',
     562                                        **kwargs)
     563            self.assertEqual(str(cm.exception),
     564                             prefix + "The field 'value' "
     565                             "on formset 'my_formset', form 1 "
     566                             "in context 0 contains no errors")
     567
     568    def test_unknown_error(self):
     569        "An assertion is raised if the field doesn't contain the specified error"
     570        for prefix, kwargs in self.msg_prefixes:
     571            with self.assertRaises(AssertionError) as cm:
     572                self.assertFormsetError(self.response_form_errors,
     573                                        'my_formset',
     574                                        0,
     575                                        'email',
     576                                        'Some error.',
     577                                        **kwargs)
     578            self.assertEqual(str(cm.exception),
     579                             prefix + "The field 'email' "
     580                             "on formset 'my_formset', form 0 "
     581                             "in context 0 does not contain the error "
     582                             "'Some error.' (actual errors: "
     583                             "[u'Enter a valid e-mail address.'])")
     584
     585    def test_field_error(self):
     586        "No assertion is raised if the field contains the provided error"
     587        for prefix, kwargs in self.msg_prefixes:
     588            self.assertFormsetError(self.response_form_errors,
     589                                'my_formset',
     590                                0,
     591                                'email',
     592                                'Enter a valid e-mail address.',
     593                                **kwargs)
     594
     595    def test_no_nonfield_error(self):
     596        "An assertion is raised if the formsets non-field errors doesn't contain any errors."
     597        for prefix, kwargs in self.msg_prefixes:
     598            with self.assertRaises(AssertionError) as cm:
     599                self.assertFormsetError(self.response_form_errors,
     600                                        'my_formset',
     601                                        1,
     602                                        None,
     603                                        'Some error.',
     604                                        **kwargs)
     605            self.assertEqual(str(cm.exception),
     606                             prefix + "The formset 'my_formset', form 1 in "
     607                             "context 0 does not contain any non-field errors."
     608                             )
     609
     610    def test_unknown_nonfield_error(self):
     611        "An assertion is raised if the formsets non-field errors doesn't contain the provided error."
     612        for prefix, kwargs in self.msg_prefixes:
     613            with self.assertRaises(AssertionError) as cm:
     614                self.assertFormsetError(self.response_form_errors,
     615                                        'my_formset',
     616                                        0,
     617                                        None,
     618                                        'Some error.',
     619                                        **kwargs)
     620            self.assertEqual(str(cm.exception),
     621                             prefix + "The formset 'my_formset', form 0 in "
     622                             "context 0 does not contain the non-field error "
     623                             "'Some error.' (actual errors: "
     624                             "[u'Non-field error.'])")
     625
     626    def test_nonfield_error(self):
     627        "No assertion is raised if the formsets non-field errors contains the provided error."
     628        for prefix, kwargs in self.msg_prefixes:
     629            self.assertFormsetError(self.response_form_errors,
     630                                'my_formset',
     631                                0,
     632                                None,
     633                                'Non-field error.',
     634                                **kwargs)
     635
     636    def test_no_nonform_error(self):
     637        "An assertion is raised if the formsets non-form errors doesn't contain any errors."
     638        for prefix, kwargs in self.msg_prefixes:
     639            with self.assertRaises(AssertionError) as cm:
     640                self.assertFormsetError(self.response_form_errors,
     641                                        'my_formset',
     642                                        None,
     643                                        None,
     644                                        'Some error.',
     645                                        **kwargs)
     646            self.assertEqual(str(cm.exception), prefix +
     647                             "The formset 'my_formset' in context 0 "
     648                             "does not contain any non-form errors.")
     649
     650    def test_unknown_nonform_error(self):
     651        "An assertion is raised if the formsets non-form errors doesn't contain the provided error."
     652        for prefix, kwargs in self.msg_prefixes:
     653            with self.assertRaises(AssertionError) as cm:
     654                self.assertFormsetError(self.response_nonform_errors,
     655                                        'my_formset',
     656                                        None,
     657                                        None,
     658                                        'Some error.',
     659                                        **kwargs)
     660            self.assertEqual(str(cm.exception), prefix +
     661                             "The formset 'my_formset' in context 0 does not "
     662                             "contain the non-form error 'Some error.' "
     663                             "(actual errors: [u'Forms in a set must have "
     664                             "distinct E-mail addresses.'])")
     665
     666    def test_nonform_error(self):
     667        "No assertion is raised if the formsets non-form errors contains the provided error."
     668        for prefix, kwargs in self.msg_prefixes:
     669            self.assertFormsetError(self.response_nonform_errors,
     670                                    'my_formset',
     671                                    None,
     672                                    None,
     673                                    'Forms in a set must have distinct E-mail '
     674                                    'addresses.',
     675                                    **kwargs)
     676
    481677class LoginTests(TestCase):
    482678    fixtures = ['testdata']
    483679
Back to Top