352 lines
12 KiB
Python
352 lines
12 KiB
Python
"""
|
|
Test calcul moyennes pour les poursuites d'études
|
|
"""
|
|
import numpy as np
|
|
import pytest
|
|
|
|
import app.pe.moys.pe_moy
|
|
from tests.unit import setup
|
|
|
|
from app import db
|
|
import pandas as pd
|
|
import app.pe.moys.pe_moy as pe_moy
|
|
import app.pe.moys.pe_rcstag as pe_rcstag
|
|
import app.pe.moys.pe_tabletags as pe_tabletags
|
|
import app.pe.moys.pe_moytag as pe_moytag
|
|
|
|
|
|
def egalite_df(df1, df2):
|
|
return ((df1 == df2) | (np.isnan(df1) & np.isnan(df2))).all()
|
|
|
|
|
|
# ******************************
|
|
# app.pe.moys.pe_moy
|
|
# ******************************
|
|
|
|
|
|
class Test_pe_moy:
|
|
infos = {
|
|
"aggregat": "S1",
|
|
"tag": "maths",
|
|
"intitule": "UE1.1",
|
|
"cohorte": "groupe",
|
|
}
|
|
|
|
def test_init(self):
|
|
"""Test de pe_moy.Moyenne.__init__"""
|
|
notes = pd.Series({1: 10.0, 2: 14.0, 3: np.nan, 4: 0.0})
|
|
moy = pe_moy.Moyenne(notes, Test_pe_moy.infos)
|
|
assert moy.etudids == [1, 2, 3, 4], "Etudids incorrect"
|
|
assert moy.inscrits_ids == [1, 2, 4], "Inscriptions incorrectes"
|
|
# Les notes
|
|
notes_attendues = pd.Series([10.0, 14.0, np.nan, 0.0], index=[1, 2, 3, 4])
|
|
assert "note" in moy.df.columns, "Colonne manquante"
|
|
assert egalite_df(moy.df["note"], notes_attendues), "Notes incorrecte"
|
|
# Les étuds
|
|
nb_etuds = pd.Series([4] * 4, index=[1, 2, 3, 4])
|
|
assert "nb_etuds" in moy.df.columns, "Colonne manquante"
|
|
assert egalite_df(moy.df["nb_etuds"], nb_etuds)
|
|
# Les inscrits
|
|
nb_inscrits = pd.Series([3, 3, np.nan, 3], index=[1, 2, 3, 4])
|
|
assert "nb_inscrits" in moy.df.columns, "Colonne manquante"
|
|
assert egalite_df(moy.df["nb_inscrits"], nb_inscrits)
|
|
# Les classements
|
|
classement = pd.Series([2.0, 1.0, np.nan, 3.0], index=[1, 2, 3, 4])
|
|
assert "classement" in moy.df, "Colonne manquante"
|
|
assert egalite_df(moy.df["classement"], classement), "Classements incorrects"
|
|
# Les rangs
|
|
rang = pd.Series(["2/3", "1/3", "nan", "3/3"], index=[1, 2, 3, 4])
|
|
assert "rang" in moy.df, "Colonne manquante"
|
|
assert moy.df["rang"].isnull().sum() == 0, "Des Nan dans les rangs interdits"
|
|
assert (moy.df["rang"] == rang).any(), "Rangs incorrects"
|
|
# Les mins
|
|
assert "min" in moy.df, "Colonne manquante"
|
|
mina = pd.Series([0.0, 0.0, np.nan, 0.0], index=[1, 2, 3, 4])
|
|
assert egalite_df(moy.df["min"], mina), "Min incorrect"
|
|
# Les max
|
|
assert "max" in moy.df, "Colonne manquante"
|
|
maxa = pd.Series([14.0, 14.0, np.nan, 14.0], index=[1, 2, 3, 4])
|
|
assert egalite_df(moy.df["max"], maxa), "Max incorrect"
|
|
# Les moy
|
|
assert "moy" in moy.df, "Colonne manquante"
|
|
moya = pd.Series([8.0, 8.0, np.nan, 8.0], index=[1, 2, 3, 4])
|
|
assert egalite_df(moy.df["moy"], moya), "Moy incorrect"
|
|
|
|
def test_init_ex_aequo(self):
|
|
"""Test de pe_moy.Moyenne.__init__ pour des ex-aequo"""
|
|
notes = pd.Series({1: 10.0, 2: 14.0, 3: 10.0, 4: 0.0})
|
|
moy = pe_moy.Moyenne(notes, Test_pe_moy.infos)
|
|
# Les rangs
|
|
rang = pd.Series(["2 ex/4", "1/4", "2 ex/4", "3/4"], index=[1, 2, 3, 4])
|
|
assert moy.df["rang"].isnull().sum() == 0, "Des Nan dans les rangs interdits"
|
|
assert (moy.df["rang"] == rang).any(), "Rangs incorrects"
|
|
|
|
@pytest.mark.parametrize(
|
|
"notes, resultat",
|
|
[
|
|
pytest.param(
|
|
pd.Series({1: 10.0, 2: 14.0, 3: np.nan, 4: 0.0}), True, id="avec_notes"
|
|
),
|
|
pytest.param(pd.Series({1: np.nan, 2: np.nan}), False, id="sans_note"),
|
|
pytest.param(pd.Series({1: 0.0, 2: np.nan}), True, id="avec 0"),
|
|
],
|
|
)
|
|
def test_has_notes(self, notes, resultat):
|
|
moy = pe_moy.Moyenne(notes, Test_pe_moy.infos)
|
|
assert (
|
|
moy.has_notes() == resultat
|
|
), "Le test sur la présence de notes est incorrect"
|
|
|
|
@pytest.mark.parametrize(
|
|
"aggregat, tag, champ, cohorte, critere, attendu",
|
|
[
|
|
pytest.param(
|
|
"S1", "Math", "UE", "Gr", "note", "S1|Math|UE|Gr|note", id="tous_args"
|
|
),
|
|
pytest.param(
|
|
None,
|
|
"Math",
|
|
"UE",
|
|
"Gr",
|
|
"note",
|
|
"Math|UE|Gr|note",
|
|
id="aggregat manquant",
|
|
),
|
|
pytest.param(
|
|
None,
|
|
"Math",
|
|
"UE",
|
|
None,
|
|
"note",
|
|
"Math|UE|note",
|
|
id="aggregat et cohorte manquant",
|
|
),
|
|
],
|
|
)
|
|
def test_colonnes_df(self, aggregat, tag, champ, cohorte, critere, attendu):
|
|
descr = app.pe.moys.pe_moy.get_colonne_df(
|
|
aggregat, tag, champ, cohorte, critere
|
|
)
|
|
assert descr == attendu, "Nom de colonne incorrect"
|
|
|
|
def to_df(self):
|
|
notes = pd.Series({1: 10.0, 2: 14.0, 3: np.nan, 4: 0.0})
|
|
infos = {
|
|
"aggregat": "S1",
|
|
"tag": "maths",
|
|
"intitule": "Général",
|
|
"cohorte": "promo",
|
|
}
|
|
cols = [
|
|
f"S1|maths|Général|promo|{critere}"
|
|
for critere in ["note", "rang", "min", "max", "moy"]
|
|
]
|
|
moy = pe_moy.Moyenne(notes, infos)
|
|
df = moy.to_df(with_min_max_moy=True)
|
|
assert (
|
|
list(df.columns) == cols
|
|
), "Colonnes du df de synthèse pour Excel pas correctes"
|
|
|
|
|
|
# ******************************
|
|
# app.pe.moys.pe_moytag
|
|
# ******************************
|
|
class Test_pe_moytag:
|
|
infos = {"aggregat": "S1", "cohorte": "promo"}
|
|
|
|
def test_moyennes_tag__init__(self):
|
|
matrice_notes = pd.DataFrame.from_dict(
|
|
{
|
|
1: [12.0, 14.0, 15.0],
|
|
2: [8.0, np.nan, 12.0],
|
|
3: [0.0, 11.0, 13.0],
|
|
4: [np.nan, np.nan, np.nan],
|
|
5: [np.nan, np.nan, np.nan],
|
|
6: [0.0, 0.0, 0.0],
|
|
},
|
|
orient="index",
|
|
columns=["UE1.1", "UE1.2", "UE1.3"],
|
|
)
|
|
matrice_coeffs = pd.DataFrame.from_dict(
|
|
{
|
|
1: [1, 2, 3],
|
|
2: [2, 10, 6],
|
|
3: [1, 2, np.nan],
|
|
4: [5, 4, 3],
|
|
5: [np.nan, np.nan, np.nan],
|
|
6: [1, 1, 1],
|
|
},
|
|
orient="index",
|
|
columns=["UE1.1", "UE1.2", "UE1.3"],
|
|
)
|
|
moy_tag = pe_moytag.MoyennesTag(
|
|
"maths", None, matrice_notes, matrice_coeffs, Test_pe_moytag.infos
|
|
)
|
|
attendu = pd.Series(
|
|
[
|
|
(12 * 1 + 14 * 2 + 15 * 3) / (1 + 2 + 3),
|
|
(8 * 2 + 12 * 6) / (2 + 6),
|
|
(0 * 1 + 2 * 11) / (1 + 2),
|
|
np.nan,
|
|
np.nan,
|
|
0,
|
|
],
|
|
index=[1, 2, 3, 4, 5, 6],
|
|
)
|
|
assert egalite_df(moy_tag.notes_gen, attendu), "La moyenne n'est pas correcte"
|
|
|
|
def test_to_df_sans_renommage_colonne(self):
|
|
"""Test le dataframe de synthèse"""
|
|
infos = {"aggregat": "S1", "cohorte": "promo"}
|
|
matrice_notes = pd.DataFrame.from_dict(
|
|
{
|
|
2: [13.0, 13.0, 13],
|
|
1: [12.0, 14.0, 15.0],
|
|
},
|
|
orient="index",
|
|
columns=["UE1.1", "UE1.2", "UE1.3"],
|
|
)
|
|
matrice_coeffs = pd.DataFrame.from_dict(
|
|
{
|
|
2: [1, 2, 3],
|
|
1: [1, 2, 3],
|
|
},
|
|
orient="index",
|
|
columns=["UE1.1", "UE1.2", "UE1.3"],
|
|
)
|
|
moy_tag = pe_moytag.MoyennesTag(
|
|
"maths", None, matrice_notes, matrice_coeffs, infos
|
|
)
|
|
synthese = moy_tag.to_df(
|
|
aggregat="S1", cohorte="promo", options={"min_max_moy": True}
|
|
)
|
|
colonnes_attendues = []
|
|
for ue in ["UE1.1", "UE1.2", "UE1.3", "Général"]:
|
|
for champ in ["note", "rang", "min", "max", "moy"]:
|
|
colonnes_attendues += [f"S1|maths|{ue}|promo|{champ}"]
|
|
assert (
|
|
list(synthese.columns) == colonnes_attendues
|
|
), "Les colonnes de synthèse ne sont pas correctes"
|
|
assert list(synthese.index) == [
|
|
1,
|
|
2,
|
|
], "Les lignes ne sont pas triées par id d'étudiants"
|
|
|
|
@pytest.mark.parametrize(
|
|
"colonnes, ajouts, resultat",
|
|
[
|
|
pytest.param(["toto", "titi"], ["tutu"], None, id="pas de modif"),
|
|
pytest.param(["toto", "titi"], ["titi"], ["titi (1)"], id="ajout de (1)"),
|
|
pytest.param(
|
|
["toto", "toto (1)"], ["toto"], ["toto (2)"], id="ajout de (2)"
|
|
),
|
|
pytest.param(
|
|
["toto (1)", "titi (3)"],
|
|
["toto", "titi"],
|
|
["toto (4)", "titi (4)"],
|
|
id="ajout multiple",
|
|
),
|
|
],
|
|
)
|
|
def test_renomme_colonnes(self, colonnes, ajouts, resultat):
|
|
res = pe_moytag.ajout_numero_a_colonnes(colonnes, ajouts)
|
|
assert res == resultat, "L'ajout d'un numéro au colonne est incorrect"
|
|
|
|
|
|
# ******************************
|
|
# app.pe.moys.pe_rcstag
|
|
# ******************************
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"notes_S1, notes_S2, coeffs_S1, coeffs_S2, "
|
|
"coeffs_rcues_S1, coeffs_rcues_S2, inscr_S1, inscr_S2,"
|
|
"moyenne, coeffs_aggreges",
|
|
[
|
|
pytest.param(
|
|
[17.0, 15.0, 12.0],
|
|
[16.0, 14.0, 13.0], # notes
|
|
[1.0, 2.0, 3.0],
|
|
[4.0, 5.0, 6.0], # coeffs moy gen
|
|
[2.0, 4.0, 6.0],
|
|
[8.0, 10.0, 12.0], # coeffs recus
|
|
[1.0, 1.0, 1.0],
|
|
[1.0, 1.0, 1.0], # inscr
|
|
[
|
|
(17.0 * 2.0 + 16.0 * 8.0) / (2.0 + 8.0),
|
|
(15.0 * 4.0 + 14.0 * 10.0) / (4.0 + 10.0),
|
|
(12.0 * 6.0 + 13.0 * 12.0) / (6.0 + 12.0),
|
|
],
|
|
[1.0 + 4.0, 2.0 + 5.0, 3.0 + 6.0],
|
|
id="etudiant_parfait",
|
|
),
|
|
pytest.param(
|
|
[17.0, 15.0, 12.0],
|
|
[16.0, 14.0, 13.0], # notes
|
|
[1.0, 2.0, 3.0],
|
|
[4.0, 5.0, 6.0], # coeffs moy gen
|
|
[2.0, 4.0, 6.0],
|
|
[8.0, 10.0, 12.0], # coeffs recus
|
|
[np.nan, 1.0, np.nan],
|
|
[1.0, np.nan, np.nan], # inscr
|
|
[
|
|
(16.0 * 8.0) / (8.0),
|
|
(15.0 * 4.0) / (4.0),
|
|
np.nan,
|
|
],
|
|
[4.0, 2.0, np.nan],
|
|
id="etudiant_non_inscrit",
|
|
),
|
|
pytest.param(
|
|
[0.0, 15.0, 0.0],
|
|
[0.0, 0.0, 0.0], # notes
|
|
[1.0, 2.0, 3.0],
|
|
[4.0, 5.0, 6.0], # coeffs moy gen
|
|
[2.0, 4.0, 6.0],
|
|
[8.0, 10.0, 12.0], # coeffs recus
|
|
[np.nan, 1.0, 1.0],
|
|
[1.0, np.nan, 1.0], # inscr
|
|
[0.0, 15.0, 0.0],
|
|
[4.0, 2.0, 3.0 + 6.0],
|
|
id="etudiant_avec_0",
|
|
),
|
|
],
|
|
)
|
|
def test_compute_moyennes_par_RCS(
|
|
notes_S1,
|
|
notes_S2,
|
|
coeffs_S1,
|
|
coeffs_S2,
|
|
coeffs_rcues_S1,
|
|
coeffs_rcues_S2,
|
|
inscr_S1,
|
|
inscr_S2,
|
|
moyenne,
|
|
coeffs_aggreges,
|
|
):
|
|
"""Test de pe_rcstag.compute_moyennes_par_RCS"""
|
|
notes_cube = np.stack([np.array([notes_S1]), np.array([notes_S2])], axis=-1)
|
|
# Vérifie les dimensions
|
|
dim1, dim2, dim3 = notes_cube.shape
|
|
assert dim1 == 1, "La dim 0 doit être le nombre d'étudiants"
|
|
assert dim2 == 3, "La dim 1 doit être le nombre d'UEs/Compétences"
|
|
assert dim3 == 2, "La dim 2 doit être le nombre de semestres"
|
|
|
|
coeffs_cube = np.stack([np.array([coeffs_S1]), np.array([coeffs_S2])], axis=-1)
|
|
coeffs_rcue_cube = np.stack(
|
|
[np.array([coeffs_rcues_S1]), np.array([coeffs_rcues_S2])], axis=-1
|
|
)
|
|
inscr_cube = np.stack([np.array([inscr_S1]), np.array([inscr_S2])], axis=-1)
|
|
moys, coeffs = pe_rcstag.compute_moyennes_par_RCS(
|
|
notes_cube, coeffs_cube, coeffs_rcue_cube, inscr_cube
|
|
)
|
|
|
|
moy_resultat = np.array([moyenne])
|
|
assert (
|
|
(moys == moy_resultat) | (np.isnan(moys) & np.isnan(moy_resultat))
|
|
).all(), "Moyenne erronée"
|
|
coeffs_resultat = np.array([coeffs_aggreges])
|
|
assert (
|
|
(coeffs == coeffs_resultat) | (np.isnan(coeffs) & np.isnan(coeffs_resultat))
|
|
).all(), "Coeffs (pour moyenne générale sur toutes les UE) erronés"
|