Skip to content

Commit

Permalink
Fixed #15838 -- Promoted assertFieldOutput to a general test utility.…
Browse files Browse the repository at this point in the history
… Thanks to Ramiro Morales for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16653 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
freakboy3742 committed Aug 23, 2011
1 parent 46ef298 commit 2664fa1
Show file tree
Hide file tree
Showing 47 changed files with 167 additions and 161 deletions.
58 changes: 54 additions & 4 deletions django/test/testcases.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@

from django.conf import settings
from django.core import mail
from django.core.exceptions import ValidationError
from django.core.management import call_command
from django.core.signals import request_started
from django.core.urlresolvers import clear_url_caches
from django.core.validators import EMPTY_VALUES
from django.db import (transaction, connection, connections, DEFAULT_DB_ALIAS,
reset_queries)
from django.forms.fields import CharField
from django.http import QueryDict
from django.test import _doctest as doctest
from django.test.client import Client
Expand Down Expand Up @@ -271,6 +274,53 @@ def assertRaisesMessage(self, expected_exception, expected_message,
return self.assertRaisesRegexp(expected_exception,
re.escape(expected_message), callable_obj, *args, **kwargs)

def assertFieldOutput(self, fieldclass, valid, invalid, field_args=None,
field_kwargs=None, empty_value=u''):
"""
Asserts that a form field behaves correctly with various inputs.
Args:
fieldclass: the class of the field to be tested.
valid: a dictionary mapping valid inputs to their expected
cleaned values.
invalid: a dictionary mapping invalid inputs to one or more
raised error messages.
field_args: the args passed to instantiate the field
field_kwargs: the kwargs passed to instantiate the field
empty_value: the expected clean output for inputs in EMPTY_VALUES
"""
if field_args is None:
field_args = []
if field_kwargs is None:
field_kwargs = {}
required = fieldclass(*field_args, **field_kwargs)
optional = fieldclass(*field_args, **dict(field_kwargs, required=False))
# test valid inputs
for input, output in valid.items():
self.assertEqual(required.clean(input), output)
self.assertEqual(optional.clean(input), output)
# test invalid inputs
for input, errors in invalid.items():
with self.assertRaises(ValidationError) as context_manager:
required.clean(input)
self.assertEqual(context_manager.exception.messages, errors)

with self.assertRaises(ValidationError) as context_manager:
optional.clean(input)
self.assertEqual(context_manager.exception.messages, errors)
# test required inputs
error_required = [u'This field is required.']
for e in EMPTY_VALUES:
with self.assertRaises(ValidationError) as context_manager:
required.clean(e)
self.assertEqual(context_manager.exception.messages, error_required)
self.assertEqual(optional.clean(e), empty_value)
# test that max_length and min_length are always accepted
if issubclass(fieldclass, CharField):
field_kwargs.update({'min_length':2, 'max_length':20})
self.assertTrue(isinstance(fieldclass(*field_args, **field_kwargs), fieldclass))

class TransactionTestCase(SimpleTestCase):
# The class we'll use for the test client self.client.
# Can be overridden in derived classes.
Expand Down Expand Up @@ -356,8 +406,8 @@ def _post_teardown(self):
# be created with the wrong time).
# To make sure this doesn't happen, get a clean connection at the
# start of every test.
for connection in connections.all():
connection.close()
for conn in connections.all():
conn.close()

def _fixture_teardown(self):
pass
Expand Down Expand Up @@ -552,9 +602,9 @@ def assertQuerysetEqual(self, qs, values, transform=repr):

def assertNumQueries(self, num, func=None, *args, **kwargs):
using = kwargs.pop("using", DEFAULT_DB_ALIAS)
connection = connections[using]
conn = connections[using]

context = _AssertNumQueriesContext(self, num, connection)
context = _AssertNumQueriesContext(self, num, conn)
if func is None:
return context

Expand Down
21 changes: 21 additions & 0 deletions docs/topics/testing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,7 @@ basic functionality like:

* Saving and restoring the Python warning machinery state.
* Checking that a callable :meth:`raises a certain exeception <TestCase.assertRaisesMessage>`.
* :meth:`Testing form field rendering <assertFieldOutput>`.

If you need any of the other more complex and heavyweight Django-specific
features like:
Expand Down Expand Up @@ -1523,6 +1524,26 @@ your test suite.
failure. Similar to unittest's ``assertRaisesRegexp`` with the difference
that ``expected_message`` isn't a regular expression.

.. method:: assertFieldOutput(self, fieldclass, valid, invalid, field_args=None, field_kwargs=None, empty_value=u'')

Asserts that a form field behaves correctly with various inputs.

:param fieldclass: the class of the field to be tested.
:param valid: a dictionary mapping valid inputs to their expected cleaned
values.
:param invalid: a dictionary mapping invalid inputs to one or more raised
error messages.
:param field_args: the args passed to instantiate the field.
:param field_kwargs: the kwargs passed to instantiate the field.
:param empty_value: the expected clean output for inputs in ``EMPTY_VALUES``.

For example, the following code tests that an ``EmailField`` accepts
"a@a.com" as a valid email address, but rejects "aaa" with a reasonable
error message::

self.assertFieldOutput(EmailField, {'a@a.com': 'a@a.com'}, {'aaa': [u'Enter a valid e-mail address.']})


.. method:: TestCase.assertContains(response, text, count=None, status_code=200, msg_prefix='')

Asserts that a ``Response`` instance produced the given ``status_code`` and
Expand Down
12 changes: 1 addition & 11 deletions tests/regressiontests/forms/localflavor/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1 @@
from django.forms import EmailField
from utils import LocalFlavorTestCase

class AssertFieldOutputTests(LocalFlavorTestCase):

def test_assert_field_output(self):
error_invalid = [u'Enter a valid e-mail address.']
self.assertFieldOutput(EmailField, {'a@a.com': 'a@a.com'}, {'aaa': error_invalid})
self.assertRaises(AssertionError, self.assertFieldOutput, EmailField, {'a@a.com': 'a@a.com'}, {'aaa': error_invalid + [u'Another error']})
self.assertRaises(AssertionError, self.assertFieldOutput, EmailField, {'a@a.com': 'Wrong output'}, {'aaa': error_invalid})
self.assertRaises(AssertionError, self.assertFieldOutput, EmailField, {'a@a.com': 'a@a.com'}, {'aaa': [u'Come on, gimme some well formatted data, dude.']})
#
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/ar.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from django.contrib.localflavor.ar.forms import (ARProvinceSelect,
ARPostalCodeField, ARDNIField, ARCUITField)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class ARLocalFlavorTests(LocalFlavorTestCase):
class ARLocalFlavorTests(SimpleTestCase):
def test_ARProvinceSelect(self):
f = ARProvinceSelect()
out = u'''<select name="provincias">
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/at.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from django.contrib.localflavor.at.forms import (ATZipCodeField, ATStateSelect,
ATSocialSecurityNumberField)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class ATLocalFlavorTests(LocalFlavorTestCase):
class ATLocalFlavorTests(SimpleTestCase):
def test_ATStateSelect(self):
f = ATStateSelect()
out = u'''<select name="bundesland">
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/au.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from django.contrib.localflavor.au.forms import (AUPostCodeField,
AUPhoneNumberField, AUStateSelect)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class AULocalFlavorTests(LocalFlavorTestCase):
class AULocalFlavorTests(SimpleTestCase):
def test_AUStateSelect(self):
f = AUStateSelect()
out = u'''<select name="state">
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/be.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from django.contrib.localflavor.be.forms import (BEPostalCodeField,
BEPhoneNumberField, BERegionSelect, BEProvinceSelect)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class BELocalFlavorTests(LocalFlavorTestCase):
class BELocalFlavorTests(SimpleTestCase):
def test_BEPostalCodeField(self):
error_format = [u'Enter a valid postal code in the range and format 1XXX - 9XXX.']
valid = {
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/br.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
BRCNPJField, BRCPFField, BRPhoneNumberField, BRStateSelect,
BRStateChoiceField)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class BRLocalFlavorTests(LocalFlavorTestCase):
class BRLocalFlavorTests(SimpleTestCase):
def test_BRZipCodeField(self):
error_format = [u'Enter a zip code in the format XXXXX-XXX.']
valid = {
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/ca.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
CAPhoneNumberField, CAProvinceField, CAProvinceSelect,
CASocialInsuranceNumberField)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class CALocalFlavorTests(LocalFlavorTestCase):
class CALocalFlavorTests(SimpleTestCase):
def setUp(self):
self.save_warnings_state()
warnings.filterwarnings(
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/ch.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from django.contrib.localflavor.ch.forms import (CHZipCodeField,
CHPhoneNumberField, CHIdentityCardNumberField, CHStateSelect)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class CHLocalFlavorTests(LocalFlavorTestCase):
class CHLocalFlavorTests(SimpleTestCase):
def test_CHStateSelect(self):
f = CHStateSelect()
out = u'''<select name="state">
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/cl.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from django.contrib.localflavor.cl.forms import CLRutField, CLRegionSelect

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class CLLocalFlavorTests(LocalFlavorTestCase):
class CLLocalFlavorTests(SimpleTestCase):
def test_CLRegionSelect(self):
f = CLRegionSelect()
out = u'''<select name="foo">
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/cn.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

from django.contrib.localflavor.cn.forms import (CNProvinceSelect,
CNPostCodeField, CNIDCardField, CNPhoneNumberField, CNCellNumberField)
from utils import LocalFlavorTestCase
from django.test import SimpleTestCase

class CNLocalFlavorTests(LocalFlavorTestCase):
class CNLocalFlavorTests(SimpleTestCase):
def test_CNProvinceSelect(self):
f = CNProvinceSelect()
correct_output = u'''<select name="provinces">
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/co.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from django.contrib.localflavor.co.forms import CODepartmentSelect

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase

class COLocalFlavorTests(LocalFlavorTestCase):
class COLocalFlavorTests(SimpleTestCase):
def test_CODepartmentSelect(self):
d = CODepartmentSelect()
out = u"""<select name="department">
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/cz.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
CZRegionSelect, CZBirthNumberField, CZICNumberField)

from django.core.exceptions import ValidationError
from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class CZLocalFlavorTests(LocalFlavorTestCase):
class CZLocalFlavorTests(SimpleTestCase):
def setUp(self):
self.save_warnings_state()
warnings.filterwarnings(
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/de.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from django.contrib.localflavor.de.forms import (DEZipCodeField, DEStateSelect,
DEIdentityCardNumberField)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class DELocalFlavorTests(LocalFlavorTestCase):
class DELocalFlavorTests(SimpleTestCase):
def test_DEStateSelect(self):
f = DEStateSelect()
out = u'''<select name="states">
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/ec.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from django.contrib.localflavor.ec.forms import ECProvinceSelect

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase

class ECLocalFlavorTests(LocalFlavorTestCase):
class ECLocalFlavorTests(SimpleTestCase):
def test_ECProvinceSelect(self):
p = ECProvinceSelect()
out = u"""<select name="province">
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/es.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from django.contrib.localflavor.es.forms import (ESPostalCodeField, ESPhoneNumberField,
ESIdentityCardNumberField, ESCCCField, ESRegionSelect, ESProvinceSelect)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class ESLocalFlavorTests(LocalFlavorTestCase):
class ESLocalFlavorTests(SimpleTestCase):
def test_ESRegionSelect(self):
f = ESRegionSelect()
out = u'''<select name="regions">
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/fi.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from django.contrib.localflavor.fi.forms import (FIZipCodeField,
FISocialSecurityNumber, FIMunicipalitySelect)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class FILocalFlavorTests(LocalFlavorTestCase):
class FILocalFlavorTests(SimpleTestCase):
def test_FIMunicipalitySelect(self):
f = FIMunicipalitySelect()
out = u'''<select name="municipalities">
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/fr.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from django.contrib.localflavor.fr.forms import (FRZipCodeField,
FRPhoneNumberField, FRDepartmentSelect)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class FRLocalFlavorTests(LocalFlavorTestCase):
class FRLocalFlavorTests(SimpleTestCase):
def test_FRZipCodeField(self):
error_format = [u'Enter a zip code in the format XXXXX.']
valid = {
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/gb.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from django.contrib.localflavor.gb.forms import GBPostcodeField

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class GBLocalFlavorTests(LocalFlavorTestCase):
class GBLocalFlavorTests(SimpleTestCase):
def test_GBPostcodeField(self):
error_invalid = [u'Enter a valid postcode.']
valid = {
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

from django.contrib.localflavor.generic.forms import DateField, DateTimeField

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class GenericLocalFlavorTests(LocalFlavorTestCase):
class GenericLocalFlavorTests(SimpleTestCase):
def test_GenericDateField(self):
error_invalid = [u'Enter a valid date.']
valid = {
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/hr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
HRLicensePlateField, HRPostalCodeField, HROIBField, HRJMBGField,
HRJMBAGField)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase

class HRLocalFlavorTests(LocalFlavorTestCase):
class HRLocalFlavorTests(SimpleTestCase):
def test_HRCountySelect(self):
f = HRCountySelect()
out = u'''<select name="county">
Expand Down
4 changes: 2 additions & 2 deletions tests/regressiontests/forms/localflavor/id.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
IDPostCodeField, IDNationalIdentityNumberField, IDLicensePlateField,
IDProvinceSelect, IDLicensePlatePrefixSelect)

from utils import LocalFlavorTestCase
from django.test import SimpleTestCase


class IDLocalFlavorTests(LocalFlavorTestCase):
class IDLocalFlavorTests(SimpleTestCase):
def setUp(self):
self.save_warnings_state()
warnings.filterwarnings(
Expand Down
Loading

0 comments on commit 2664fa1

Please sign in to comment.