"""Tests unitaires pour le module pastille. Ces tests verifient la fonction pastille() qui renvoie une icone en fonction de la valeur d'un indicateur par rapport aux seuils definis. """ from unittest.mock import MagicMock, patch import pytest # -- Donnees de test partagees ------------------------------------------------ SEUILS_EXEMPLE = { "criticite": { "vert": {"max": 30}, "rouge": {"min": 70}, }, "confort": { "vert": {"max": 10}, "rouge": {"min": 50}, }, } # -- Fixture commune pour le mock Streamlit ----------------------------------- @pytest.fixture(autouse=True) def _mock_streamlit(): """Remplace le module streamlit par un mock dans sys.modules. Le mock expose session_state.get() qui renvoie SEUILS_EXEMPLE par defaut. """ mock_st = MagicMock() mock_st.session_state.get.return_value = SEUILS_EXEMPLE with patch.dict("sys.modules", {"streamlit": mock_st}): yield mock_st # -- Import apres le mock (au niveau fonction) -------------------------------- def _import_pastille(): """Importe la fonction pastille en contexte de mock.""" from app.fiches.utils.dynamic.utils.pastille import pastille return pastille def _import_icons(): """Importe le dictionnaire PASTILLE_ICONS.""" from app.fiches.utils.dynamic.utils.pastille import PASTILLE_ICONS return PASTILLE_ICONS # ============================================================================= # Tests # ============================================================================= class TestPastilleIcons: """Verifie que le dictionnaire PASTILLE_ICONS contient les bonnes icones.""" def test_contient_trois_couleurs(self): """Verifie la presence des trois couleurs (vert, orange, rouge).""" icons = _import_icons() assert set(icons.keys()) == {"vert", "orange", "rouge"} def test_icones_non_vides(self): """Verifie que chaque icone est une chaine non vide.""" icons = _import_icons() for couleur, icone in icons.items(): assert icone, f"L'icone pour '{couleur}' ne doit pas etre vide" class TestPastilleVert: """Verifie que les valeurs sous le seuil vert renvoient l'icone verte.""" def test_valeur_zero(self): """Verifie que la valeur 0 renvoie l'icone verte.""" pastille = _import_pastille() assert pastille("criticite", "0") == "\u2705" def test_valeur_sous_seuil_vert(self): """Verifie qu'une valeur sous le seuil vert renvoie l'icone verte.""" pastille = _import_pastille() assert pastille("criticite", "10") == "\u2705" def test_valeur_juste_sous_seuil_vert(self): """Verifie qu'une valeur juste sous vert_max renvoie l'icone verte.""" pastille = _import_pastille() assert pastille("criticite", "29.9") == "\u2705" def test_valeur_negative(self): """Verifie qu'une valeur negative renvoie l'icone verte.""" pastille = _import_pastille() assert pastille("criticite", "-5") == "\u2705" class TestPastilleRouge: """Verifie que les valeurs au-dessus du seuil rouge renvoient l'icone rouge.""" def test_valeur_au_dessus_seuil_rouge(self): """Verifie qu'une valeur bien au-dessus du seuil rouge renvoie le rouge.""" pastille = _import_pastille() assert pastille("criticite", "80") == "\U0001f534" def test_valeur_juste_au_dessus_seuil_rouge(self): """Verifie qu'une valeur juste au-dessus de rouge_min renvoie le rouge.""" pastille = _import_pastille() assert pastille("criticite", "70.1") == "\U0001f534" def test_valeur_tres_elevee(self): """Verifie qu'une valeur tres elevee renvoie l'icone rouge.""" pastille = _import_pastille() assert pastille("criticite", "999") == "\U0001f534" class TestPastilleOrange: """Verifie que les valeurs entre vert et rouge renvoient l'icone orange.""" def test_valeur_exacte_seuil_vert(self): """Quand val == vert_max, val n'est PAS < vert_max donc orange.""" pastille = _import_pastille() assert pastille("criticite", "30") == "\U0001f536" def test_valeur_entre_seuils(self): """Verifie qu'une valeur entre les deux seuils renvoie l'icone orange.""" pastille = _import_pastille() assert pastille("criticite", "50") == "\U0001f536" def test_valeur_exacte_seuil_rouge(self): """Quand val == rouge_min, val n'est PAS > rouge_min donc orange.""" pastille = _import_pastille() assert pastille("criticite", "70") == "\U0001f536" class TestPastilleAutreIndice: """Verifie le fonctionnement avec un indice different (confort).""" def test_vert_confort(self): """Verifie la pastille verte pour l'indice confort.""" pastille = _import_pastille() assert pastille("confort", "5") == "\u2705" def test_orange_confort(self): """Verifie la pastille orange pour l'indice confort.""" pastille = _import_pastille() assert pastille("confort", "25") == "\U0001f536" def test_rouge_confort(self): """Verifie la pastille rouge pour l'indice confort.""" pastille = _import_pastille() assert pastille("confort", "60") == "\U0001f534" class TestPastilleIndiceInconnu: """Verifie que la fonction renvoie '' pour un indice non defini dans les seuils.""" def test_indice_absent(self): """Verifie que la fonction renvoie '' pour un indice inexistant.""" pastille = _import_pastille() assert pastille("indice_inexistant", "10") == "" class TestPastilleErreurs: """Verifie que les erreurs sont gerees silencieusement (retour '').""" def test_valeur_non_numerique(self): """Une valeur non convertible en float declenche ValueError.""" pastille = _import_pastille() assert pastille("criticite", "abc") == "" def test_valeur_none(self): """None comme valeur declenche TypeError lors de float(None).""" pastille = _import_pastille() assert pastille("criticite", None) == "" def test_valeur_vide(self): """Chaine vide declenche ValueError lors de float('').""" pastille = _import_pastille() assert pastille("criticite", "") == "" class TestPastilleSansSeuilsEnSession: """Verifie le comportement quand session_state ne contient pas de seuils.""" def test_seuils_vides(self, _mock_streamlit): """Seuils = {} : la ligne seuils[indice] leve KeyError -> retour ''.""" _mock_streamlit.session_state.get.return_value = {} pastille = _import_pastille() assert pastille("criticite", "10") == "" def test_seuils_none(self, _mock_streamlit): """Seuils = None : le test 'indice not in seuils' leve TypeError -> retour ''.""" _mock_streamlit.session_state.get.return_value = None pastille = _import_pastille() assert pastille("criticite", "10") == "" def test_seuil_incomplet_sans_vert(self, _mock_streamlit): """Un seuil sans la cle 'vert' leve KeyError -> retour ''.""" _mock_streamlit.session_state.get.return_value = { "criticite": {"rouge": {"min": 70}} } pastille = _import_pastille() assert pastille("criticite", "10") == "" def test_seuil_incomplet_sans_rouge(self, _mock_streamlit): """Un seuil sans la cle 'rouge' leve KeyError -> retour ''.""" _mock_streamlit.session_state.get.return_value = { "criticite": {"vert": {"max": 30}} } pastille = _import_pastille() # rouge_min est lu avant le test val < vert_max, donc KeyError -> '' assert pastille("criticite", "10") == "" assert pastille("criticite", "50") == ""