From fbac67abad22e24f980b480ad155e9ab2727512d Mon Sep 17 00:00:00 2001 From: Andria Capai Date: Fri, 17 Jan 2025 17:29:37 +0100 Subject: [PATCH] test: add backend test for individual and marking Reviewed-by: andriacap --- .../gn_module_monitoring/tests/conftest.py | 2 + .../tests/fixtures/generic.py | 2 + .../tests/fixtures/individual.py | 71 ++++++++++++++++++ .../tests/fixtures/marking.py | 33 ++++++++ .../tests/fixtures/observation.py | 18 +++++ .../tests/fixtures/visit.py | 17 +++++ .../test_models/test_individuals.py | 24 ++++++ .../test_models/test_marking.py | 16 ++++ .../test_schemas/test_individual_schema.py | 75 +++++++++++++++++++ 9 files changed, 258 insertions(+) create mode 100644 backend/gn_module_monitoring/tests/conftest.py create mode 100644 backend/gn_module_monitoring/tests/fixtures/individual.py create mode 100644 backend/gn_module_monitoring/tests/fixtures/marking.py create mode 100644 backend/gn_module_monitoring/tests/fixtures/observation.py create mode 100644 backend/gn_module_monitoring/tests/test_monitoring/test_models/test_individuals.py create mode 100644 backend/gn_module_monitoring/tests/test_monitoring/test_models/test_marking.py create mode 100644 backend/gn_module_monitoring/tests/test_monitoring/test_schemas/test_individual_schema.py diff --git a/backend/gn_module_monitoring/tests/conftest.py b/backend/gn_module_monitoring/tests/conftest.py new file mode 100644 index 000000000..3ec0c13d9 --- /dev/null +++ b/backend/gn_module_monitoring/tests/conftest.py @@ -0,0 +1,2 @@ +import pytest +from geonature.tests.test_monitoring import markings, nomenclature_type_markings diff --git a/backend/gn_module_monitoring/tests/fixtures/generic.py b/backend/gn_module_monitoring/tests/fixtures/generic.py index f5fa26bd2..652cb6d7e 100644 --- a/backend/gn_module_monitoring/tests/fixtures/generic.py +++ b/backend/gn_module_monitoring/tests/fixtures/generic.py @@ -40,6 +40,8 @@ def monitorings_users(app): "MONITORINGS_GRP_SITES", "MONITORINGS_SITES", "MONITORINGS_VISITES", + "MONITORINGS_INDIVIDUALS", + "MONITORINGS_MARKINGS", "ALL", ] diff --git a/backend/gn_module_monitoring/tests/fixtures/individual.py b/backend/gn_module_monitoring/tests/fixtures/individual.py new file mode 100644 index 000000000..dacdbb82e --- /dev/null +++ b/backend/gn_module_monitoring/tests/fixtures/individual.py @@ -0,0 +1,71 @@ +import pytest + +from sqlalchemy import select, and_ +from sqlalchemy.orm import joinedload + +from geonature.utils.env import db +from apptax.taxonomie.models import Taxref + +from geonature.core.gn_monitoring.models import corIndividualModule +from gn_module_monitoring.monitoring.models import TMonitoringIndividuals +from gn_module_monitoring.tests.fixtures.marking import * + +SPECIE = "Athene noctua" + + +@pytest.fixture +def individuals(monitorings_users, monitoring_module): + user = monitorings_users["user"] + cd_nom = db.session.execute( + select(Taxref.cd_nom).where( + and_(Taxref.lb_nom.ilike(SPECIE), Taxref.cd_nom == Taxref.cd_ref) + ) + ).scalar_one_or_none() + if cd_nom is None: + raise ValueError(f"L'espèce '{SPECIE}' n'a pas été trouvée dans la table Taxref.") + + db_individuals = {} + cor_individual_module = [] + individuals_key = ["individual_with_site", "orphan_individual"] + + for key in individuals_key: + db_individuals[key] = TMonitoringIndividuals( + individual_name=key, + cd_nom=cd_nom, + active=True, + id_digitiser=user.id_role, + ) + # Insertion des individus dans la base de données + with db.session.begin_nested(): + db.session.add_all(db_individuals.values()) + db.session.flush() + + for key in individuals_key: + cor_individual_module.append( + { + "id_individual": db_individuals[ + key + ].id_individual, # Maintenant, l'ID est disponible + "id_module": monitoring_module.id_module, + } + ) + + # Insertion dans la table de relation corIndividualModule + db.session.execute(corIndividualModule.insert(), cor_individual_module) + + return db_individuals + + +# TODO: a enlever si pas besoin du tests pour les relationship avec TMonitoringIndividuals +@pytest.fixture +def individual_with_marking(individuals, markings): + individual = ( + db.session.query(TMonitoringIndividuals) + .options(joinedload(TMonitoringIndividuals.markings)) + .filter( + TMonitoringIndividuals.id_individual + == individuals["individual_with_site"].id_individual + ) + .one() + ) + return individual diff --git a/backend/gn_module_monitoring/tests/fixtures/marking.py b/backend/gn_module_monitoring/tests/fixtures/marking.py new file mode 100644 index 000000000..5328e1c6f --- /dev/null +++ b/backend/gn_module_monitoring/tests/fixtures/marking.py @@ -0,0 +1,33 @@ +import pytest + +from geonature.utils.env import db + +from gn_module_monitoring.monitoring.models import TMonitoringMarkingEvent + + +# TODO: meme fixture que celle présente dans GN à l'exception que c'est TMonitoringMarkingEvent utilisé au lieu de TMarkingEvent +# et pas les user et module utilisé +@pytest.fixture +def markings(users, monitoring_module, individuals, nomenclature_type_markings): + user = users["user"] + markings = [] + for key in individuals: + markings.append( + TMonitoringMarkingEvent( + id_individual=individuals[key].id_individual, + id_module=monitoring_module.id_module, + digitiser=user, + operator=user, + marking_date="2025-01-01", + marking_location="Là bas", + marking_code="0007", + marking_details="Super super", + id_nomenclature_marking_type=nomenclature_type_markings.id_nomenclature, + ) + ) + + with db.session.begin_nested(): + db.session.add_all(markings) + db.session.flush() + + return markings diff --git a/backend/gn_module_monitoring/tests/fixtures/observation.py b/backend/gn_module_monitoring/tests/fixtures/observation.py new file mode 100644 index 000000000..184a01e0d --- /dev/null +++ b/backend/gn_module_monitoring/tests/fixtures/observation.py @@ -0,0 +1,18 @@ +import pytest + +from geonature.utils.env import db + +from gn_module_monitoring.monitoring.models import TMonitoringObservations + + +@pytest.fixture +def observation_with_individual(visit_with_individual, individuals, monitoring_module): + db_observation = TMonitoringObservations( + id_base_visit=visit_with_individual.id_base_visit, + cd_nom=individuals["individual_with_site"].cd_nom, + id_digitiser=visit_with_individual.id_digitiser, + id_individual=individuals["individual_with_site"].id_individual, + ) + with db.session.begin_nested(): + db.session.add(db_observation) + return db_observation diff --git a/backend/gn_module_monitoring/tests/fixtures/visit.py b/backend/gn_module_monitoring/tests/fixtures/visit.py index 4ea007d41..34c34ba3b 100644 --- a/backend/gn_module_monitoring/tests/fixtures/visit.py +++ b/backend/gn_module_monitoring/tests/fixtures/visit.py @@ -24,3 +24,20 @@ def visits(sites, datasets, monitoring_module): db.session.add_all(db_visits) return db_visits + + +@pytest.fixture +def visit_with_individual(sites, datasets, monitorings_users, monitoring_module): + user = monitorings_users["user"] + now = datetime.datetime.now() + dataset = datasets["orphan_dataset"] + db_visit = TMonitoringVisits( + id_base_site=sites["no-type"].id_base_site, + id_module=monitoring_module.id_module, + id_dataset=dataset.id_dataset, + visit_date_min=now, + id_digitiser=user.id_role, + ) + with db.session.begin_nested(): + db.session.add(db_visit) + return db_visit diff --git a/backend/gn_module_monitoring/tests/test_monitoring/test_models/test_individuals.py b/backend/gn_module_monitoring/tests/test_monitoring/test_models/test_individuals.py new file mode 100644 index 000000000..3f138454e --- /dev/null +++ b/backend/gn_module_monitoring/tests/test_monitoring/test_models/test_individuals.py @@ -0,0 +1,24 @@ +import pytest + +from geonature.core.gn_monitoring.models import TIndividuals +from gn_module_monitoring.monitoring.models import ( + PermissionModel, + TMonitoringIndividuals, + MonitoringQuery, +) +from gn_module_monitoring.tests.fixtures.individual import * +from gn_module_monitoring.tests.fixtures.observation import * + + +@pytest.mark.usefixtures("temporary_transaction") +class TestMonitoringIndividuals: + def test_model_inheritance(self): + assert issubclass(TMonitoringIndividuals, TIndividuals) + assert issubclass(TMonitoringIndividuals, PermissionModel) + assert issubclass(TMonitoringIndividuals, MonitoringQuery) + + def test_nb_sites( + self, individuals, sites, visit_with_individual, observation_with_individual + ): + assert individuals["individual_with_site"].nb_sites == 1 + assert individuals["orphan_individual"].nb_sites == 0 diff --git a/backend/gn_module_monitoring/tests/test_monitoring/test_models/test_marking.py b/backend/gn_module_monitoring/tests/test_monitoring/test_models/test_marking.py new file mode 100644 index 000000000..8eb7db3d6 --- /dev/null +++ b/backend/gn_module_monitoring/tests/test_monitoring/test_models/test_marking.py @@ -0,0 +1,16 @@ +import pytest + +from geonature.core.gn_monitoring.models import TMarkingEvent +from gn_module_monitoring.monitoring.models import ( + PermissionModel, + TMonitoringMarkingEvent, + MonitoringQuery, +) + + +@pytest.mark.usefixtures("temporary_transaction") +class TestMonitoringMarkingEvent: + def test_model_inheritance(self): + assert issubclass(TMonitoringMarkingEvent, TMarkingEvent) + assert issubclass(TMonitoringMarkingEvent, PermissionModel) + assert issubclass(TMonitoringMarkingEvent, MonitoringQuery) diff --git a/backend/gn_module_monitoring/tests/test_monitoring/test_schemas/test_individual_schema.py b/backend/gn_module_monitoring/tests/test_monitoring/test_schemas/test_individual_schema.py new file mode 100644 index 000000000..ef97c5723 --- /dev/null +++ b/backend/gn_module_monitoring/tests/test_monitoring/test_schemas/test_individual_schema.py @@ -0,0 +1,75 @@ +import pytest +from marshmallow import ValidationError + +from gn_module_monitoring.monitoring.schemas import MonitoringIndividualsSchema +from gn_module_monitoring.tests.fixtures.individual import * +from gn_module_monitoring.tests.fixtures.marking import * + + +@pytest.mark.usefixtures("temporary_transaction") +class TestMonitoringIndividuals: + def test_monitoring_individuals_schema_serialization(self, individuals): + # Récupération de l'individu + individual = individuals["individual_with_site"] + + # Sérialisation avec le schéma + schema = MonitoringIndividualsSchema() + serialized_data = schema.dump(individual) + + # Vérifications + assert serialized_data["id_individual"] == individual.id_individual + assert serialized_data["individual_name"] == individual.individual_name + assert serialized_data["cd_nom"] == individual.cd_nom + assert serialized_data["active"] == individual.active + assert serialized_data["id_digitiser"] == individual.id_digitiser + + def test_monitoring_individuals_schema_deserialization(self, users): + # Données d'entrée + user = users["user"] + input_data = { + "individual_name": "Test Individual", + "cd_nom": 12345, + "active": True, + "id_digitiser": user.id_role, + } + + # Désérialisation avec le schéma + schema = MonitoringIndividualsSchema() + deserialized_data = schema.load(input_data) + + # Vérifications + assert deserialized_data["individual_name"] == input_data["individual_name"] + assert deserialized_data["cd_nom"] == input_data["cd_nom"] + assert deserialized_data["active"] == input_data["active"] + assert deserialized_data["id_digitiser"] == input_data["id_digitiser"] + + def test_monitoring_individuals_schema_validation(self): + # Données d'entrée invalides + invalid_data = { + "individual_name": None, # Nom vide + "cd_nom": None, # cd_nom manquant + "id_digitiser": 99999, # ID utilisateur inexistant + } + + # Désérialisation avec validation + schema = MonitoringIndividualsSchema() + try: + schema.load(invalid_data) + except ValidationError as err: + errors = err.messages + + # Vérifications des erreurs + assert "individual_name" in errors + assert "cd_nom" in errors + # TODO: ici ça passe avec un id_digitiser non existant + # assert "id_digitiser" in errors + + # TODO: est ce que le dump permet de récupérer les relations ? Pour l'instant ce test ne passe pas + # def test_schema_load_relationships(self,sites, individual_with_marking, markings): + + # # Sérialisation avec le schéma + # schema = MonitoringIndividualsSchema() + # serialized_data = schema.dump(individual_with_marking) + + # # Vérification que les relations sont bien incluses + # assert "markings" in serialized_data