- 9 nouveaux fichiers de tests (persistance, translations, fiches, indices, IHH) - Enrichissement des tests existants (graph_utils, gitea, widgets, tickets) - 67→448 tests, tous passent Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
214 lines
7.6 KiB
Python
214 lines
7.6 KiB
Python
"""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") == ""
|