Files
dbstorage/dbapp/mainapp/tests.py

431 lines
19 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from django.test import TestCase, RequestFactory
from django.contrib.auth.models import User
from django.contrib.gis.geos import Point
from .models import CustomUser, Geo, ObjItem
from .utils import format_coordinates, parse_pagination_params
from .mixins import RoleRequiredMixin, CoordinateProcessingMixin
from django.views import View
class FormatCoordinatesTestCase(TestCase):
"""Тесты для функции format_coordinates"""
def test_format_positive_coordinates(self):
"""Тест форматирования положительных координат"""
result = format_coordinates(37.62, 55.75)
self.assertEqual(result, "55.75N 37.62E")
def test_format_negative_longitude(self):
"""Тест форматирования с отрицательной долготой"""
result = format_coordinates(-122.42, 37.77)
self.assertEqual(result, "37.77N 122.42W")
def test_format_negative_latitude(self):
"""Тест форматирования с отрицательной широтой"""
result = format_coordinates(151.21, -33.87)
self.assertEqual(result, "33.87S 151.21E")
def test_format_both_negative(self):
"""Тест форматирования с обеими отрицательными координатами"""
result = format_coordinates(-58.38, -34.60)
self.assertEqual(result, "34.6S 58.38W")
class ParsePaginationParamsTestCase(TestCase):
"""Тесты для функции parse_pagination_params"""
def setUp(self):
self.factory = RequestFactory()
def test_default_values(self):
"""Тест значений по умолчанию"""
request = self.factory.get("/")
page, per_page = parse_pagination_params(request)
self.assertEqual(page, 1)
self.assertEqual(per_page, 50)
def test_custom_values(self):
"""Тест пользовательских значений"""
request = self.factory.get("/?page=3&items_per_page=100")
page, per_page = parse_pagination_params(request)
self.assertEqual(page, 3)
self.assertEqual(per_page, 100)
def test_invalid_page_number(self):
"""Тест невалидного номера страницы"""
request = self.factory.get("/?page=invalid")
page, per_page = parse_pagination_params(request)
self.assertEqual(page, 1)
def test_negative_page_number(self):
"""Тест отрицательного номера страницы"""
request = self.factory.get("/?page=-5")
page, per_page = parse_pagination_params(request)
self.assertEqual(page, 1)
def test_max_items_per_page_limit(self):
"""Тест ограничения максимального количества элементов"""
request = self.factory.get("/?items_per_page=20000")
page, per_page = parse_pagination_params(request)
self.assertEqual(per_page, 10000)
class RoleRequiredMixinTestCase(TestCase):
"""Тесты для RoleRequiredMixin"""
def setUp(self):
self.factory = RequestFactory()
def test_admin_has_access(self):
"""Тест что администратор имеет доступ"""
user = User.objects.create_user(username="testuser", password="12345")
# Get the automatically created CustomUser and set role to 'admin'
custom_user = CustomUser.objects.get(user=user)
custom_user.role = "admin"
custom_user.save()
# Refresh user to get updated customuser
user.refresh_from_db()
class TestView(RoleRequiredMixin, View):
required_roles = ["admin", "moderator"]
view = TestView()
request = self.factory.get("/")
request.user = user
view.request = request
self.assertTrue(view.test_func())
def test_user_without_role_denied(self):
"""Тест что пользователь без роли не имеет доступа"""
user_no_role = User.objects.create_user(username="norole", password="12345")
# Get the automatically created CustomUser - default role is 'user'
custom_user_no_role = CustomUser.objects.get(user=user_no_role)
self.assertEqual(custom_user_no_role.role, "user")
class TestView(RoleRequiredMixin, View):
required_roles = ["admin", "moderator"]
view = TestView()
request = self.factory.get("/")
request.user = user_no_role
view.request = request
self.assertFalse(view.test_func())
class CoordinateProcessingMixinTestCase(TestCase):
"""Тесты для CoordinateProcessingMixin"""
def setUp(self):
self.factory = RequestFactory()
def test_extract_geo_coordinates(self):
"""Тест извлечения координат геолокации"""
class TestView(CoordinateProcessingMixin, View):
pass
view = TestView()
request = self.factory.post(
"/", {"geo_longitude": "37.62", "geo_latitude": "55.75"}
)
view.request = request
coords = view._extract_coordinates("geo")
self.assertIsNotNone(coords)
self.assertEqual(coords, (37.62, 55.75))
def test_extract_invalid_coordinates(self):
"""Тест извлечения невалидных координат"""
class TestView(CoordinateProcessingMixin, View):
pass
view = TestView()
request = self.factory.post(
"/", {"geo_longitude": "invalid", "geo_latitude": "55.75"}
)
view.request = request
coords = view._extract_coordinates("geo")
self.assertIsNone(coords)
def test_process_coordinates(self):
"""Тест обработки координат и применения к объекту Geo"""
class TestView(CoordinateProcessingMixin, View):
pass
view = TestView()
request = self.factory.post(
"/",
{
"geo_longitude": "37.62",
"geo_latitude": "55.75",
},
)
view.request = request
geo_instance = Geo()
view.process_coordinates(geo_instance)
self.assertIsNotNone(geo_instance.coords)
self.assertEqual(geo_instance.coords.coords, (37.62, 55.75))
class CSVImportTestCase(TestCase):
"""Тесты для функции get_points_from_csv"""
def setUp(self):
"""Подготовка тестовых данных"""
from .models import CustomUser, Satellite, Polarization
from django.contrib.auth.models import User
# Создаем пользователя
user = User.objects.create_user(username="testuser", password="12345")
self.custom_user = CustomUser.objects.get(user=user)
# Создаем спутник
self.satellite = Satellite.objects.create(name="Test Satellite", norad=12345)
# Создаем поляризации
Polarization.objects.get_or_create(name="Вертикальная")
Polarization.objects.get_or_create(name="Горизонтальная")
Polarization.objects.get_or_create(name="Правая")
Polarization.objects.get_or_create(name="Левая")
Polarization.objects.get_or_create(name="-")
# Создаем спутники-зеркала для тестов
Satellite.objects.get_or_create(name="Mirror1 Satellite", norad=11111)
Satellite.objects.get_or_create(name="Mirror2 Satellite", norad=22222)
Satellite.objects.get_or_create(name="Mirror3 Satellite", norad=33333)
def test_initial_csv_import(self):
"""Тест первичного импорта из CSV файла"""
from .utils import get_points_from_csv
from .models import Source, ObjItem
# Тестовые данные CSV - 3 точки в разных местах
csv_content = """1;Signal1 V;55.7558;37.6173;0;01.01.2024 12:00:00;Test Satellite;12345;11500.5;36.0;1;good;Mirror1;Mirror2;Mirror3
2;Signal2 H;55.7560;37.6175;0;01.01.2024 12:05:00;Test Satellite;12345;11520.3;36.0;1;good;Mirror1;Mirror2;
3;Signal3 V;56.8389;60.6057;0;01.01.2024 12:10:00;Test Satellite;12345;11540.7;36.0;1;good;Mirror1;Mirror2;"""
# Выполняем импорт
result = get_points_from_csv(csv_content, self.custom_user)
# Проверяем результаты
# Первые две точки близко (Москва), третья далеко (Екатеринбург)
# Должно быть создано 2 источника
self.assertEqual(result['new_sources'], 2)
self.assertEqual(result['added'], 3)
self.assertEqual(result['skipped'], 0)
self.assertEqual(len(result['errors']), 0)
self.assertEqual(Source.objects.count(), 2)
self.assertEqual(ObjItem.objects.count(), 3)
# Проверяем, что первые две точки привязаны к одному источнику
source1 = Source.objects.first()
items_in_source1 = ObjItem.objects.filter(source=source1).count()
self.assertEqual(items_in_source1, 2)
def test_csv_import_with_existing_sources(self):
"""Тест импорта CSV с существующими источниками"""
from .utils import get_points_from_csv
from .models import Source, ObjItem
# Первый импорт - создаем начальные данные
csv_content_1 = """1;Signal1 V;55.7558;37.6173;0;01.01.2024 12:00:00;Test Satellite;12345;11500.5;36.0;1;good;Mirror1;Mirror2;
2;Signal2 H;55.7560;37.6175;0;01.01.2024 12:05:00;Test Satellite;12345;11520.3;36.0;1;good;Mirror1;Mirror2;"""
result_1 = get_points_from_csv(csv_content_1, self.custom_user)
self.assertEqual(result_1['new_sources'], 1)
initial_sources_count = Source.objects.count()
initial_objitems_count = ObjItem.objects.count()
# Второй импорт - добавляем новые точки
# Точка 3 - близко к существующему источнику (Москва)
# Точка 4 - далеко (Екатеринбург) - создаст новый источник
csv_content_2 = """3;Signal3 V;55.7562;37.6177;0;01.01.2024 12:10:00;Test Satellite;12345;11540.7;36.0;1;good;Mirror1;Mirror2;
4;Signal4 H;56.8389;60.6057;0;01.01.2024 12:15:00;Test Satellite;12345;11560.2;36.0;1;good;Mirror1;Mirror2;"""
result_2 = get_points_from_csv(csv_content_2, self.custom_user)
# Проверяем результаты
# Должен быть создан 1 новый источник (для точки 4)
self.assertEqual(result_2['new_sources'], 1)
self.assertEqual(result_2['added'], 2)
self.assertEqual(Source.objects.count(), initial_sources_count + 1)
self.assertEqual(ObjItem.objects.count(), initial_objitems_count + 2)
# Проверяем, что точка 3 добавлена к существующему источнику
first_source = Source.objects.first()
items_in_first_source = ObjItem.objects.filter(source=first_source).count()
self.assertEqual(items_in_first_source, 3) # 2 начальных + 1 новая
def test_csv_import_skip_duplicates(self):
"""Тест пропуска дубликатов при импорте CSV"""
from .utils import get_points_from_csv
from .models import Source, ObjItem
# Первый импорт
csv_content_1 = """1;Signal1 V;55.7558;37.6173;0;01.01.2024 12:00:00;Test Satellite;12345;11500.5;36.0;1;good;Mirror1;Mirror2;"""
get_points_from_csv(csv_content_1, self.custom_user)
initial_sources_count = Source.objects.count()
initial_objitems_count = ObjItem.objects.count()
# Второй импорт - та же точка (дубликат)
csv_content_2 = """1;Signal1 V;55.7558;37.6173;0;01.01.2024 12:00:00;Test Satellite;12345;11500.5;36.0;1;good;Mirror1;Mirror2;"""
result = get_points_from_csv(csv_content_2, self.custom_user)
# Проверяем, что дубликат пропущен
self.assertEqual(result['new_sources'], 0)
self.assertEqual(result['added'], 0)
self.assertEqual(result['skipped'], 1)
self.assertEqual(Source.objects.count(), initial_sources_count)
self.assertEqual(ObjItem.objects.count(), initial_objitems_count)
def test_csv_import_mixed_scenario(self):
"""Тест смешанного сценария: дубликаты + новые точки + близкие точки"""
from .utils import get_points_from_csv
from .models import Source, ObjItem
# Первый импорт - 2 точки в Москве
csv_content_1 = """1;Signal1 V;55.7558;37.6173;0;01.01.2024 12:00:00;Test Satellite;12345;11500.5;36.0;1;good;Mirror1;Mirror2;
2;Signal2 H;55.7560;37.6175;0;01.01.2024 12:05:00;Test Satellite;12345;11520.3;36.0;1;good;Mirror1;Mirror2;"""
get_points_from_csv(csv_content_1, self.custom_user)
# Второй импорт:
# - Точка 1 (дубликат) - должна быть пропущена
# - Точка 3 (близко к Москве) - должна добавиться к существующему источнику
# - Точка 4 (Екатеринбург) - должна создать новый источник
# - Точка 5 (близко к Екатеринбургу) - должна добавиться к новому источнику
csv_content_2 = """1;Signal1 V;55.7558;37.6173;0;01.01.2024 12:00:00;Test Satellite;12345;11500.5;36.0;1;good;Mirror1;Mirror2;
3;Signal3 V;55.7562;37.6177;0;01.01.2024 12:10:00;Test Satellite;12345;11540.7;36.0;1;good;Mirror1;Mirror2;
4;Signal4 H;56.8389;60.6057;0;01.01.2024 12:15:00;Test Satellite;12345;11560.2;36.0;1;good;Mirror1;Mirror2;
5;Signal5 V;56.8391;60.6059;0;01.01.2024 12:20:00;Test Satellite;12345;11580.8;36.0;1;good;Mirror1;Mirror2;"""
result = get_points_from_csv(csv_content_2, self.custom_user)
# Проверяем результаты
self.assertEqual(result['new_sources'], 1) # Только для Екатеринбурга
self.assertEqual(result['added'], 3) # Точки 3, 4, 5
self.assertEqual(result['skipped'], 1) # Точка 1 (дубликат)
self.assertEqual(Source.objects.count(), 2) # Москва + Екатеринбург
self.assertEqual(ObjItem.objects.count(), 5) # 2 начальных + 3 новых (дубликат пропущен)
# Проверяем распределение по источникам
moscow_source = Source.objects.first()
ekb_source = Source.objects.last()
moscow_items = ObjItem.objects.filter(source=moscow_source).count()
ekb_items = ObjItem.objects.filter(source=ekb_source).count()
self.assertEqual(moscow_items, 3) # 2 начальных + 1 новая
self.assertEqual(ekb_items, 2) # 2 новых точки в Екатеринбурге
class FindMirrorSatellitesTestCase(TestCase):
"""Тесты для функции find_mirror_satellites"""
def setUp(self):
"""Подготовка тестовых данных"""
from .models import Satellite
# Создаем спутники с разными именами
Satellite.objects.create(name="Eutelsat 16A", norad=40874)
Satellite.objects.create(name="Eutelsat 21B", norad=41591)
Satellite.objects.create(name="Astra 4A", norad=41404)
Satellite.objects.create(name="Turksat 4A", norad=40361)
Satellite.objects.create(name="Express AM6", norad=39508)
def test_find_exact_match(self):
"""Тест поиска спутника по точному совпадению"""
from .utils import find_mirror_satellites
mirrors = find_mirror_satellites(["Eutelsat 16A"])
self.assertEqual(len(mirrors), 1)
self.assertEqual(mirrors[0].name, "Eutelsat 16A")
def test_find_partial_match(self):
"""Тест поиска спутника по частичному совпадению"""
from .utils import find_mirror_satellites
# Ищем по части имени "Eutelsat"
mirrors = find_mirror_satellites(["eutelsat"])
self.assertEqual(len(mirrors), 2)
names = [m.name for m in mirrors]
self.assertIn("Eutelsat 16A", names)
self.assertIn("Eutelsat 21B", names)
def test_find_case_insensitive(self):
"""Тест поиска без учета регистра"""
from .utils import find_mirror_satellites
# Разные варианты регистра
mirrors1 = find_mirror_satellites(["ASTRA"])
mirrors2 = find_mirror_satellites(["astra"])
mirrors3 = find_mirror_satellites(["AsTrA"])
self.assertEqual(len(mirrors1), 1)
self.assertEqual(len(mirrors2), 1)
self.assertEqual(len(mirrors3), 1)
self.assertEqual(mirrors1[0].name, "Astra 4A")
self.assertEqual(mirrors2[0].name, "Astra 4A")
self.assertEqual(mirrors3[0].name, "Astra 4A")
def test_find_multiple_mirrors(self):
"""Тест поиска нескольких зеркал"""
from .utils import find_mirror_satellites
mirrors = find_mirror_satellites(["Eutelsat", "Turksat"])
self.assertEqual(len(mirrors), 3) # 2 Eutelsat + 1 Turksat
names = [m.name for m in mirrors]
self.assertIn("Eutelsat 16A", names)
self.assertIn("Eutelsat 21B", names)
self.assertIn("Turksat 4A", names)
def test_find_with_spaces(self):
"""Тест поиска с пробелами в начале и конце"""
from .utils import find_mirror_satellites
mirrors = find_mirror_satellites([" Express "])
self.assertEqual(len(mirrors), 1)
self.assertEqual(mirrors[0].name, "Express AM6")
def test_find_empty_list(self):
"""Тест с пустым списком"""
from .utils import find_mirror_satellites
mirrors = find_mirror_satellites([])
self.assertEqual(len(mirrors), 0)
def test_find_with_dash(self):
"""Тест с дефисом (должен быть пропущен)"""
from .utils import find_mirror_satellites
mirrors = find_mirror_satellites(["-"])
self.assertEqual(len(mirrors), 0)
def test_find_no_match(self):
"""Тест когда спутник не найден"""
from .utils import find_mirror_satellites
mirrors = find_mirror_satellites(["NonExistentSatellite"])
self.assertEqual(len(mirrors), 0)
def test_find_removes_duplicates(self):
"""Тест удаления дубликатов"""
from .utils import find_mirror_satellites
# Ищем один и тот же спутник дважды
mirrors = find_mirror_satellites(["Astra", "Astra 4A"])
self.assertEqual(len(mirrors), 1)
self.assertEqual(mirrors[0].name, "Astra 4A")