diff --git a/Pipfile b/Pipfile index b6cd945..cca9ef8 100644 --- a/Pipfile +++ b/Pipfile @@ -5,6 +5,7 @@ verify_ssl = true [dev-packages] pylint = "*" +coverage = "*" [packages] django = "*" diff --git a/lostplaces/lostplaces_app/models.py b/lostplaces/lostplaces_app/models.py index cf625a2..e3d5563 100644 --- a/lostplaces/lostplaces_app/models.py +++ b/lostplaces/lostplaces_app/models.py @@ -9,6 +9,7 @@ import uuid from django.db import models from django.dispatch import receiver from django.contrib.auth.models import AbstractUser +from django.core.validators import MaxValueValidator, MinValueValidator from easy_thumbnails.fields import ThumbnailerImageField from taggit.managers import TaggableManager @@ -52,8 +53,18 @@ class Place (models.Model): related_name='places' ) location = models.CharField(max_length=50) - latitude = models.FloatField() - longitude = models.FloatField() + latitude = models.FloatField( + validators=[ + MinValueValidator(-90), + MaxValueValidator(90) + ] + ) + longitude = models.FloatField( + validators=[ + MinValueValidator(-180), + MaxValueValidator(180) + ] + ) description = models.TextField() tags = TaggableManager(blank=True) diff --git a/lostplaces/lostplaces_app/tests.py b/lostplaces/lostplaces_app/tests.py deleted file mode 100644 index 1a11e63..0000000 --- a/lostplaces/lostplaces_app/tests.py +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -''' Tests for the lostplaces_app. ''' - -rom django.test import TestCase - -# Create your tests here. diff --git a/lostplaces/lostplaces_app/tests/__init__.py b/lostplaces/lostplaces_app/tests/__init__.py new file mode 100644 index 0000000..4d80975 --- /dev/null +++ b/lostplaces/lostplaces_app/tests/__init__.py @@ -0,0 +1,30 @@ +from django.db import models +from lostplaces_app.models import Explorer + +def mock_user(): + explorer_list = Explorer.objects.all() + if len(explorer_list) <= 0: + return Explorer.objects.create_user( + username='testpeter', + password='Develop123' + ) + else: + return explorer_list[0] + + +class TestSubmittable: + + def test_submitted_when(self): + submitted_when = self.object._meta.get_field('submitted_when') + self.assertTrue(submitted_when) + self.assertEqual(type(submitted_when), models.DateTimeField) + self.assertTrue(submitted_when.auto_now_add) + + def test_submitted_by(self): + submitted_by = self.object._meta.get_field('submitted_by') + self.assertTrue(submitted_by) + self.assertEqual(type(submitted_by), models.ForeignKey) + self.assertEqual(submitted_by.remote_field.related_name, 'places') + self.assertTrue(submitted_by.null) + self.assertTrue(submitted_by.blank) + self.assertEqual(submitted_by.remote_field.on_delete, models.SET_NULL) \ No newline at end of file diff --git a/lostplaces/lostplaces_app/tests/test_models.py b/lostplaces/lostplaces_app/tests/test_models.py new file mode 100644 index 0000000..e69de29 diff --git a/lostplaces/lostplaces_app/tests/views/__init__.py b/lostplaces/lostplaces_app/tests/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lostplaces/lostplaces_app/tests/views/test_place_views.py b/lostplaces/lostplaces_app/tests/views/test_place_views.py new file mode 100644 index 0000000..9b19df6 --- /dev/null +++ b/lostplaces/lostplaces_app/tests/views/test_place_views.py @@ -0,0 +1,199 @@ +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: + model_name = None + + def _test_field(self, field_name, field_class): + 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): + 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): + 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): + 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): + 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): + 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 + ) + + )