From b9f3db91d476ffdfadeaa26aa0c2ca05262ee487 Mon Sep 17 00:00:00 2001 From: iziram Date: Mon, 19 Dec 2022 21:32:45 +0100 Subject: [PATCH] tests unitaires assiduites --- app/models/assiduites.py | 9 +- app/scodoc/sco_assiduites.py | 2 +- app/scodoc/sco_utils.py | 4 +- ...ajout_modeles_assiduites_justificatifs.py} | 12 +- tests/unit/test_assiduites.py | 315 ++++++++++++++++++ 5 files changed, 331 insertions(+), 11 deletions(-) rename migrations/versions/{7b762fcbf644_models_assiduites.py => 530594458193_ajout_modeles_assiduites_justificatifs.py} (91%) create mode 100644 tests/unit/test_assiduites.py diff --git a/app/models/assiduites.py b/app/models/assiduites.py index aeb3b200a..cd930e608 100644 --- a/app/models/assiduites.py +++ b/app/models/assiduites.py @@ -67,11 +67,14 @@ class Assiduite(db.Model): """ # Vérification de non duplication des périodes assiduites: list[Assiduite] = etud.assiduites.all() + + date_debut = localize_datetime(date_debut) + date_fin = localize_datetime(date_fin) assiduites = [ ass for ass in assiduites if verif_interval( - (localize_datetime(date_debut), localize_datetime(date_fin)), + (date_debut, date_fin), (ass.date_debut, ass.date_fin), ) ] @@ -92,8 +95,8 @@ class Assiduite(db.Model): return 2 else: nouv_assiduite = Assiduite( - date_debut=date_debut.isoformat(), - date_fin=date_fin.isoformat(), + date_debut=date_debut, + date_fin=date_fin, etat=etat, etudiant=etud, ) diff --git a/app/scodoc/sco_assiduites.py b/app/scodoc/sco_assiduites.py index d1faf1844..d1c477d01 100644 --- a/app/scodoc/sco_assiduites.py +++ b/app/scodoc/sco_assiduites.py @@ -77,7 +77,7 @@ def filter_by_etat(assiduites: Assiduite, etat: str) -> Assiduite: Filtrage d'une collection d'assiduites en fonction de leur état """ etats: list[str] = list(etat.split(",")) - etats = [scu.ETATS_ASSIDUITE.get(e, "") for e in etats] + etats = [scu.ETATS_ASSIDUITE.get(e, -1) for e in etats] return assiduites.filter(Assiduite.etat.in_(etats)) diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index 46255a507..54de152bb 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -149,7 +149,9 @@ def is_iso_formated(date: str, convert=False) -> bool or datetime.datetime or No return None if convert else False -def localize_datetime(date: datetime.datetime) -> datetime.datetime: +def localize_datetime(date: datetime.datetime or str) -> datetime.datetime: + if type(date) == str: + date = is_iso_formated(date, convert=True) new_date: datetime.datetime = date if date.tzinfo == None: diff --git a/migrations/versions/7b762fcbf644_models_assiduites.py b/migrations/versions/530594458193_ajout_modeles_assiduites_justificatifs.py similarity index 91% rename from migrations/versions/7b762fcbf644_models_assiduites.py rename to migrations/versions/530594458193_ajout_modeles_assiduites_justificatifs.py index ba4172bc5..53a849f7a 100644 --- a/migrations/versions/7b762fcbf644_models_assiduites.py +++ b/migrations/versions/530594458193_ajout_modeles_assiduites_justificatifs.py @@ -1,8 +1,8 @@ -"""models assiduites +"""Ajout Modeles Assiduites Justificatifs -Revision ID: 7b762fcbf644 -Revises: 52f5f35c077f -Create Date: 2022-11-03 09:09:19.213260 +Revision ID: 530594458193 +Revises: f95656fdd3ef +Create Date: 2022-12-19 13:56:28.597632 """ from alembic import op @@ -10,8 +10,8 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = '7b762fcbf644' -down_revision = '52f5f35c077f' +revision = '530594458193' +down_revision = 'f95656fdd3ef' branch_labels = None depends_on = None diff --git a/tests/unit/test_assiduites.py b/tests/unit/test_assiduites.py new file mode 100644 index 000000000..1242b5276 --- /dev/null +++ b/tests/unit/test_assiduites.py @@ -0,0 +1,315 @@ +# -*- mode: python -*- +# -*- coding: utf-8 -*- + +""" +Tests unitaires vérifiant le bon fonctionnement du modèle Assiduité et de +ses fonctions liées + +Ecrit par HARTMANN Matthias (en s'inspirant de tests.unit.test_abs_count.py par Fares Amer ) +""" + +from tests.unit import sco_fake_gen + +from app.scodoc import sco_formsemestre +import app.scodoc.sco_assiduites as scass +from app.models import Assiduite, Identite, FormSemestre +import app.scodoc.sco_utils as scu + + +def test_general(test_client): + """ """ + + G = sco_fake_gen.ScoFake(verbose=False) + + # Création d'une formation (1) + + formation_id = G.create_formation() + ue_id = G.create_ue(formation_id=formation_id, acronyme="T1", titre="UE TEST 1") + matiere_id = G.create_matiere(ue_id=ue_id, titre="test matière") + module_id_1 = G.create_module( + matiere_id=matiere_id, code="Mo1", coefficient=1.0, titre="test module" + ) + module_id_2 = G.create_module( + matiere_id=matiere_id, code="Mo2", coefficient=1.0, titre="test module2" + ) + + # Création semestre (2) + + formsemestre_id_1 = G.create_formsemestre( + formation_id=formation_id, + semestre_id=1, + date_debut="01/09/2022", + date_fin="31/12/2022", + ) + formsemestre_id_2 = G.create_formsemestre( + formation_id=formation_id, + semestre_id=2, + date_debut="01/01/2023", + date_fin="31/07/2023", + ) + formsemestre_id_3 = G.create_formsemestre( + formation_id=formation_id, + semestre_id=3, + date_debut="01/01/2024", + date_fin="31/07/2024", + ) + + formsemestre_1 = sco_formsemestre.get_formsemestre(formsemestre_id_1) + formsemestre_2 = sco_formsemestre.get_formsemestre(formsemestre_id_2) + formsemestre_3 = sco_formsemestre.get_formsemestre(formsemestre_id_3) + + # Création des modulesimpls (4, 2 par semestre) + + moduleimpl_id_1_1 = G.create_moduleimpl( + module_id=module_id_1, + formsemestre_id=formsemestre_id_1, + ) + moduleimpl_id_1_2 = G.create_moduleimpl( + module_id=module_id_2, + formsemestre_id=formsemestre_id_1, + ) + + moduleimpl_id_2_1 = G.create_moduleimpl( + module_id=module_id_1, + formsemestre_id=formsemestre_id_2, + ) + moduleimpl_id_2_2 = G.create_moduleimpl( + module_id=module_id_2, + formsemestre_id=formsemestre_id_2, + ) + + moduleimpls = [ + moduleimpl_id_1_1, + moduleimpl_id_1_2, + moduleimpl_id_2_1, + moduleimpl_id_2_2, + ] + + # Création des étudiants (3) + + etuds_dict = [G.create_etud(code_nip=None, prenom=f"etud{i}") for i in range(3)] + + etuds = [] + for etud in etuds_dict: + G.inscrit_etudiant(formsemestre_id=formsemestre_id_1, etud=etud) + G.inscrit_etudiant(formsemestre_id=formsemestre_id_2, etud=etud) + + etuds.append(Identite.query.filter_by(id=etud["id"]).first()) + + assert None not in etuds, "Problème avec la conversion en Identite" + + ajouter_assiduites(etuds, moduleimpls=moduleimpls) + verifier_comptage_et_filtrage( + etuds, moduleimpls, (formsemestre_1, formsemestre_2, formsemestre_3) + ) + + +def ajouter_assiduites(etuds: list[Identite], moduleimpls: list[int]): + """ + Première partie: + - Ajoute 6 assiduités à chaque étudiant + - 2 présence (semestre 1 et 2) + - 2 retard (semestre 2) + - 2 absence (semestre 1) + - Vérifie la création des assiduités + """ + + for etud in etuds: + obj_assiduites = [ + { + "etat": scu.EtatAssiduite.PRESENT, + "deb": "2022-09-03T08:00+01:00", + "fin": "2022-09-03T10:00+01:00", + "moduleimpl_id": None, + }, + { + "etat": scu.EtatAssiduite.PRESENT, + "deb": "2023-01-03T08:00+01:00", + "fin": "2023-01-03T10:00+01:00", + "moduleimpl_id": moduleimpls[2], + }, + { + "etat": scu.EtatAssiduite.ABSENT, + "deb": "2022-09-03T10:00:01+01:00", + "fin": "2022-09-03T11:00+01:00", + "moduleimpl_id": moduleimpls[0], + }, + { + "etat": scu.EtatAssiduite.ABSENT, + "deb": "2022-09-03T14:00:00+01:00", + "fin": "2022-09-03T15:00+01:00", + "moduleimpl_id": moduleimpls[1], + }, + { + "etat": scu.EtatAssiduite.RETARD, + "deb": "2023-01-03T11:00:01+01:00", + "fin": "2023-01-03T12:00+01:00", + "moduleimpl_id": moduleimpls[3], + }, + { + "etat": scu.EtatAssiduite.RETARD, + "deb": "2023-01-04T11:00:01+01:00", + "fin": "2023-01-04T12:00+01:00", + "moduleimpl_id": moduleimpls[3], + }, + ] + + assiduites = [ + Assiduite.create_assiduite( + etud, ass["deb"], ass["fin"], ass["etat"], ass["moduleimpl_id"] + ) + for ass in obj_assiduites + ] + + # Vérification de la création des assiduités + assert [ + ass for ass in assiduites if type(ass) != Assiduite + ] == [], "La création des assiduités de base n'est pas OK" + + # Vérification de la gestion des erreurs + + test_assiduites = [ + { + "etat": scu.EtatAssiduite.RETARD, + "deb": "2023-01-04T11:00:01+01:00", + "fin": "2023-01-04T12:00+01:00", + "moduleimpl_id": moduleimpls[3], + }, + { + "etat": scu.EtatAssiduite.RETARD, + "deb": "2023-01-05T11:00:01+01:00", + "fin": "2023-01-05T12:00+01:00", + "moduleimpl_id": 1000, + }, + ] + + assiduites_crees = [ + Assiduite.create_assiduite( + etuds[0], ass["deb"], ass["fin"], ass["etat"], ass["moduleimpl_id"] + ) + for ass in test_assiduites + ] + + assert [ass for ass in assiduites_crees if type(ass) != Assiduite] == [ + 1, + 2, + ], "La vérification des erreurs ne fonctionne pas" + + +def verifier_comptage_et_filtrage( + etuds: list[Identite], moduleimpls: list[int], formsemestres: tuple[int] +): + """ + Deuxième partie: + - vérifier les valeurs du comptage (compte, heure, journée, demi-journée) + - vérifier le filtrage des assiduites (etat, debut, fin, module, formsemestre) + + """ + + etu1, etu2, etu3 = etuds + + mod11, mod12, mod21, mod22 = moduleimpls + + # Vérification du comptage classique + comptage = scass.get_assiduites_stats(etu1.assiduites) + + assert comptage["compte"] == 6, "la métrique 'Comptage' n'est pas bien calculée" + assert comptage["journee"] == 3, "la métrique 'Journée' n'est pas bien calculée" + assert comptage["demi"] == 4, "la métrique 'Demi-Journée' n'est pas bien calculée" + assert comptage["heure"] == 8, "la métrique 'Heure' n'est pas bien calculée" + + # Vérification du filtrage classique + + # Etat + assert ( + scass.filter_by_etat(etu2.assiduites, "present").count() == 2 + ), "Filtrage de l'état 'présent' mauvais" + assert ( + scass.filter_by_etat(etu2.assiduites, "retard").count() == 2 + ), "Filtrage de l'état 'retard' mauvais" + assert ( + scass.filter_by_etat(etu2.assiduites, "absent").count() == 2 + ), "Filtrage de l'état 'absent' mauvais" + assert ( + scass.filter_by_etat(etu2.assiduites, "absent,retard").count() == 4 + ), "Filtrage de l'état 'absent,retard' mauvais" + assert ( + scass.filter_by_etat(etu2.assiduites, "absent,retard,present").count() == 6 + ), "Filtrage de l'état 'absent,retard,present' mauvais" + assert ( + scass.filter_by_etat(etu2.assiduites, "autre").count() == 0 + ), "Filtrage de l'état 'autre' mauvais" + + # Module + assert ( + scass.filter_by_module_impl(etu3.assiduites, mod11).count() == 1 + ), "Filtrage par 'Moduleimpl' mauvais" + assert ( + scass.filter_by_module_impl(etu3.assiduites, mod12).count() == 1 + ), "Filtrage par 'Moduleimpl' mauvais" + assert ( + scass.filter_by_module_impl(etu3.assiduites, mod21).count() == 1 + ), "Filtrage par 'Moduleimpl' mauvais" + assert ( + scass.filter_by_module_impl(etu3.assiduites, mod22).count() == 2 + ), "Filtrage par 'Moduleimpl' mauvais" + assert ( + scass.filter_by_module_impl(etu3.assiduites, None).count() == 1 + ), "Filtrage par 'Moduleimpl' mauvais" + assert ( + scass.filter_by_module_impl(etu3.assiduites, 152).count() == 0 + ), "Filtrage par 'Moduleimpl' mauvais" + + # Formsemestre + formsemestres = [ + FormSemestre.query.filter_by(id=fms["id"]).first() for fms in formsemestres + ] + assert ( + scass.filter_by_formsemstre(etu1.assiduites, formsemestres[0]).count() == 3 + ), "Filtrage 'Formsemestre' mauvais" + assert ( + scass.filter_by_formsemstre(etu1.assiduites, formsemestres[1]).count() == 3 + ), "Filtrage 'Formsemestre' mauvais" + assert ( + scass.filter_by_formsemstre(etu1.assiduites, formsemestres[2]).count() == 0 + ), "Filtrage 'Formsemestre' mauvais" + + # Date début + date = scu.localize_datetime("2022-09-01T10:00+01:00") + assert ( + scass.filter_by_date(etu2.assiduites, date, sup=True).count() == 6 + ), "Filtrage 'Date début' mauvais" + date = scu.localize_datetime("2022-09-03T10:00:00+01:00") + assert ( + scass.filter_by_date(etu2.assiduites, date, sup=True).count() == 5 + ), "Filtrage 'Date début' mauvais" + date = scu.localize_datetime("2022-09-03T10:00:01+01:00") + assert ( + scass.filter_by_date(etu2.assiduites, date, sup=True).count() == 5 + ), "Filtrage 'Date début' mauvais" + date = scu.localize_datetime("2022-09-03T10:00:02+01:00") + assert ( + scass.filter_by_date(etu2.assiduites, date, sup=True).count() == 4 + ), "Filtrage 'Date début' mauvais" + + # Date fin + date = scu.localize_datetime("2022-09-01T10:00+01:00") + assert ( + scass.filter_by_date(etu2.assiduites, date, sup=False).count() == 0 + ), "Filtrage 'Date fin' mauvais" + date = scu.localize_datetime("2022-09-03T10:00:00+01:00") + assert ( + scass.filter_by_date(etu2.assiduites, date, sup=False).count() == 1 + ), "Filtrage 'Date fin' mauvais" + date = scu.localize_datetime("2022-09-03T10:00:01+01:00") + assert ( + scass.filter_by_date(etu2.assiduites, date, sup=False).count() == 1 + ), "Filtrage 'Date fin' mauvais" + date = scu.localize_datetime("2023-01-04T13:00:01+01:00") + assert ( + scass.filter_by_date(etu2.assiduites, date, sup=False).count() == 6 + ), "Filtrage 'Date fin' mauvais" + date = scu.localize_datetime("2023-01-03T11:00:01+01:00") + assert ( + scass.filter_by_date(etu2.assiduites, date, sup=False).count() == 4 + ), "Filtrage 'Date fin' mauvais"