Picarones / tests /test_register_default_metrics.py
Claude
refactor(audit): Phase 3.1 + Phase 5 — code mort robustness + violations archi
1d1017e unverified
Raw
History Blame
3.79 kB
"""Phase 5.3 audit code-quality — ``picarones.register_default_metrics``
est exposée comme API publique testable, en remplacement du
side-effect import opaque qui était en tête de ``picarones/__init__.py``.
Avant la Phase 5.3, le ``__init__`` contenait :
.. code-block:: python
import picarones.evaluation.metrics as _trigger_metric_registration
Côté caller, l'enregistrement des ~37 métriques + ~25 agrégateurs
corpus-level était implicite — pas de point d'entrée nommé, pas de
test direct. Désormais :
- ``register_default_metrics()`` est exposée dans ``picarones.__all__``.
- L'auto-déclenchement en fin de ``__init__`` reste pour la
rétrocompat (``from picarones import register_metric`` doit
marcher hors-test sans setup explicite).
- L'opération est idempotente (appel multiple sans effet de bord
grâce au cache ``sys.modules``).
"""
from __future__ import annotations
def test_register_default_metrics_is_public_api() -> None:
"""La fonction est exportée dans ``picarones.__all__``."""
import picarones
assert "register_default_metrics" in picarones.__all__
assert callable(picarones.register_default_metrics)
def test_register_default_metrics_is_idempotent() -> None:
"""Plusieurs appels successifs n'ont pas d'effet de bord —
le module ``picarones.evaluation.metrics`` est cache par
``sys.modules`` après le premier import.
"""
import picarones
from picarones.evaluation.metric_registry import all_metrics
snapshot_before = len(all_metrics())
picarones.register_default_metrics()
picarones.register_default_metrics()
picarones.register_default_metrics()
snapshot_after = len(all_metrics())
assert snapshot_before == snapshot_after, (
f"register_default_metrics non idempotent : {snapshot_before} → "
f"{snapshot_after} métriques. Le cache sys.modules devrait "
f"empêcher tout doublon."
)
def test_auto_trigger_loads_evaluation_metrics_submodules() -> None:
"""Le simple ``import picarones`` doit charger les sous-modules
listés dans ``picarones/evaluation/metrics/__init__.py`` (ce qui
déclenche leurs ``@register_metric`` éventuels).
Limitation connue (drift pré-existant identifié par l'audit
code-quality, hors scope Phase 5.3) : tous les modules
``@register_metric`` ne sont pas dans le ``__init__``.
L'enregistrement complet des ~37 métriques passe par
``builtin_hooks`` et ``philological_hooks`` qui sont eux-mêmes
chargés à la demande par ``BenchmarkService``. Ce test vérifie
uniquement l'invariant minimal : les modules **explicitement**
listés sont bien chargés.
"""
import sys
import picarones # noqa: F401 — déclenche l'auto-import
# ``picarones.evaluation.metrics`` doit être chargé.
assert "picarones.evaluation.metrics" in sys.modules, (
"Le module ``picarones.evaluation.metrics`` n'est pas dans "
"``sys.modules`` après ``import picarones`` — "
"``register_default_metrics`` ne déclenche plus l'import."
)
# Et au moins un sous-module concret listé dans son __init__.
assert "picarones.evaluation.metrics.confusion" in sys.modules
def test_register_default_metrics_signature_takes_no_args() -> None:
"""Contrat d'API : appelable sans argument."""
import inspect
import picarones
sig = inspect.signature(picarones.register_default_metrics)
assert len(sig.parameters) == 0, (
f"register_default_metrics doit être sans argument, signature : "
f"{sig}"
)
assert sig.return_annotation in (None, type(None), "None"), (
f"register_default_metrics doit retourner ``None``, "
f"annotation actuelle : {sig.return_annotation}"
)