summaryrefslogtreecommitdiff
path: root/parts/django/tests/modeltests/validation
diff options
context:
space:
mode:
Diffstat (limited to 'parts/django/tests/modeltests/validation')
-rw-r--r--parts/django/tests/modeltests/validation/__init__.py21
-rw-r--r--parts/django/tests/modeltests/validation/models.py65
-rw-r--r--parts/django/tests/modeltests/validation/test_custom_messages.py13
-rw-r--r--parts/django/tests/modeltests/validation/test_unique.py85
-rw-r--r--parts/django/tests/modeltests/validation/tests.py114
-rw-r--r--parts/django/tests/modeltests/validation/validators.py18
6 files changed, 316 insertions, 0 deletions
diff --git a/parts/django/tests/modeltests/validation/__init__.py b/parts/django/tests/modeltests/validation/__init__.py
new file mode 100644
index 0000000..d0a7d19
--- /dev/null
+++ b/parts/django/tests/modeltests/validation/__init__.py
@@ -0,0 +1,21 @@
+import unittest
+
+from django.core.exceptions import ValidationError
+
+class ValidationTestCase(unittest.TestCase):
+ def assertFailsValidation(self, clean, failed_fields):
+ self.assertRaises(ValidationError, clean)
+ try:
+ clean()
+ except ValidationError, e:
+ self.assertEquals(sorted(failed_fields), sorted(e.message_dict.keys()))
+
+ def assertFieldFailsValidationWithMessage(self, clean, field_name, message):
+ self.assertRaises(ValidationError, clean)
+ try:
+ clean()
+ except ValidationError, e:
+ self.assertTrue(field_name in e.message_dict)
+ self.assertEquals(message, e.message_dict[field_name])
+
+
diff --git a/parts/django/tests/modeltests/validation/models.py b/parts/django/tests/modeltests/validation/models.py
new file mode 100644
index 0000000..dd42936
--- /dev/null
+++ b/parts/django/tests/modeltests/validation/models.py
@@ -0,0 +1,65 @@
+from datetime import datetime
+from django.core.exceptions import ValidationError
+from django.db import models
+from django.test import TestCase
+
+
+def validate_answer_to_universe(value):
+ if value != 42:
+ raise ValidationError('This is not the answer to life, universe and everything!', code='not42')
+
+class ModelToValidate(models.Model):
+ name = models.CharField(max_length=100)
+ created = models.DateTimeField(default=datetime.now)
+ number = models.IntegerField(db_column='number_val')
+ parent = models.ForeignKey('self', blank=True, null=True, limit_choices_to={'number': 10})
+ email = models.EmailField(blank=True)
+ url = models.URLField(blank=True)
+ f_with_custom_validator = models.IntegerField(blank=True, null=True, validators=[validate_answer_to_universe])
+
+ def clean(self):
+ super(ModelToValidate, self).clean()
+ if self.number == 11:
+ raise ValidationError('Invalid number supplied!')
+
+class UniqueFieldsModel(models.Model):
+ unique_charfield = models.CharField(max_length=100, unique=True)
+ unique_integerfield = models.IntegerField(unique=True)
+ non_unique_field = models.IntegerField()
+
+class CustomPKModel(models.Model):
+ my_pk_field = models.CharField(max_length=100, primary_key=True)
+
+class UniqueTogetherModel(models.Model):
+ cfield = models.CharField(max_length=100)
+ ifield = models.IntegerField()
+ efield = models.EmailField()
+
+ class Meta:
+ unique_together = (('ifield', 'cfield',), ['ifield', 'efield'])
+
+class UniqueForDateModel(models.Model):
+ start_date = models.DateField()
+ end_date = models.DateTimeField()
+ count = models.IntegerField(unique_for_date="start_date", unique_for_year="end_date")
+ order = models.IntegerField(unique_for_month="end_date")
+ name = models.CharField(max_length=100)
+
+class CustomMessagesModel(models.Model):
+ other = models.IntegerField(blank=True, null=True)
+ number = models.IntegerField(db_column='number_val',
+ error_messages={'null': 'NULL', 'not42': 'AAARGH', 'not_equal': '%s != me'},
+ validators=[validate_answer_to_universe]
+ )
+
+class Author(models.Model):
+ name = models.CharField(max_length=100)
+
+class Article(models.Model):
+ title = models.CharField(max_length=100)
+ author = models.ForeignKey(Author)
+ pub_date = models.DateTimeField(blank=True)
+
+ def clean(self):
+ if self.pub_date is None:
+ self.pub_date = datetime.now()
diff --git a/parts/django/tests/modeltests/validation/test_custom_messages.py b/parts/django/tests/modeltests/validation/test_custom_messages.py
new file mode 100644
index 0000000..05bb651
--- /dev/null
+++ b/parts/django/tests/modeltests/validation/test_custom_messages.py
@@ -0,0 +1,13 @@
+from modeltests.validation import ValidationTestCase
+from models import CustomMessagesModel
+
+
+class CustomMessagesTest(ValidationTestCase):
+ def test_custom_simple_validator_message(self):
+ cmm = CustomMessagesModel(number=12)
+ self.assertFieldFailsValidationWithMessage(cmm.full_clean, 'number', ['AAARGH'])
+
+ def test_custom_null_message(self):
+ cmm = CustomMessagesModel()
+ self.assertFieldFailsValidationWithMessage(cmm.full_clean, 'number', ['NULL'])
+
diff --git a/parts/django/tests/modeltests/validation/test_unique.py b/parts/django/tests/modeltests/validation/test_unique.py
new file mode 100644
index 0000000..fb77c4d
--- /dev/null
+++ b/parts/django/tests/modeltests/validation/test_unique.py
@@ -0,0 +1,85 @@
+import unittest
+import datetime
+from django.conf import settings
+from django.db import connection
+from models import CustomPKModel, UniqueTogetherModel, UniqueFieldsModel, UniqueForDateModel, ModelToValidate
+
+
+class GetUniqueCheckTests(unittest.TestCase):
+ def test_unique_fields_get_collected(self):
+ m = UniqueFieldsModel()
+ self.assertEqual(
+ ([(UniqueFieldsModel, ('id',)),
+ (UniqueFieldsModel, ('unique_charfield',)),
+ (UniqueFieldsModel, ('unique_integerfield',))],
+ []),
+ m._get_unique_checks()
+ )
+
+ def test_unique_together_gets_picked_up_and_converted_to_tuple(self):
+ m = UniqueTogetherModel()
+ self.assertEqual(
+ ([(UniqueTogetherModel, ('ifield', 'cfield',)),
+ (UniqueTogetherModel, ('ifield', 'efield')),
+ (UniqueTogetherModel, ('id',)), ],
+ []),
+ m._get_unique_checks()
+ )
+
+ def test_primary_key_is_considered_unique(self):
+ m = CustomPKModel()
+ self.assertEqual(([(CustomPKModel, ('my_pk_field',))], []), m._get_unique_checks())
+
+ def test_unique_for_date_gets_picked_up(self):
+ m = UniqueForDateModel()
+ self.assertEqual((
+ [(UniqueForDateModel, ('id',))],
+ [(UniqueForDateModel, 'date', 'count', 'start_date'),
+ (UniqueForDateModel, 'year', 'count', 'end_date'),
+ (UniqueForDateModel, 'month', 'order', 'end_date')]
+ ), m._get_unique_checks()
+ )
+
+ def test_unique_for_date_exclusion(self):
+ m = UniqueForDateModel()
+ self.assertEqual((
+ [(UniqueForDateModel, ('id',))],
+ [(UniqueForDateModel, 'year', 'count', 'end_date'),
+ (UniqueForDateModel, 'month', 'order', 'end_date')]
+ ), m._get_unique_checks(exclude='start_date')
+ )
+
+class PerformUniqueChecksTest(unittest.TestCase):
+ def setUp(self):
+ # Set debug to True to gain access to connection.queries.
+ self._old_debug, settings.DEBUG = settings.DEBUG, True
+ super(PerformUniqueChecksTest, self).setUp()
+
+ def tearDown(self):
+ # Restore old debug value.
+ settings.DEBUG = self._old_debug
+ super(PerformUniqueChecksTest, self).tearDown()
+
+ def test_primary_key_unique_check_not_performed_when_adding_and_pk_not_specified(self):
+ # Regression test for #12560
+ query_count = len(connection.queries)
+ mtv = ModelToValidate(number=10, name='Some Name')
+ setattr(mtv, '_adding', True)
+ mtv.full_clean()
+ self.assertEqual(query_count, len(connection.queries))
+
+ def test_primary_key_unique_check_performed_when_adding_and_pk_specified(self):
+ # Regression test for #12560
+ query_count = len(connection.queries)
+ mtv = ModelToValidate(number=10, name='Some Name', id=123)
+ setattr(mtv, '_adding', True)
+ mtv.full_clean()
+ self.assertEqual(query_count + 1, len(connection.queries))
+
+ def test_primary_key_unique_check_not_performed_when_not_adding(self):
+ # Regression test for #12132
+ query_count= len(connection.queries)
+ mtv = ModelToValidate(number=10, name='Some Name')
+ mtv.full_clean()
+ self.assertEqual(query_count, len(connection.queries))
+
diff --git a/parts/django/tests/modeltests/validation/tests.py b/parts/django/tests/modeltests/validation/tests.py
new file mode 100644
index 0000000..0027393
--- /dev/null
+++ b/parts/django/tests/modeltests/validation/tests.py
@@ -0,0 +1,114 @@
+from django import forms
+from django.test import TestCase
+from django.core.exceptions import NON_FIELD_ERRORS
+from modeltests.validation import ValidationTestCase
+from modeltests.validation.models import Author, Article, ModelToValidate
+
+# Import other tests for this package.
+from modeltests.validation.validators import TestModelsWithValidators
+from modeltests.validation.test_unique import GetUniqueCheckTests, PerformUniqueChecksTest
+from modeltests.validation.test_custom_messages import CustomMessagesTest
+
+
+class BaseModelValidationTests(ValidationTestCase):
+
+ def test_missing_required_field_raises_error(self):
+ mtv = ModelToValidate(f_with_custom_validator=42)
+ self.assertFailsValidation(mtv.full_clean, ['name', 'number'])
+
+ def test_with_correct_value_model_validates(self):
+ mtv = ModelToValidate(number=10, name='Some Name')
+ self.assertEqual(None, mtv.full_clean())
+
+ def test_custom_validate_method(self):
+ mtv = ModelToValidate(number=11)
+ self.assertFailsValidation(mtv.full_clean, [NON_FIELD_ERRORS, 'name'])
+
+ def test_wrong_FK_value_raises_error(self):
+ mtv=ModelToValidate(number=10, name='Some Name', parent_id=3)
+ self.assertFailsValidation(mtv.full_clean, ['parent'])
+
+ def test_correct_FK_value_validates(self):
+ parent = ModelToValidate.objects.create(number=10, name='Some Name')
+ mtv = ModelToValidate(number=10, name='Some Name', parent_id=parent.pk)
+ self.assertEqual(None, mtv.full_clean())
+
+ def test_limitted_FK_raises_error(self):
+ # The limit_choices_to on the parent field says that a parent object's
+ # number attribute must be 10, so this should fail validation.
+ parent = ModelToValidate.objects.create(number=11, name='Other Name')
+ mtv = ModelToValidate(number=10, name='Some Name', parent_id=parent.pk)
+ self.assertFailsValidation(mtv.full_clean, ['parent'])
+
+ def test_wrong_email_value_raises_error(self):
+ mtv = ModelToValidate(number=10, name='Some Name', email='not-an-email')
+ self.assertFailsValidation(mtv.full_clean, ['email'])
+
+ def test_correct_email_value_passes(self):
+ mtv = ModelToValidate(number=10, name='Some Name', email='valid@email.com')
+ self.assertEqual(None, mtv.full_clean())
+
+ def test_wrong_url_value_raises_error(self):
+ mtv = ModelToValidate(number=10, name='Some Name', url='not a url')
+ self.assertFieldFailsValidationWithMessage(mtv.full_clean, 'url', [u'Enter a valid value.'])
+
+ def test_correct_url_but_nonexisting_gives_404(self):
+ mtv = ModelToValidate(number=10, name='Some Name', url='http://google.com/we-love-microsoft.html')
+ self.assertFieldFailsValidationWithMessage(mtv.full_clean, 'url', [u'This URL appears to be a broken link.'])
+
+ def test_correct_url_value_passes(self):
+ mtv = ModelToValidate(number=10, name='Some Name', url='http://www.djangoproject.com/')
+ self.assertEqual(None, mtv.full_clean()) # This will fail if there's no Internet connection
+
+ def test_text_greater_that_charfields_max_length_eaises_erros(self):
+ mtv = ModelToValidate(number=10, name='Some Name'*100)
+ self.assertFailsValidation(mtv.full_clean, ['name',])
+
+class ArticleForm(forms.ModelForm):
+ class Meta:
+ model = Article
+ exclude = ['author']
+
+class ModelFormsTests(TestCase):
+ def setUp(self):
+ self.author = Author.objects.create(name='Joseph Kocherhans')
+
+ def test_partial_validation(self):
+ # Make sure the "commit=False and set field values later" idiom still
+ # works with model validation.
+ data = {
+ 'title': 'The state of model validation',
+ 'pub_date': '2010-1-10 14:49:00'
+ }
+ form = ArticleForm(data)
+ self.assertEqual(form.errors.keys(), [])
+ article = form.save(commit=False)
+ article.author = self.author
+ article.save()
+
+ def test_validation_with_empty_blank_field(self):
+ # Since a value for pub_date wasn't provided and the field is
+ # blank=True, model-validation should pass.
+ # Also, Article.clean() should be run, so pub_date will be filled after
+ # validation, so the form should save cleanly even though pub_date is
+ # not allowed to be null.
+ data = {
+ 'title': 'The state of model validation',
+ }
+ article = Article(author_id=self.author.id)
+ form = ArticleForm(data, instance=article)
+ self.assertEqual(form.errors.keys(), [])
+ self.assertNotEqual(form.instance.pub_date, None)
+ article = form.save()
+
+ def test_validation_with_invalid_blank_field(self):
+ # Even though pub_date is set to blank=True, an invalid value was
+ # provided, so it should fail validation.
+ data = {
+ 'title': 'The state of model validation',
+ 'pub_date': 'never'
+ }
+ article = Article(author_id=self.author.id)
+ form = ArticleForm(data, instance=article)
+ self.assertEqual(form.errors.keys(), ['pub_date'])
+
diff --git a/parts/django/tests/modeltests/validation/validators.py b/parts/django/tests/modeltests/validation/validators.py
new file mode 100644
index 0000000..3ad2c40
--- /dev/null
+++ b/parts/django/tests/modeltests/validation/validators.py
@@ -0,0 +1,18 @@
+from unittest import TestCase
+from modeltests.validation import ValidationTestCase
+from models import *
+
+
+class TestModelsWithValidators(ValidationTestCase):
+ def test_custom_validator_passes_for_correct_value(self):
+ mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=42)
+ self.assertEqual(None, mtv.full_clean())
+
+ def test_custom_validator_raises_error_for_incorrect_value(self):
+ mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=12)
+ self.assertFailsValidation(mtv.full_clean, ['f_with_custom_validator'])
+ self.assertFieldFailsValidationWithMessage(
+ mtv.full_clean,
+ 'f_with_custom_validator',
+ [u'This is not the answer to life, universe and everything!']
+ )