ScoDoc-PE/tests/unit/test_pe.py

324 lines
11 KiB
Python

"""
Test calcul moyennes pour les poursuites d'études
"""
import numpy as np
import pytest
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:
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)
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)
# 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)
assert (
moy.has_notes() == resultat
), "Le test sur la présence de notes est incorrect"
# ******************************
# app.pe.moys.pe_moytag
# ******************************
class Test_pe_moytag:
@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 = pe_moytag.get_colonne_df(aggregat, tag, champ, cohorte, critere)
assert descr == attendu, "Nom de colonne incorrect"
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)
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(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)
def test_to_df(self):
"""Test le dataframe de synthèse"""
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)
synthese = moy_tag.to_df(
aggregat="S1", cohorte="groupe", 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}|groupe|{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"
# ******************************
# 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"