From e0d3b8d062b1dba2fd980155266afdea6388ec71 Mon Sep 17 00:00:00 2001 From: Nikos Roussos Date: Thu, 2 Mar 2017 23:48:44 +0200 Subject: [PATCH] Add some basic tests --- .coveragerc | 32 ++++++++++++++++++ .gitignore | 1 + .travis.yml | 5 ++- README.md | 1 + db/api/tests.py | 26 +++++++++++++++ db/base/tests.py | 77 +++++++++++++++++++++++++++++++++++++++++--- pytest.ini | 4 +++ requirements/dev.txt | 46 ++++++++++++++++++++++++-- 8 files changed, 185 insertions(+), 7 deletions(-) create mode 100644 .coveragerc create mode 100644 db/api/tests.py create mode 100644 pytest.ini diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..408ba96 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,32 @@ +[run] +include = + db/* + db/base/* + db/api/* + base/decoders/* + base/management/* + base/management/commands/* + base/templatetags/* + +[report] +exclude_lines = + pragma: no cover + + # Don't complain about missing debug-only code: + def __unicode__ + def __repr__ + if self\.debug + + # Don't complain if tests don't hit defensive assertion code: + raise AssertionError + raise NotImplementedError + + # Don't complain if non-runnable code isn't run: + if 0: + if __name__ == .__main__.: + +omit = + settings/* + */migrations/* + +show_missing = True diff --git a/.gitignore b/.gitignore index 422b55e..54170b3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ __pycache__ env .env +.cache # Logs *.log diff --git a/.travis.yml b/.travis.yml index 0d858eb..b010b06 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,12 @@ dist: trusty python: - "2.7" install: - - pip install flake8 + - pip install -r requirements/dev.txt - npm install -g eslint stylelint script: - flake8 . + - pytest - eslint 'db/static/js/*.js' - stylelint 'db/static/css/*.css' +after_success: + - coveralls diff --git a/README.md b/README.md index e3c1785..8e95cd8 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ See the [documentation](http://docs.satnogs.org/en/stable/db/). [![kanban](https://img.shields.io/badge/kanban-board-lightgray.svg)](https://github.com/satnogs/satnogs-db/projects/1) [![travis](https://img.shields.io/travis/satnogs/satnogs-db/dev.svg?label=tests)](http://travis-ci.org/satnogs/satnogs-db/) +[![coveralls](https://img.shields.io/coveralls/satnogs/satnogs-db/dev.svg)](https://coveralls.io/github/satnogs/satnogs-db) [![requirements](https://img.shields.io/requires/github/satnogs/satnogs-db.svg?branch=dev)](https://requires.io/github/satnogs/satnogs-db/requirements/?branch=dev) ## License diff --git a/db/api/tests.py b/db/api/tests.py new file mode 100644 index 0000000..55c9628 --- /dev/null +++ b/db/api/tests.py @@ -0,0 +1,26 @@ +import pytest + +from rest_framework import status +from django.test import TestCase + +from db.base.tests import ModeFactory + + +@pytest.mark.django_db(transaction=True) +class ModeViewApiTest(TestCase): + """ + Tests the Mode View API + """ + mode = None + + def setUp(self): + self.mode = ModeFactory() + self.mode.save() + + def test_list(self): + response = self.client.get('/api/modes/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_retrieve(self): + response = self.client.get('/api/modes/%s/' % self.mode.id) + self.assertContains(response, self.mode.name) diff --git a/db/base/tests.py b/db/base/tests.py index c8a4139..ed90e70 100644 --- a/db/base/tests.py +++ b/db/base/tests.py @@ -1,13 +1,44 @@ -from django.contrib.auth.models import User +import random +from datetime import datetime, timedelta +import pytest import factory from factory import fuzzy +from django.contrib.auth.models import User +from django.test import TestCase +from django.utils.timezone import now -from db.base.models import Mode, Satellite, Transmitter, Suggestion +from db.base.models import (DATA_SOURCES, Mode, Satellite, Transmitter, Suggestion, + Telemetry, DemodData) + + +DATA_SOURCE_IDS = [c[0] for c in DATA_SOURCES] + + +def generate_payload(): + payload = '{0:b}'.format(random.randint(500000000, 510000000)) + digits = 1824 + while digits: + digit = random.randint(0, 1) + payload += str(digit) + digits -= 1 + return payload + + +def generate_payload_name(): + filename = datetime.strftime(fuzzy.FuzzyDateTime(now() - timedelta(days=10), now()).fuzz(), + '%Y%m%dT%H%M%SZ') + return filename + + +def get_valid_satellites(): + qs = Transmitter.objects.all() + satellites = Satellite.objects.filter(transmitters__in=qs).distinct() + return satellites class ModeFactory(factory.django.DjangoModelFactory): - """Antenna model factory.""" + """Mode model factory.""" name = fuzzy.FuzzyText() class Meta: @@ -25,6 +56,7 @@ class UserFactory(factory.django.DjangoModelFactory): class SatelliteFactory(factory.django.DjangoModelFactory): """Sattelite model factory.""" norad_cat_id = fuzzy.FuzzyInteger(2000, 4000) + name = fuzzy.FuzzyText() class Meta: model = Satellite @@ -49,9 +81,46 @@ class TransmitterFactory(factory.django.DjangoModelFactory): class SuggestionFactory(factory.django.DjangoModelFactory): - transmitter = factory.SubFactory('db.base.tests.TransmitterFactory') + transmitter = factory.SubFactory(TransmitterFactory) citation = fuzzy.FuzzyText() user = factory.SubFactory(UserFactory) class Meta: model = Suggestion + + +class TelemetryFactory(factory.django.DjangoModelFactory): + satellite = factory.SubFactory(SatelliteFactory) + name = fuzzy.FuzzyText() + schema = '{}' + decoder = 'qb50' + + class Meta: + model = Telemetry + + +class DemodDataFactory(factory.django.DjangoModelFactory): + satellite = factory.SubFactory(SatelliteFactory) + transmitter = factory.SubFactory(TransmitterFactory) + source = fuzzy.FuzzyChoice(choices=DATA_SOURCE_IDS) + data_id = fuzzy.FuzzyInteger(0, 200) + payload_frame = factory.django.FileField(filename='data.raw') + payload_decoded = None + payload_telemetry = None + station = fuzzy.FuzzyText() + lat = fuzzy.FuzzyFloat(-20, 70) + lng = fuzzy.FuzzyFloat(-180, 180) + timestamp = fuzzy.FuzzyDateTime(now() - timedelta(days=10), now()) + + class Meta: + model = DemodData + + +@pytest.mark.django_db(transaction=True) +class HomeViewTest(TestCase): + """ + Simple test to make sure the home page is working + """ + def test_home_page(self): + response = self.client.get('/') + self.assertContains(response, 'SatNOGS DB is, and will always be, an open database.') diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..5384173 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,4 @@ +[pytest] +addopts = -v --cov --cov-report term-missing +python_files = tests.py +DJANGO_SETTINGS_MODULE=db.settings.dev diff --git a/requirements/dev.txt b/requirements/dev.txt index af60661..98caa16 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -2,12 +2,30 @@ -r base.txt # Debug & Testing -factory-boy==2.8.1 \ - --hash=sha256:246f7da9caf9bf855aaa73b4963353ccb147fdd3adcbc419fa29422c5b69dd4c +sqlparse==0.2.2 \ + --hash=sha256:9b61c319b3c7b64681e1b4d554a9c3fe81ed52da00a901ccf3fe72962734e444 flake8==3.3.0 \ --hash=sha256:83905eadba99f73fbfe966598aaf1682b3eb6755d2263c5b33a4e8367d60b0d1 +factory-boy==2.8.1 \ + --hash=sha256:246f7da9caf9bf855aaa73b4963353ccb147fdd3adcbc419fa29422c5b69dd4c +pytest==3.0.6 \ + --hash=sha256:da0ab50c7eec0683bc24f1c1137db1f4111752054ecdad63125e7ec71316b813 +pytest-cov==2.4.0 \ + --hash=sha256:10e37e876f49ddec80d6c83a54b657157f1387ebc0f7755285f8c156130014a1 +pytest-django==3.1.2 \ + --hash=sha256:00995c2999b884a38ae9cd30a8c00ed32b3d38c1041250ea84caf18085589662 +pytest-xdist==1.15.0 \ + --hash=sha256:6238395f8bd050f9288a3b10f34330edece80f4424cf2b4204d6e7d622f0f00b +python-coveralls==2.9.0 \ + --hash=sha256:1f22b69e166ec27475954b65033e21ba54c6a68779c2d39762ce5c4dcbe013d3 +coverage==4.3.4 \ + --hash=sha256:ca36d83cd591d027952e5019149c4386e7058cd674bf8cb52dc622f768d689e9 faker==0.7.7 \ --hash=sha256:249d1bd8fddb80643d4dc91b72c6089c847ab2d0deead946a6d339209ac24146 +docopts==0.6.1 \ + --hash=sha256:ea8d6b03a0931c75a0e4919a0b0856f1c187c38a96174a750c86b41b903a693a +mock==2.0.0 \ +--hash=sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1 # Deps configparser==3.5.0 \ @@ -24,3 +42,27 @@ ipaddress==1.0.18 \ --hash=sha256:d34cf15d95ce9a734560f7400a8bd2ac2606f378e2a1d0eadbf1c98707e7c74a python_dateutil==2.6.0 \ --hash=sha256:537bf2a8f8ce6f6862ad705cd68f9e405c0b5db014aa40fa29eab4335d4b1716 +appdirs==1.4.0 \ + --hash=sha256:85e58578db8f29538f3109c11250c2a5514a2fcdc9890d9b2fe777eb55517736 +packaging==16.8 \ + --hash=sha256:99276dc6e3a7851f32027a68f1095cd3f77c148091b092ea867a351811cfe388 +py==1.4.32 \ + --hash=sha256:2d4bba2e25fff58140e6bdce1e485e89bb59776adbe01d490baa6b1f37a3dd6b +pyparsing==2.1.10 \ + --hash=sha256:67101d7acee692962f33dd30b5dce079ff532dd9aa99ff48d52a3dad51d2fe84 +setuptools==34.2.0 \ + --hash=sha256:75d352eeeddd96a3fb702b1da9f8b89e5f8c045dbd86e3894516733eb5f99713 +apipkg==1.4 \ + --hash=sha256:65d2aa68b28e7d31233bb2ba8eb31cda40e4671f8ac2d6b241e358c9652a74b9 +execnet==1.4.1 \ + --hash=sha256:d2b909c7945832e1c19cfacd96e78da68bdadc656440cfc7dfe59b766744eb8c +pytest-xdist==1.15.0 + --hash=sha256:6238395f8bd050f9288a3b10f34330edece80f4424cf2b4204d6e7d622f0f00b +docopt==0.6.1 \ + --hash=sha256:71ad940a773fbc23be6093e9476ad57b2ecec446946a28d30127501f3b29aa35 +funcsigs==1.0.2 \ + --hash=sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca +pbr==1.10.0 \ + --hash=sha256:f5cf7265a80636ecff66806d13494cbf9d77a3758a65fd8b4d4d4bee81b0c375 +PyYAML==3.12 \ + --hash=sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab