diff --git a/lostplaces/lostplaces_app/tests/models/__init__.py b/lostplaces/lostplaces_app/tests/models/__init__.py index 7538d94..26914a2 100644 --- a/lostplaces/lostplaces_app/tests/models/__init__.py +++ b/lostplaces/lostplaces_app/tests/models/__init__.py @@ -1,58 +1,99 @@ from django.db import models +from django.core.exceptions import FieldDoesNotExist +from django.test import TestCase -class TestModel: + +class ModelTestCase: ''' Base class for Lostplaces models ''' model_name = None - def _test_field(self, field_name, field_class): + def _test_field(self, field_name, field_class, must_have={}, must_not_have={}): ''' Tests if a field exists under the given name and - if the field is of the right type + if the field is of the right type. + Also checks if the field has the given must_have attributes + and does not have any of the must_not_have attributes. If you + dont care about the value of the attribute you can just set it to + something that fullfills value == False (i.e. '' or 0) ''' - field = self.object._meta.get_field(field_name) - self.assertTrue( - field, - msg="%s has no field named '%s'" % ( - self.model_name, - field_name + try: + field = self.object._meta.get_field(field_name) + except FieldDoesNotExist: + self.fail( + 'Expecting %s to have a field named \'%s\'' % ( + self.model_name, + field_name + ) ) - ) self.assertEqual( - type(field), field_class, - msg='%s.%s name field is no CharField' % ( + type(field), field_class, + msg='Expecting type of %s.%s to be %s' % ( self.model_name, - field_name + field_name, + field_class.__name__ ) ) + + for key, value in must_have.items(): + if value: + self.assertEqual(getattr(field, key), value, + msg='Expeting %s.%s.%s to be \'%s\'' % ( + self.model_name, + field_name, + key, + value + ) + ) + else: + self.assertTrue(hasattr(field, key), + msg='Expeting %s.%s to have \'%s\'' % ( + self.model_name, + field_name, + key + ) + ) + + for key, value in must_not_have.items(): + if value: + self.assertTrue(getattr(field, key) != value, + msg='Expeting %s.%s.%s to not be \'%s\'' % ( + self.model_name, + field_name, + key, + value + ) + ) + else: + self.assertFalse(hasattr(field, value), + msg='Expeting %s.%s to not have \'%s\'' % ( + self.model_name, + field_name, + key + ) + ) + return field - - def _test_char_field(self, field_name, min_length, max_length): + def _test_char_field(self, field_name, min_length, max_length, must_have={}, must_hot_have={}): ''' Tests if the given field is a char field and if its max_length is in min_length and max_legth ''' - field = self._test_field(field_name, models.CharField) - self.assertEqual( - type(field), models.CharField, - msg='%s.%s name field is no CharField' % ( - self.model_name, - field_name - ) - ) + field = self._test_field( + field_name, models.CharField, must_have, must_hot_have) self.assertTrue( field.max_length in range(min_length, max_length), - msg='%s.%s field max_length not in range of %d and %d' % ( + msg='Expeting %s.%s field max_length to be in the range of %d and %d' % ( self.model_name, field_name, min_length, max_length - ) + ) ) - - def _test_float_field(self, field_name, min_value=None, max_value=None): + + def _test_float_field(self, field_name, min_value=None, max_value=None, must_have={}, must_hot_have={}): ''' Tests if the field is a floatfield. If min_value and/or max_value are passed, the validators of the field are also checked. The validator list of the field should @@ -61,21 +102,23 @@ class TestModel: [MinValueValidator] if only min_value is passed, [MaxValueValidator] if only max_value is passed ''' - field = self._test_field(field_name, models.FloatField) + field = self._test_field( + field_name, models.FloatField, must_have, must_hot_have) if min_value: self.assertTrue( len(field.validators) >= 1, - msg='%s.%s first validator should check minimum' % ( + msg='Expecting the first valiator of %s.%s to check the minimum' % ( self.model_name, field_name - ) ) + ) self.assertEqual( field.validators[0].limit_value, min_value, - msg='%s.%s min value missmatch' % ( + msg='Expecting the min value of %s.%s min to be at least %d' % ( self.model_name, - field_name + field_name, + min_value ) ) if max_value: @@ -84,38 +127,41 @@ class TestModel: index += 1 self.assertTrue( len(field.validators) >= index+1, - msg='%s.%s second validator should check maximum' % ( - self.model_name, - field_name - ) - ) - self.assertEqual( - field.validators[1].limit_value, - max_value, - msg='%s.%s max value missmatch' % ( + msg='Expecting the second valiator of %s.%s to check the maximum' % ( self.model_name, field_name ) ) + self.assertEqual( + field.validators[1].limit_value, + max_value, + msg='Expecting the max value of %s.%s min to be at most %d' % ( + self.model_name, + field_name, + max_value + ) + ) -class TestSubmittable(TestModel): - model_name='' + +class SubmittableTestCase(ModelTestCase): + model_name = '' related_name = None nullable = False def test_submitted_when(self): - submitted_when = self._test_field('submitted_when', models.DateTimeField) - self.assertTrue(submitted_when.auto_now_add, - msg='%s.submitted_when should be auto_now_add' % ( - self.model_name - ) + submitted_when = self._test_field( + 'submitted_when', + models.DateTimeField, + must_have={'auto_now_add': True} ) def test_submitted_by(self): - submitted_by = self._test_field('submitted_by',models.ForeignKey) + submitted_by = self._test_field('submitted_by', models.ForeignKey) if self.related_name: - self.assertEqual(submitted_by.remote_field.related_name, self.related_name) + self.assertEqual( + submitted_by.remote_field.related_name, self.related_name) if self.nullable: self.assertTrue(submitted_by.null,) self.assertTrue(submitted_by.blank) - self.assertEqual(submitted_by.remote_field.on_delete, models.SET_NULL) + self.assertEqual( + submitted_by.remote_field.on_delete, models.SET_NULL)