1
0
Fork 0

More improved unit testing

Additional pytests, including tests for a fully populated DB

Also:

- simplify a conditional statement in the home page view

- fix broken robots.txt url parsing

- fix case in cached stats generation where new satellite id association could
trip a comparison against a NoneType by adding a default

- removed a print statement leftover from satellite id development

Signed-off-by: Corey Shields <cshields@gmail.com>
spacecruft
Corey Shields 2021-05-25 16:31:08 -04:00
parent 33357e9207
commit 79ca1834c9
5 changed files with 147 additions and 36 deletions

View File

@ -227,6 +227,7 @@ class TelemetryViewApiTest(TestCase):
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
@pytest.mark.django_db(transaction=True)
class LoginView(TestCase):
"""
Tests various API endpoints with authentication

View File

@ -1,13 +1,16 @@
"""SatNOGS DB test suites"""
# pylint: disable=R0903
# pylint: disable=R0903,W0612
# flake8: noqa: F841
from datetime import timedelta
import factory
import pytest
from django.contrib.auth import get_user_model
from django.contrib.auth.models import User # pylint: disable=E5142
from django.test import TestCase
from django.utils.timezone import now
from factory import fuzzy
from pytest_django.asserts import assertContains # pylint: disable=E0611
from db.base.models import DATA_SOURCES, DemodData, Mode, Satellite, SatelliteEntry, \
SatelliteIdentifier, Telemetry, Transmitter, TransmitterSuggestion
@ -127,6 +130,7 @@ class TelemetryFactory(factory.django.DjangoModelFactory):
model = Telemetry
# @pytest.mark.django_db
class DemodDataFactory(factory.django.DjangoModelFactory):
"""DemodData model factory."""
satellite = factory.SubFactory(SatelliteFactory)
@ -146,39 +150,145 @@ class DemodDataFactory(factory.django.DjangoModelFactory):
@pytest.mark.django_db(transaction=True)
class HomeViewTest(TestCase):
"""
Simple test to make sure the home page is working
"""
def test_home_page(self):
"""Tests for a known string in the SatNOGS DB home page template"""
response = self.client.get('/')
self.assertContains(response, 'New Satellites')
# class HomeViewTest(TestCase):
# """
# Simple test to make sure the home page is working
# """
def test_home_page(client):
"""Tests the SatNOGS DB home page in an unpopulated state"""
response = client.get('/')
assertContains(response, 'no contributions')
@pytest.mark.django_db(transaction=True)
class SatelliteViewTest(TestCase):
"""
Test to make sure the satellite page is working
"""
satellite = None
def test_satellite_norad_404(client):
"""Tests for satellite not found by norad ID"""
response = client.get('/satellite/999999/')
assert response.status_code == 404
@pytest.mark.django_db(transaction=True)
def test_satellite_id_404(client):
"""Tests for satellite not found by satellite ID"""
response = client.get('/satellite/AAAA-AAAA-AAAA-AAAA-AAAA/')
assert response.status_code == 404
@pytest.mark.django_db(transaction=True)
# class AboutViewTest(TestCase):
# """
# Test to make sure the about page is working
# """
def test_about_page(client):
"""Tests for a known string in the SatNOGS DB about page template"""
response = client.get('/about/')
assertContains(response, 'SatNOGS DB is an effort to create an hollistic')
@pytest.mark.django_db(transaction=True)
@pytest.mark.usefixtures('celery_session_app')
@pytest.mark.usefixtures('celery_session_worker')
class PopulatedDBTest(TestCase):
"""
Tests with sample data populated
"""
def setUp(self):
self.satellite = SatelliteFactory()
self.satellite.save()
self.client.force_login(User.objects.get_or_create(username='testuser')[0])
def test_satellite_page(self):
"""Tests for satellite name in a SatNOGS DB satellite page"""
response = self.client.get('/satellite/%s/' % self.satellite.satellite_entry.norad_cat_id)
self.assertContains(response, self.satellite.satellite_entry.name)
# start by creating a bunch of satellite entries
satellites = []
satellites = [SatelliteFactory() for i in range(10)]
# now create transmitters and some DemodData in the past 24h for the satellites
for sat in range(0, len(satellites) - 1):
demod = []
demod = [
DemodDataFactory(
satellite=satellites[sat],
timestamp=fuzzy.FuzzyDateTime(now() - timedelta(days=1), now())
) for i in range(10)
]
transmitters = []
transmitters = [TransmitterFactory(satellite=satellites[sat]) for i in range(2)]
bad_transmitter = TransmitterFactory(status='inactive')
good_transmitter = TransmitterFactory(status='active')
# make sure we have a recent demoddata to show
recent_demod_data = DemodDataFactory(timestamp=now())
# and the newest satellite with no data
recent_satellite_entry = SatelliteEntryFactory(created=now())
recent_satellite = SatelliteFactory(satellite_entry=recent_satellite_entry)
def test_home_page(self):
"""Tests for known strings in the populated SatNOGS DB home page"""
response = self.client.get('/')
assertContains(response, 'Latest data timestamp')
assertContains(response, 'Data - Last 24h')
assertContains(response, 'No Data')
def test_satellites_page(self):
"""Tests for known strings in the populated satellites page"""
check_sat = Satellite.objects.first()
response = self.client.get('/satellites/')
assertContains(response, check_sat.satellite_identifier)
def test_satellite_by_id(self):
"""Tests for a good satellite entry by satellite ID"""
check_sat = Satellite.objects.first()
# go ahead and test transmitter suggestions here too
TransmitterSuggestionFactory(satellite=check_sat)
response = self.client.get('/satellite/%s/' % check_sat.satellite_identifier)
assertContains(response, check_sat.satellite_entry.name)
def test_satellite_by_norad(self):
"""Tests for a good satellite entry by NORAD ID"""
check_sat = Satellite.objects.first()
response = self.client.get('/satellite/%s/' % check_sat.satellite_entry.norad_cat_id)
assertContains(response, check_sat.satellite_entry.name)
def test_transmitter_page(self):
"""Tests for known strings in the populated transmitters page"""
response = self.client.get('/transmitters/')
assertContains(response, '<td>active</td>')
assertContains(response, '<td>inactive</td>')
def test_search_redirect(self):
"""Tests satellite search redirect"""
check_sat = Satellite.objects.first()
response = self.client.get('/search/?q=%s' % check_sat.satellite_entry.name)
assert response.status_code == 302
def test_multiple_search_results(self):
"""Tests satellite search with multiple results"""
check_sat = Satellite.objects.first()
# assume our population has created enough data for multiple hits of 1
response = self.client.get('/search/?q=1')
assertContains(response, 'multiple results')
def test_bad_search(self):
"""Tests satellite search ending in 404"""
check_sat = Satellite.objects.first()
response = self.client.get('/search/?q=XXXXXXXXXX')
assertContains(response, 'No results found')
def test_stats(self):
"""Tests stats page against count of satellites"""
# At some point we should force a celery run and test against the total sat cnt
# refresh statistics first
refresh = self.client.get('/statistics/')
response = self.client.get('/stats/')
assertContains(response, 'Total Satellites')
@pytest.mark.django_db(transaction=True)
class AboutViewTest(TestCase):
"""
Test to make sure the about page is working
"""
def test_about_page(self):
"""Tests for a known string in the SatNOGS DB about page template"""
response = self.client.get('/about/')
self.assertContains(response, 'SatNOGS DB is an effort to create an hollistic')
def test_robots(client):
"""Tests for a known string in the SatNOGS DB about page template"""
response = client.get('/robots.txt')
assertContains(response, 'Disallow')
def test_help(client):
"""Tests for a known string in the help modal"""
response = client.get('/help/')
assertContains(response, 'You can ask questions')

View File

@ -31,7 +31,7 @@ BASE_URLPATTERNS = (
path('statistics/', views.statistics, name='statistics'),
path('stats/', views.stats, name='stats'),
path('users/edit/', views.users_edit, name='users_edit'),
path(r'robots\.txt', views.robots, name='robots'),
path('robots.txt', views.robots, name='robots'),
path('search/', views.search, name='search_results'),
path('create_satellite/', views.SatelliteCreateView.as_view(), name='create_satellite'),
path(

View File

@ -451,14 +451,15 @@ def cache_statistics():
# Aggregate stats for satellites and their associated ones
for sat in satellites:
print(sat, sat['associated_satellite'], flush=True)
# if satellite is merged then add statistics to its association
if sat['associated_satellite']:
if sat['associated_satellite'] in sat_stats:
sat_stats[sat['associated_satellite']]['count'] += sat['count']
sat_stats[sat['associated_satellite']]['decoded'] += sat['decoded']
sat_stats[sat['associated_satellite']]['latest_payload'] = max(
sat_stats[sat['associated_satellite']]['latest_payload'], sat['latest_payload']
sat_stats[sat['associated_satellite']]['latest_payload'],
sat['latest_payload'],
default=sat['latest_payload']
)
else:
del sat['associated_satellite']

View File

@ -56,9 +56,8 @@ def home(request):
page = paginator.page(1)
while not found:
for data in page.object_list:
if data.satellite.id in latest_data_satellites:
continue
latest_data_satellites.append(data.satellite.id)
if data.satellite.id not in latest_data_satellites:
latest_data_satellites.append(data.satellite.id)
if len(latest_data_satellites) > 5:
found = True
break
@ -206,7 +205,7 @@ def request_export(request, sat_pk, period=None):
completed.
:returns: the originating satellite page
"""
satellite_obj = get_object_or_404(Satellite, pk=sat_pk)
satellite_obj = get_object_or_404(Satellite, id=sat_pk)
if satellite_obj.associated_satellite:
satellite_obj = satellite_obj.associated_satellite