Les parseurs sont la partie la plus exposée aux régressions silencieuses :
un décalage de colonne ne lève aucune exception, il produit des montants
faux. Rien ne les couvrait jusqu'ici.
Chaque PDF du corpus local produit une empreinte (structure des lots,
totaux par lot, montants par catégorie, détail de chaque opération)
comparée à une référence figée. Les libellés sensibles — locataire,
fournisseur, description — sont réduits à un hash court : un changement
reste détecté sans recopier la donnée.
Ni les PDF (`data/`) ni les références (`tests/golden/`) ne sont
versionnés : la suite se saute d'elle-même là où le corpus est absent.
Régénération après un changement volontaire de parseur :
uv run pytest tests/test_parsers_golden.py --regen-golden
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
96 lines
2.8 KiB
Python
96 lines
2.8 KiB
Python
"""Fixtures partagées pour les tests."""
|
|
|
|
import pytest
|
|
|
|
from plesna_gerance.database import connection
|
|
|
|
|
|
def pytest_addoption(parser):
|
|
"""Ajoute --regen-golden pour refiger les références des parseurs."""
|
|
parser.addoption(
|
|
"--regen-golden",
|
|
action="store_true",
|
|
default=False,
|
|
help="Réécrit les références de tests/golden au lieu de les comparer.",
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def regen_golden(request) -> bool:
|
|
"""Vrai quand la suite est lancée avec --regen-golden."""
|
|
return request.config.getoption("--regen-golden")
|
|
|
|
|
|
@pytest.fixture
|
|
def db_session(tmp_path, monkeypatch):
|
|
"""Session SQLAlchemy sur une base SQLite temporaire et isolée.
|
|
|
|
Configure aussi PLESNA_DB_PATH / PLESNA_STORAGE_PATH pour que les helpers
|
|
qui lisent l'environnement (sql_executor, storage) ciblent le temp dir.
|
|
"""
|
|
db_path = tmp_path / "test.sqlite"
|
|
monkeypatch.setenv("PLESNA_DB_PATH", str(db_path))
|
|
monkeypatch.setenv("PLESNA_STORAGE_PATH", str(tmp_path / "documents"))
|
|
|
|
connection.reset_connection()
|
|
connection.init_db(db_path)
|
|
|
|
SessionLocal = connection.get_session_factory()
|
|
session = SessionLocal()
|
|
try:
|
|
yield session
|
|
finally:
|
|
session.close()
|
|
connection.reset_connection()
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_data():
|
|
"""Données extraites minimales mais complètes pour save_document."""
|
|
return {
|
|
"metadata": {
|
|
"document": {
|
|
"reference": "REF001",
|
|
"date": "2024-01-15",
|
|
"type": "COMPTE RENDU DE GESTION",
|
|
},
|
|
"immeuble": {
|
|
"code": "IMM1",
|
|
"adresse": "4 RUE SERVIENT",
|
|
"ville": "LYON",
|
|
"code_postal": "69003",
|
|
},
|
|
"editeur": {"nom": "ORALIA", "siret": "12345678901234"},
|
|
"solde": {
|
|
"montant": 100.0,
|
|
"type": "crediteur",
|
|
"date_arrete": "2024-01-15",
|
|
},
|
|
},
|
|
"situation_locataires": [
|
|
{
|
|
"lot": {"numero": "01", "type": "Appartement"},
|
|
"locataire": {"nom": "DUPONT"},
|
|
"lignes": [
|
|
{
|
|
"type": "loyer",
|
|
"periode": {"debut": "2024-01-01", "fin": "2024-01-31"},
|
|
"loyers": 500.0,
|
|
"total": 500.0,
|
|
"regles": 500.0,
|
|
"impayes": 0.0,
|
|
}
|
|
],
|
|
}
|
|
],
|
|
"recapitulatif_operations": [
|
|
{
|
|
"categorie": "DEPENSES_LOCATIVES",
|
|
"sous_categorie": "Nettoyage",
|
|
"fournisseur": "ACME",
|
|
"description": "Nettoyage immeuble",
|
|
"montants": {"debit": 50.0},
|
|
}
|
|
],
|
|
}
|