From f528a02e40d5742eac325c4c06d2f987a11e693f Mon Sep 17 00:00:00 2001 From: csparpa Date: Fri, 4 Nov 2016 09:28:47 +0100 Subject: [PATCH 1/9] Change testrunner --- docs/testing.md | 3 +++ runtests.py | 35 +++++++++++++---------------------- setup.py | 1 + test_settings.py | 16 ++++++++++++++++ 4 files changed, 33 insertions(+), 22 deletions(-) create mode 100644 docs/testing.md create mode 100644 test_settings.py diff --git a/docs/testing.md b/docs/testing.md new file mode 100644 index 0000000..ef2663c --- /dev/null +++ b/docs/testing.md @@ -0,0 +1,3 @@ +# Testing + +http://joebergantine.com/blog/2015/dec/03/test-reusable-django-application-support-multiple-/ \ No newline at end of file diff --git a/runtests.py b/runtests.py index 0a10611..d4af121 100644 --- a/runtests.py +++ b/runtests.py @@ -1,26 +1,17 @@ -import django, sys +import django +import os +import sys from django.conf import settings +from django.test.utils import get_runner -settings.configure( - DEBUG=True, - DATABASES={ - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - } - }, - USE_TZ=True, - INSTALLED_APPS=('django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.admin', - 'django_pyowm') -) +def runtests(): + os.environ['DJANGO_SETTINGS_MODULE'] = 'test_settings' + django.setup() + TestRunner = get_runner(settings) + test_runner = TestRunner() + failures = test_runner.run_tests(['django_pyowm.tests']) + sys.exit(bool(failures)) -django.setup() -from django.test.runner import DiscoverRunner -test_runner = DiscoverRunner(verbosity=1) - -failures = test_runner.run_tests(['django_pyowm']) -if failures: - sys.exit(failures) +if __name__ == '__main__': + runtests() diff --git a/setup.py b/setup.py index 3c6cb6e..5bcff08 100644 --- a/setup.py +++ b/setup.py @@ -38,4 +38,5 @@ 'Topic :: Internet :: WWW/HTTP', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', ], + test_suite="runtests.runtests", ) diff --git a/test_settings.py b/test_settings.py new file mode 100644 index 0000000..358548f --- /dev/null +++ b/test_settings.py @@ -0,0 +1,16 @@ +SECRET_KEY = 'a$h$of7!$2%a@ea=04vx(@qf^--b^4+@vmw4$@91mlxeizb2r8' +DEBUG = True, +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + } +} +USE_TZ = True +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'django_pyowm' +) \ No newline at end of file From c428462800c17c0793bfe28c2208e9f2a0757b18 Mon Sep 17 00:00:00 2001 From: csparpa Date: Fri, 4 Nov 2016 09:32:38 +0100 Subject: [PATCH 2/9] update --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3179668..a454212 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ *.pyc -.idea/ \ No newline at end of file +.idea/ +.tox/ +dist/ +django_pyowm.egg-info/ \ No newline at end of file From 0df9326020b72d7a9e8ee85e3e20e9813a1e9123 Mon Sep 17 00:00:00 2001 From: csparpa Date: Fri, 4 Nov 2016 11:02:47 +0100 Subject: [PATCH 3/9] Too much hassle for testing, definitely --- README.md | 4 +--- docs/testing.md | 39 +++++++++++++++++++++++++++++++++++++++ runtests.py | 17 ----------------- setup.py | 3 +-- test_settings.py | 16 ---------------- 5 files changed, 41 insertions(+), 38 deletions(-) delete mode 100644 runtests.py delete mode 100644 test_settings.py diff --git a/README.md b/README.md index 4fc8a25..54a0bff 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,4 @@ original_obs = m.to_entity() ``` ## Testing -```shell -$ python runtests.py -``` +Take a look at file [docs/testing.md](docs/testing.md). diff --git a/docs/testing.md b/docs/testing.md index ef2663c..7197633 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -1,3 +1,42 @@ # Testing +## How to run tests + +As `django_pyowm` is a Django app, it must be tested against a Django project, so we will create one. + +First of all you need to have the app installed in your `PYTHONPATH`. +Then create a test Django project and a test Django app with: + +```shel +$ django-admin startproject testproject +$ cd testproject +$ django-admin startapp testapp +``` + +Then edit your `INSTALLED_APPS` in file `testproject/testproject/settings.py` + +```python +INSTALLED_APPS = [ + ... + 'testapp', + 'django_pyowm' +] +``` + +Now copy the content of file `django_pyowm/django_pyowm/tests.py` into file `testproject/testapp/tests.py` + +Apply migrations with: + +``` +$ cd testproject +$ python manage.py migrate +``` + +Finally launch the tests with: + +``` +$ python manage.py test +``` + +## Good reads http://joebergantine.com/blog/2015/dec/03/test-reusable-django-application-support-multiple-/ \ No newline at end of file diff --git a/runtests.py b/runtests.py deleted file mode 100644 index d4af121..0000000 --- a/runtests.py +++ /dev/null @@ -1,17 +0,0 @@ -import django -import os -import sys -from django.conf import settings -from django.test.utils import get_runner - - -def runtests(): - os.environ['DJANGO_SETTINGS_MODULE'] = 'test_settings' - django.setup() - TestRunner = get_runner(settings) - test_runner = TestRunner() - failures = test_runner.run_tests(['django_pyowm.tests']) - sys.exit(bool(failures)) - -if __name__ == '__main__': - runtests() diff --git a/setup.py b/setup.py index 5bcff08..b4e1a1e 100644 --- a/setup.py +++ b/setup.py @@ -37,6 +37,5 @@ 'Programming Language :: Python :: 3.5', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', - ], - test_suite="runtests.runtests", + ] ) diff --git a/test_settings.py b/test_settings.py deleted file mode 100644 index 358548f..0000000 --- a/test_settings.py +++ /dev/null @@ -1,16 +0,0 @@ -SECRET_KEY = 'a$h$of7!$2%a@ea=04vx(@qf^--b^4+@vmw4$@91mlxeizb2r8' -DEBUG = True, -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - } -} -USE_TZ = True -INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django_pyowm' -) \ No newline at end of file From da4cf61d014d367ffc6b42083363205a12efe1f6 Mon Sep 17 00:00:00 2001 From: csparpa Date: Fri, 4 Nov 2016 11:38:25 +0100 Subject: [PATCH 4/9] Absolute import --- django_pyowm/tests.py | 2 +- docs/testing.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/django_pyowm/tests.py b/django_pyowm/tests.py index aa13513..e0fe84d 100644 --- a/django_pyowm/tests.py +++ b/django_pyowm/tests.py @@ -11,7 +11,7 @@ from pyowm.webapi25.uvindex import UVIndex as UVIndexEntity from pyowm.webapi25.coindex import COIndex as COIndexEntity from pyowm.webapi25.ozone import Ozone as OzoneEntity -from .models import Location, Weather, Observation, Forecast, Station, \ +from django_pyowm.models import Location, Weather, Observation, Forecast, Station, \ StationHistory, UVIndex, COIndex, Ozone diff --git a/docs/testing.md b/docs/testing.md index 7197633..6452717 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -7,7 +7,7 @@ As `django_pyowm` is a Django app, it must be tested against a Django project, s First of all you need to have the app installed in your `PYTHONPATH`. Then create a test Django project and a test Django app with: -```shel +```shell $ django-admin startproject testproject $ cd testproject $ django-admin startapp testapp @@ -29,6 +29,7 @@ Apply migrations with: ``` $ cd testproject +$ python manage.py makemigrations django_pyowm $ python manage.py migrate ``` From 9e69dc32d9c3dae4871373bf9022992fdb9ca912 Mon Sep 17 00:00:00 2001 From: csparpa Date: Fri, 4 Nov 2016 12:33:13 +0100 Subject: [PATCH 5/9] More tests and fixes --- django_pyowm/models.py | 34 +++++++++------ django_pyowm/tests.py | 93 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 13 deletions(-) diff --git a/django_pyowm/models.py b/django_pyowm/models.py index 2f76627..3cf6f15 100644 --- a/django_pyowm/models.py +++ b/django_pyowm/models.py @@ -193,8 +193,12 @@ def save_all(self): Saves this model along with all related ones. :return: None """ - self.location.save() - self.weather.save() + location = self.location + weather = self.weather + location.save() + weather.save() + self.location = location + self.weather = weather self.save() class Meta: @@ -265,13 +269,9 @@ def save_all(self): Saves this model along with all related ones. :return: None """ - self.location.save() - weats = self.weathers - self.weathers = [] - self.save() - for w in weats: - w.save() - self.weathers = weats + location = self.location + location.save() + self.location = location self.save() class Meta: @@ -353,7 +353,9 @@ def save_all(self): Saves this model along with all related ones. :return: None """ - self.last_weather.save() + last_weather = self.last_weather + last_weather.save() + self.last_weather = last_weather self.save() class Meta: @@ -489,7 +491,9 @@ def save_all(self): Saves this model along with all related ones. :return: None """ - self.location.save() + location = self.location + location.save() + self.location = location self.save() class Meta: @@ -564,7 +568,9 @@ def save_all(self): Saves this model along with all related ones. :return: None """ - self.location.save() + location = self.location + location.save() + self.location = location self.save() class Meta: @@ -639,7 +645,9 @@ def save_all(self): Saves this model along with all related ones. :return: None """ - self.location.save() + location = self.location + location.save() + self.location = location self.save() class Meta: diff --git a/django_pyowm/tests.py b/django_pyowm/tests.py index e0fe84d..5f80a2e 100644 --- a/django_pyowm/tests.py +++ b/django_pyowm/tests.py @@ -305,6 +305,21 @@ def test_to_entity(self): Asserter.assertWeatherEntitiesEqual(self, expected.get_weather(), result.get_weather()) + def test_save_all(self): + location = Location.from_entity(Databox.location) + weather = Weather.from_entity(Databox.weather) + observation = Observation(reception_time=Databox.reception_time, + location=location, + weather=weather) + self.assertIsNone(location.pk) + self.assertIsNone(weather.pk) + self.assertIsNone(observation.pk) + + observation.save_all() + self.assertIsNotNone(location.pk) + self.assertIsNotNone(weather.pk) + self.assertIsNotNone(observation.pk) + class TestForecastModel(TestCase): @@ -339,6 +354,23 @@ def test_to_entity(self): for ex_w, res_w in zip(expected.get_weathers(), result.get_weathers()): Asserter.assertWeatherEntitiesEqual(self, ex_w, res_w) + def test_save_all(self): + weathers = [Weather.from_entity(w) for w in Databox.weathers] + location = Location.from_entity(Databox.location) + forecast = Forecast(interval=Databox.interval, + reception_time=Databox.reception_time, + location=location) + self.assertIsNone(location.pk) + for w in weathers: + self.assertIsNone(w.pk) + self.assertIsNone(forecast.pk) + + for w in weathers: + w.save() + forecast.save_all() + self.assertIsNotNone(location.pk) + self.assertIsNotNone(forecast.pk) + class TestStationModel(TestCase): @@ -381,6 +413,22 @@ def test_to_entity(self): Asserter.assertWeatherEntitiesEqual(self, expected.get_last_weather(), result.get_last_weather()) + def test_save_all(self): + last_weather = Weather.from_entity(Databox.weather) + station = Station(name=Databox.station_name, + station_id=Databox.station_id, + station_type=Databox.station_type, + station_status=Databox.station_status, + lat=Databox.lat, lon=Databox.lon, + distance=Databox.station_distance, + last_weather=last_weather) + self.assertIsNone(last_weather.pk) + self.assertIsNone(station.pk) + + station.save_all() + self.assertIsNotNone(last_weather.pk) + self.assertIsNotNone(station.pk) + class TestStationHistoryModel(TestCase): @@ -442,6 +490,21 @@ def test_to_entity(self): Asserter.assertLocationEntitiesEqual(self, expected.get_location(), result.get_location()) + def test_save_all(self): + location = Location.from_entity(Databox.location) + uvindex = UVIndex( + reference_time=Databox.reference_time, + location=location, + value=Databox.uvindex_intensity, + interval=Databox.uvindex_interval, + reception_time=Databox.reception_time) + self.assertIsNone(location.pk) + self.assertIsNone(uvindex.pk) + + uvindex.save_all() + self.assertIsNotNone(location.pk) + self.assertIsNotNone(uvindex.pk) + class TestCOIndexModel(TestCase): @@ -475,6 +538,21 @@ def test_to_entity(self): Asserter.assertLocationEntitiesEqual(self, expected.get_location(), result.get_location()) + def test_save_all(self): + location = Location.from_entity(Databox.location) + coindex = COIndex( + reference_time=Databox.reference_time, + location=location, + interval=Databox.coindex_interval, + reception_time=Databox.reception_time, + co_samples=json.dumps(Databox.co_samples)) + self.assertIsNone(location.pk) + self.assertIsNone(coindex.pk) + + coindex.save_all() + self.assertIsNotNone(location.pk) + self.assertIsNotNone(coindex.pk) + class TestOzoneModel(TestCase): @@ -507,3 +585,18 @@ def test_to_entity(self): self.assertEquals(expected.get_reception_time(), result.get_reception_time()) Asserter.assertLocationEntitiesEqual(self, expected.get_location(), result.get_location()) + + def test_save_all(self): + location = Location.from_entity(Databox.location) + ozone = Ozone( + reference_time=Databox.reference_time, + location=location, + du_value=Databox.du_value, + interval=Databox.ozone_interval, + reception_time=Databox.reception_time) + self.assertIsNone(location.pk) + self.assertIsNone(ozone.pk) + + ozone.save_all() + self.assertIsNotNone(location.pk) + self.assertIsNotNone(ozone.pk) From dee0c5bd2ffe0af235037258a93bbaaed6b6953f Mon Sep 17 00:00:00 2001 From: csparpa Date: Fri, 4 Nov 2016 12:47:22 +0100 Subject: [PATCH 6/9] release checklist --- docs/releasing.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 docs/releasing.md diff --git a/docs/releasing.md b/docs/releasing.md new file mode 100644 index 0000000..886bbcc --- /dev/null +++ b/docs/releasing.md @@ -0,0 +1,12 @@ +https://github.com/csparpa/django-pyowm + +Checklist: + + - write new models / patch existing ones + - write / patch tests + - + - update setup.py + - merge develop branch into master branch (no feature/hotfix branches left open) + - handle github stuff (issues, PRs, etc..) + - tag release on github + - generate and upload release on pypi \ No newline at end of file From 4d4b6363dc608e2bd952cdb77acfc1cabb583f62 Mon Sep 17 00:00:00 2001 From: csparpa Date: Fri, 4 Nov 2016 12:49:09 +0100 Subject: [PATCH 7/9] Only Py27 for the moment --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 54a0bff..a8c3823 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A Django ORM interface for PyOWM domain entities - Django 1.10+ - PyOWM 2.5+ -Python 2.7 and 3.2+ are supported. +Python 2.7 is supported. ## Install From 88e2557a2af6432486b50b5c5e88e848b38a9d8d Mon Sep 17 00:00:00 2001 From: csparpa Date: Fri, 16 Dec 2016 22:45:00 +0100 Subject: [PATCH 8/9] Fix link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b6480e6..24a272e 100644 --- a/README.md +++ b/README.md @@ -73,4 +73,4 @@ original_obs = m.to_entity() ``` ## Testing -All details in file [docs/testing.md](docs/testing.md) +All details about testing are [here](https://github.com/csparpa/django-pyowm/wiki/Testing) From abdeed8940f15de6bd64caccb16191d5f753dd15 Mon Sep 17 00:00:00 2001 From: csparpa Date: Wed, 1 Feb 2017 08:17:15 +0100 Subject: [PATCH 9/9] Specified that API might be unstable as we are in beta testing phase --- README.md | 2 ++ setup.py | 1 + 2 files changed, 3 insertions(+) diff --git a/README.md b/README.md index 24a272e..bd17b46 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ A Django ORM interface for PyOWM domain entities Python 2.7 is supported. +** Please notice that the API can be unstable as this project is still in beta testing ** + ## Install Install the library with `pip`: diff --git a/setup.py b/setup.py index b4e1a1e..644913f 100644 --- a/setup.py +++ b/setup.py @@ -23,6 +23,7 @@ author='Claudio Sparpaglione', author_email='csparpa@gmail.com', classifiers=[ + 'Development Status :: 4 - Beta', 'Environment :: Web Environment', 'Framework :: Django', 'Framework :: Django :: 1.10',