diff --git a/tests/unit/cursus_but_gb.yaml b/tests/unit/cursus_but_gb.yaml index ce969856eb..cb92040aed 100644 --- a/tests/unit/cursus_but_gb.yaml +++ b/tests/unit/cursus_but_gb.yaml @@ -140,8 +140,26 @@ Etudiants: "SAÉ 1.02": 9 # UE12 ratée "SAÉ 1.SEE.03": 18 # UE13 => sera capitalisée "SAÉ 1.SEE.04": 7 # UE14 ratée - deca: - codes_min: [ ] + attendu: # les codes jury que l'on doit vérifier + deca: + passage_de_droit: False + res_pair: None + codes: [ "RED", "..." ] + decisions_ues: + "UE 11": + codes: [ "AJ", "..." ] + moy_ue: 8. + explanation: "notes insuffisantes" + "UE 12": + codes: [ "AJ", "..." ] + moy_ue: 9 + "UE 1.3 SEE": + codes: [ "ADM", "..." ] + moy_ue: 18 + explanation: "Moyenne >= 10.0/20" + "UE 1.4 SEE": + codes: [ "AJ", "..." ] + S2_SEE: parcours: SEE notes_modules: # on joue avec les SAE seulement diff --git a/tests/unit/test_but_jury.py b/tests/unit/test_but_jury.py index e8dc867140..565f827f20 100644 --- a/tests/unit/test_but_jury.py +++ b/tests/unit/test_but_jury.py @@ -1,8 +1,8 @@ """ Test jury BUT avec parcours """ -import pytest -import yaml -from tests.unit import setup_test_yaml as sty + +from tests.unit import yaml_setup + import app from app.but.jury_but import DecisionsProposeesAnnee from app.models import ( @@ -17,36 +17,87 @@ from config import TestConfig DEPT = TestConfig.DEPT_TEST -def test_but_jury_S1(test_client): - """Test jurys BUT1 avec un seul parcours. - Vérifie aussi les champs de DecisionsProposeesAnnee +def test_but_jury_GB(test_client): + """Tests sur un cursus GB + - construction des semestres et de leurs étudianst à partir du yaml + - vérification jury de S1 + - vérification jury de S2 + - vérification jury de S3 + - vérification jury de S1 avec redoublants et capitalisations """ app.set_sco_dept(DEPT) - doc = sty.setup_from_yaml("tests/unit/cursus_but_gb.yaml") - formsemestre: FormSemestre = FormSemestre.query.filter_by(titre="S1_SEE").first() - etud: Identite = formsemestre.etuds.first() + # Construit la base de test GB une seule fois + # puis lance les tests de jury + doc = yaml_setup.setup_from_yaml("tests/unit/cursus_but_gb.yaml") + + # Vérifie les deca de tous les semestres: + for formsemestre in FormSemestre.query: + _check_deca(formsemestre) + + S1: FormSemestre = FormSemestre.query.filter_by(titre="S1_SEE").first() + _test_but_jury_S1(S1) + _test_but_jury_S2() + _test_but_jury_S3() + _test_but_jury_S1_redoublant() + + +def _check_deca(formsemestre: FormSemestre, etud: Identite = None): + """vérifie les champs principaux de l'instance de DecisionsProposeesAnnee""" + etud = etud or formsemestre.etuds.first() + assert etud # il faut au moins un étudiant dans le semestre deca = DecisionsProposeesAnnee(etud, formsemestre) assert deca.validation is None # pas encore de validation enregistrée assert False is deca.recorded assert deca.code_valide is None - assert deca.formsemestre_impair == formsemestre - assert deca.formsemestre_pair is None # jury de S1, pas de S2 - assert deca.rcues_annee == [] # S1, pas de RCUEs + if formsemestre.semestre_id % 2: + assert deca.formsemestre_impair == formsemestre + assert formsemestre.query_ues_parcours_etud(etud.id).all() == deca.ues_impair + else: + assert deca.formsemestre_pair == formsemestre + assert formsemestre.query_ues_parcours_etud(etud.id).all() == deca.ues_pair + if formsemestre.semestre_id == 1: + assert deca.formsemestre_pair is None # jury de S1, pas de S2 + assert deca.rcues_annee == [] # S1, pas de RCUEs assert deca.inscription_etat == scu.INSCRIT assert deca.inscription_etat_impair == scu.INSCRIT assert deca.parcour == formsemestre.parcours[0] # un seul parcours dans ce sem. - assert formsemestre.query_ues().all() == deca.ues_impair - nb_ues = formsemestre.query_ues().count() + + nb_ues = ( + len(deca.formsemestre_pair.query_ues_parcours_etud(etud.id).all()) + if deca.formsemestre_pair + else 0 + ) + nb_ues += ( + len(deca.formsemestre_impair.query_ues_parcours_etud(etud.id).all()) + if deca.formsemestre_impair + else 0 + ) assert len(deca.decisions_ues) == nb_ues - assert len(deca.niveaux_competences) == nb_ues - assert deca.nb_competences == nb_ues + + nb_ues_un_sem = ( + len(deca.formsemestre_impair.query_ues_parcours_etud(etud.id).all()) + if deca.formsemestre_impair + else len(deca.formsemestre_pair.query_ues_parcours_etud(etud.id).all()) + ) + assert len(deca.niveaux_competences) == nb_ues_un_sem + assert deca.nb_competences == nb_ues_un_sem + + +def _test_but_jury_S1(formsemestre: FormSemestre): + """Test jurys BUT1 avec un seul parcours. + Vérifie aussi les champs de DecisionsProposeesAnnee + """ + etud: Identite = formsemestre.etuds.first() + # XXX à compléter avec le jury quand on aura décidé des notes -def test_but_jury_S3(test_client): +def _test_but_jury_S2(): + pass + + +def _test_but_jury_S3(): """Test jurys BUT2/S3 avec 2 parcours dans le sem.""" - app.set_sco_dept(DEPT) - doc = sty.setup_from_yaml("tests/unit/cursus_but_gb.yaml") formsemestre: FormSemestre = FormSemestre.query.filter_by(titre="S3").first() etud: Identite = formsemestre.etuds.filter_by( prenom="Étudiant_SEE" @@ -54,3 +105,7 @@ def test_but_jury_S3(test_client): assert etud deca = DecisionsProposeesAnnee(etud, formsemestre) assert len(deca.niveaux_competences) == 5 # 5 compétences dans ce parcours + + +def _test_but_jury_S1_redoublant(): + pass diff --git a/tests/unit/setup_test_yaml.py b/tests/unit/yaml_setup.py similarity index 85% rename from tests/unit/setup_test_yaml.py rename to tests/unit/yaml_setup.py index 31435b4c86..99c84e8d68 100644 --- a/tests/unit/setup_test_yaml.py +++ b/tests/unit/yaml_setup.py @@ -15,6 +15,7 @@ from app import db from app.auth.models import User from app.but.import_refcomp import orebut_import_refcomp +from app.but.jury_but import DecisionsProposeesAnnee, DecisionsProposeesUE from app.models import ( ApcNiveau, ApcParcours, @@ -315,3 +316,52 @@ def setup_from_yaml(filename: str) -> dict: inscrit_les_etudiants(formation, doc) note_les_modules(doc) return doc + + +def _check_codes_jury(codes: list[str], codes_att: list[str]): + """Vérifie (assert) la liste des codes + l'ordre n'a pas d'importance ici. + Si codes_att contient un "...", on se contente de vérifie que + les codes de codes_att sont tous présents dans codes. + """ + codes_set = set(codes) + codes_att_set = set(codes_att) + if "..." in codes_att_set: + codes_att_set.remove("...") + assert codes_att_set.issubset(codes_set) + else: + assert codes_att_set == codes_set + + +def _check_decisions_ues( + decisions_ues: dict[int, DecisionsProposeesUE], decisions_ues_att: dict[str:dict] +): + """Vérifie les décisions d'UE""" + for acronyme, dec_ue_att in decisions_ues_att.items(): + # retrouve l'UE + ues_d = [ + dec_ue + for dec_ue in decisions_ues.values() + if dec_ue.ue.acronyme == acronyme + ] + assert len(ues_d) == 1 # une et une seule UE avec l'acronyme indiqué + dec_ue = ues_d[0] + if "codes" in dec_ue_att: + _check_codes_jury(dec_ue.codes, dec_ue_att["codes"]) + if "moy_ue" in dec_ue_att: + assert dec_ue_att["moy_ue"] == dec_ue.moy_ue + if "moy_ue_with_cap" in dec_ue_att: + assert dec_ue_att["moy_ue_with_cap"] == dec_ue.moy_ue_with_cap + if "explanation" in dec_ue_att: + assert dec_ue_att["explanation"] == dec_ue.explanation + + +def compare_decisions_annee(deca: DecisionsProposeesAnnee, deca_att: dict): + """Vérifie que les résultats de jury calculés sont ceux attendus. + deca est le résultat calculé par ScoDoc + deca_att est un dict lu du YAML + """ + if "codes" in deca_att: + _check_codes_jury(deca.codes, deca_att["codes"]) + if "decisions_ues" in deca_att: + _check_decisions_ues(deca.decisions_ues, deca_att["decisions_ues"])