import datetime from django.test import TestCase from django.db import models from lostplaces_app.models import Place from lostplaces_app.tests import mock_user, TestSubmittable from taggit.managers import TaggableManager def mock_place(): place = Place.objects.create( name='Im a place', submitted_when=datetime.datetime.now(), submitted_by=mock_user(), location='Testtown', latitude=50.5, longitude=7.0, description='This is just a test, do not worry' ) place.tags.add('I a tag', 'testlocation') return place class ModelTest: ''' Base class for Lostplaces models ''' model_name = None def _test_field(self, field_name, field_class): ''' Tests if a field exists under the given name and if the field is of the right type ''' field = self.place._meta.get_field(field_name) self.assertTrue( field, msg="%s has no field named '%s'" % ( self.model_name, field_name ) ) self.assertEqual( type(field), field_class, msg='%s.%s name field is no CharField' % ( self.model_name, field_name ) ) return field def _test_char_field(self, field_name, min_length, max_length): ''' 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 ) ) self.assertTrue( field.max_length in range(min_length, max_length), msg='%s.%s field max_length not in 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): ''' 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 look like [MinValueValidator, MayValueValidator], if both values are passed, [MinValueValidator] if only min_value is passed, [MaxValueValidator] if only max_value is passed ''' field = self._test_field(field_name, models.FloatField) if min_value: self.assertTrue( len(field.validators) >= 1, msg='%s.%s first validator should check minimum' % ( self.model_name, field_name ) ) self.assertEqual( field.validators[0].limit_value, min_value, msg='%s.%s min value missmatch' % ( self.model_name, field_name ) ) if max_value: index = 0 if min_value: 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' % ( self.model_name, field_name ) ) class PlaceTestCase(ModelTest, TestSubmittable, TestCase): model_name = 'Place' def setUp(self): self.place = mock_place() self.object = self.place def test_name_field(self): self._test_char_field( field_name='name', min_length=10, max_length=100 ) def test_location(self): self._test_char_field( field_name='location', min_length=10, max_length=100 ) def test_latitude(self): self._test_float_field( field_name='latitude', min_value=-90, max_value=90 ) def test_longitude(self): self._test_float_field( field_name='longitude', min_value=-180, max_value=180 ) def test_decsription(self): self._test_field('description', models.TextField) def test_tags(self): self._test_field('tags', TaggableManager) def test_average_latlon(self): ''' Tests the average latitude/longitude calculation of a list of 10 places ''' place_list = [] for i in range(10): place = mock_place() place.latitude = i+1 place.longitude = i+10 place_list.append(place) avg_latlon = Place.average_latlon(place_list) self.assertEqual(avg_latlon[0], 5.5, msg='%s: average latitude missmatch' % ( self.model_name ) ) self.assertEqual(avg_latlon[1], 14.5, msg='%s: average longitude missmatch' % ( self.model_name ) ) def test_average_latlon_one_place(self): ''' Tests the average latitude/longitude calculation of a list of one place ''' place = mock_place() avg_latlon = Place.average_latlon([place]) self.assertEqual(avg_latlon[0], place.latitude, msg='%s:(one place) average latitude missmatch' % ( self.model_name ) ) self.assertEqual(avg_latlon[1], place.longitude, msg='%s: (one place) average longitude missmatch' % ( self.model_name ) ) def test_average_latlon_no_places(self): ''' Tests the average latitude/longitude calculation of an empty list ''' avg_latlon = Place.average_latlon([]) self.assertEqual(avg_latlon[0], 0, msg='%s: (no places) average latitude missmatch' % ( self.model_name ) ) self.assertEqual(avg_latlon[1], 0, msg='%s: a(no places) verage longitude missmatch' % ( self.model_name ) ) def test_str(self): place = mock_place() self.assertEqual(str(place), place.name, msg='%s __str__ should return the name' % ( self.model_name ) )