Code/tests/unit/test_isg.py
Stéphan Peccini 8e2556c2b0
test(unit): +381 tests unitaires — couverture 16%→35%
- 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>
2026-03-02 11:52:21 +01:00

286 lines
10 KiB
Python

"""Tests unitaires pour le module app.fiches.utils.dynamic.indice.isg.
Ces tests verifient les fonctions de traitement Markdown pour l'indice ISG :
- _synth_isg
- build_isg_sections
"""
import textwrap
from unittest.mock import patch
import pytest
from app.fiches.utils.dynamic.indice.isg import (
_synth_isg,
build_isg_sections,
)
# ──────────────────────────────────────────────
# Helpers
# ──────────────────────────────────────────────
def _yaml_pays_bloc(pays: list[dict]) -> str:
"""Construit un bloc YAML markdown avec des donnees de pays ISG."""
lignes = ["```yaml"]
for p in pays:
lignes.append(f"{p['id']}:")
lignes.append(f" pays: {p['pays']}")
lignes.append(f" wgi_ps: {p['wgi_ps']}")
lignes.append(f" fsi: {p['fsi']}")
lignes.append(f" ndgain: {p['ndgain']}")
lignes.append(f" isg: {p['isg']}")
lignes.append("```")
return "\n".join(lignes)
def _sample_pays(**overrides) -> dict:
"""Retourne un dictionnaire pays avec des valeurs par defaut."""
base = {
"id": "chine",
"pays": "Chine",
"wgi_ps": 35,
"fsi": 72,
"ndgain": 48,
"isg": 54,
}
base.update(overrides)
return base
def _make_isg_md(pays: list[dict], with_front_matter: bool = True,
indice_court: str = "ISG") -> str:
"""Construit un markdown complet pour ISG."""
parts = []
if with_front_matter:
parts.append(
f"---\nindice: Indice de Stabilit\u00e9 G\u00e9opolitique\n"
f"indice_court: {indice_court}\n---\n"
)
parts.append("# Indice de Stabilit\u00e9 G\u00e9opolitique (ISG)\n")
parts.append("Introduction de la fiche.\n")
parts.append("# Criticit\u00e9 par pays\n")
parts.append(_yaml_pays_bloc(pays))
parts.append("\n## Tableau de synth\u00e8se\n")
parts.append("<!---- AUTO-BEGIN:TABLEAU-FINAL -->\nancien tableau\n<!---- AUTO-END:TABLEAU-FINAL -->")
return "\n".join(parts)
@pytest.fixture(autouse=True)
def _mock_pastille():
"""Mock la fonction pastille pour retourner une valeur previsible."""
with patch(
"app.fiches.utils.dynamic.indice.isg.pastille",
side_effect=lambda indice, valeur: f"[{indice}:{valeur}]",
):
yield
# ──────────────────────────────────────────────
# _synth_isg
# ──────────────────────────────────────────────
class TestSynthIsg:
"""Tests pour la generation du tableau de synthese ISG."""
def test_un_pays(self):
"""Test la synthese avec un seul pays."""
pays = [_sample_pays()]
md = _yaml_pays_bloc(pays)
result = _synth_isg(md)
assert "| Pays | WGI | FSI | NDGAIN | ISG |" in result
assert "| :-- | :-- | :-- | :-- | :-- |" in result
assert "Chine" in result
assert "54" in result
def test_plusieurs_pays_tries_alpha(self):
"""Test que les pays sont tries alphabetiquement par nom."""
pays = [
_sample_pays(id="chine", pays="Chine", isg=54),
_sample_pays(id="australie", pays="Australie", isg=25),
_sample_pays(id="rdc", pays="RDC", isg=82),
]
md = _yaml_pays_bloc(pays)
result = _synth_isg(md)
idx_australie = result.find("Australie")
idx_chine = result.find("Chine")
idx_rdc = result.find("RDC")
assert idx_australie < idx_chine < idx_rdc
def test_toutes_colonnes_presentes(self):
"""Test que toutes les colonnes de donnees sont presentes."""
pays = [_sample_pays(wgi_ps=35, fsi=72, ndgain=48, isg=54)]
md = _yaml_pays_bloc(pays)
result = _synth_isg(md)
assert "35" in result
assert "72" in result
assert "48" in result
assert "54" in result
def test_pas_de_bloc_yaml(self):
"""Test avec un texte sans bloc yaml retourne un message par defaut."""
result = _synth_isg("Texte sans donnees YAML.")
assert "aucune donnee de pays trouvee" in result.lower() or "aucune donn" in result
def test_texte_vide(self):
"""Test avec un texte vide."""
result = _synth_isg("")
assert "aucune donn" in result
def test_nombre_lignes(self):
"""Test que le nombre de lignes correspond aux donnees."""
pays = [
_sample_pays(id="a", pays="Alpha", isg=10),
_sample_pays(id="b", pays="Beta", isg=20),
_sample_pays(id="c", pays="Gamma", isg=30),
]
md = _yaml_pays_bloc(pays)
result = _synth_isg(md)
lignes = result.strip().split("\n")
# 2 en-tetes + 3 donnees = 5
assert len(lignes) == 5
def test_pastille_incluse(self):
"""Test que la pastille est incluse dans la colonne ISG."""
pays = [_sample_pays(isg=25)]
md = _yaml_pays_bloc(pays)
result = _synth_isg(md)
# La pastille mockee retourne [ISG:valeur] avant la valeur
assert "[ISG:25]" in result
assert "25" in result
# ──────────────────────────────────────────────
# build_isg_sections
# ──────────────────────────────────────────────
class TestBuildIsgSections:
"""Tests pour la fonction principale de construction des sections dynamiques ISG."""
def test_remplacement_tableau_final(self):
"""Test que le tableau final est remplace entre les marqueurs."""
pays = [_sample_pays()]
md = _make_isg_md(pays)
result = build_isg_sections(md)
assert "<!---- AUTO-BEGIN:TABLEAU-FINAL -->" in result
assert "<!---- AUTO-END:TABLEAU-FINAL -->" in result
assert "ancien tableau" not in result
def test_tableau_synthese_genere(self):
"""Test que le tableau de synthese est genere correctement."""
pays = [_sample_pays()]
md = _make_isg_md(pays)
result = build_isg_sections(md)
assert "| Pays | WGI | FSI | NDGAIN | ISG |" in result
assert "Chine" in result
def test_bloc_yaml_pays_supprime(self):
"""Test que le bloc YAML des pays est supprime de la section Criticite."""
pays = [_sample_pays()]
md = _make_isg_md(pays)
result = build_isg_sections(md)
assert "# Criticit\u00e9 par pays" in result
# Le bloc YAML doit etre supprime
assert "```yaml" not in result
def test_front_matter_isg_valide(self):
"""Test que la fiche est traitee quand indice_court est ISG."""
pays = [_sample_pays()]
md = _make_isg_md(pays, indice_court="ISG")
result = build_isg_sections(md)
# La fiche doit etre traitee
assert "| Pays | WGI | FSI | NDGAIN | ISG |" in result
def test_front_matter_non_isg_retourne_original(self):
"""Test que la fiche n'est pas traitee si indice_court != ISG."""
pays = [_sample_pays()]
md = _make_isg_md(pays, indice_court="ICS")
result = build_isg_sections(md)
# Le markdown original doit etre retourne sans modification
assert "ancien tableau" in result
def test_sans_front_matter(self):
"""Test le traitement sans front-matter YAML."""
pays = [_sample_pays()]
md = _make_isg_md(pays, with_front_matter=False)
result = build_isg_sections(md)
# Sans front-matter, la fiche est quand meme traitee (pas de filtre)
assert "| Pays | WGI | FSI | NDGAIN | ISG |" in result
def test_plusieurs_pays(self):
"""Test avec plusieurs pays dans le bloc YAML."""
pays = [
_sample_pays(id="australie", pays="Australie", wgi_ps=85, fsi=28, ndgain=72, isg=25),
_sample_pays(id="chine", pays="Chine", wgi_ps=35, fsi=72, ndgain=48, isg=54),
_sample_pays(id="rdc", pays="RDC", wgi_ps=15, fsi=102, ndgain=33, isg=82),
]
md = _make_isg_md(pays)
result = build_isg_sections(md)
assert "Australie" in result
assert "Chine" in result
assert "RDC" in result
def test_texte_sans_marqueurs(self):
"""Test avec un markdown sans marqueurs AUTO-BEGIN/END."""
md = textwrap.dedent("""\
---
indice_court: ISG
---
# ISG
# Criticit\u00e9 par pays
```yaml
fr:
pays: France
wgi_ps: 80
fsi: 30
ndgain: 65
isg: 28
```
## Tableau de synth\u00e8se
Pas de marqueurs ici.
""")
result = build_isg_sections(md)
# Sans marqueurs, le sub ne match pas, le tableau n'est pas remplace
assert isinstance(result, str)
def test_md_vide_avec_front_matter_isg(self):
"""Test avec un markdown minimal contenant seulement le front-matter ISG."""
md = "---\nindice_court: ISG\n---\n\nContenu minimal."
result = build_isg_sections(md)
# Pas de bloc YAML de pays, pas de marqueurs, retourne le texte en l'etat
assert "Contenu minimal." in result
def test_preservation_contenu_hors_sections(self):
"""Test que le contenu hors des sections dynamiques est preserve."""
pays = [_sample_pays()]
md = _make_isg_md(pays)
result = build_isg_sections(md)
assert "# Indice de Stabilit\u00e9 G\u00e9opolitique (ISG)" in result
assert "Introduction de la fiche." in result
def test_tri_alphabetique_dans_resultat(self):
"""Test que les pays sont tries alphabetiquement dans le resultat final."""
pays = [
_sample_pays(id="z", pays="Zambie", isg=60),
_sample_pays(id="a", pays="Albanie", isg=30),
]
md = _make_isg_md(pays)
result = build_isg_sections(md)
idx_albanie = result.find("Albanie")
idx_zambie = result.find("Zambie")
assert idx_albanie < idx_zambie