Files
solduri2roa/tests/test_regresie.py
Marius Mutu 9a83e367d8 Muta datele din radacina in date/, iesiri/ si sablon/
date/    - intrari de la client (PDF-urile, exportul SAGA) si balanta intermediara
iesiri/  - xlsx-urile generate si verificare_<FIRMA>.md (ignorat de git)
sablon/  - sablonul ROA

Punctele de intrare scriu acolo implicit: extrage.py --dir=date, genereaza.py
citeste din date/ si scrie in iesiri/ (--dir-iesire), ca radacina sa nu se
murdareasca la fiecare rulare. Sablonul e cautat langa script, in sablon/.

Actualizate: TEMPLATE, cele trei teste care tin caile, .gitignore, CLAUDE.md si
handoff-ul. Poarta capat-la-capat incepuse sa sara tacut dupa mutarea PDF-urilor
(skipTest pe "lipsesc PDF-urile"); acum arata din nou catre date/ si ruleaza.
33 de teste trec, zero skip-uri.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYeAtVxeS8m4oXekjX8Am2
2026-09-21 16:42:25 +03:00

124 lines
4.4 KiB
Python

"""Poarta de regresie: codul de conversie de azi trebuie sa reproduca etalonul.
Ruleaza convertorul pe balantele CSV de pe disc (FUNDATIA, MASTER), scrie xlsx-urile
de initializare intr-un director temporar (nu peste cele din radacina), le
anonimizeaza cu ACELEASI reguli si ACEIASI tabela ca tests/anonimizeaza_etalon.py si
le compara cu tests/golden/ pe VALORI DE CELULA.
Comparatia nu se face niciodata pe hash de fisier: un xlsx rescris de alta versiune
de openpyxl are alti octeti cu acelasi continut.
Rulare: py -m unittest discover -s tests -v
"""
import os
import pathlib
import sys
import tempfile
import unittest
import openpyxl
RADACINA = pathlib.Path(__file__).resolve().parent.parent
TESTS = pathlib.Path(__file__).resolve().parent
for cale in (str(RADACINA), str(TESTS)):
if cale not in sys.path:
sys.path.insert(0, cale)
import genereaza_xlsx as generator
import anonimizeaza_etalon as anonim
CORESP = TESTS / "_corespondenta_anonimizare.json"
GOLDEN = TESTS / "golden"
FIRME = [
("FUNDATIA", "balanta_FUNDATIA.csv", "golden_FUNDATIA_2025_12.xlsx"),
("MASTER", "balanta_MASTERJOB.csv", "golden_MASTER_2025_12.xlsx"),
]
MAX_DIFERENTE_RAPORTATE = 20
class TestRegresieEtalon(unittest.TestCase):
@classmethod
def setUpClass(cls):
if not CORESP.exists():
raise unittest.SkipTest(
"Lipseste %s (e ignorata de git). Etalonul nu se poate reproduce "
"fara tabela de corespondenta - vezi docs/handoff_etapa2_convertor.md, "
"sectiunea despre etalon." % CORESP
)
cls.coresp = anonim.citeste_corespondenta(CORESP)
cls._cwd = os.getcwd()
os.chdir(str(RADACINA)) # TEMPLATE si CSV-urile sunt relative la radacina
cls._tmp = tempfile.TemporaryDirectory(prefix="regresie_")
tmpdir = pathlib.Path(cls._tmp.name)
cls.iesiri = {}
try:
header = generator.citeste_header()
for firma, csv_nume, golden_nume in FIRME:
rows = generator.citeste_balanta(str(RADACINA / "date" / csv_nume))
out, _, _, _, _ = generator.genereaza(rows, header)
brut = tmpdir / ("init_%s_2025_12.xlsx" % firma)
generator.scrie_xlsx(header, out, str(brut))
anonimizat = tmpdir / ("anon_%s.xlsx" % firma)
anonim.anonimizeaza_fisier(str(brut), str(anonimizat), cls.coresp)
cls.iesiri[firma] = (anonimizat, GOLDEN / golden_nume)
except Exception:
os.chdir(cls._cwd)
cls._tmp.cleanup()
raise
@classmethod
def tearDownClass(cls):
os.chdir(cls._cwd)
cls._tmp.cleanup()
def _verifica(self, firma):
anonimizat, golden = self.iesiri[firma]
self.assertTrue(golden.exists(), "lipseste etalonul %s" % golden)
wb_gasit = openpyxl.load_workbook(anonimizat)
wb_asteptat = openpyxl.load_workbook(golden)
ws_gasit, ws_asteptat = wb_gasit.active, wb_asteptat.active
nr_g = ws_gasit.max_row
nc_g = ws_gasit.max_column
nr_a = ws_asteptat.max_row
nc_a = ws_asteptat.max_column
self.assertEqual(
(nr_g, nc_g), (nr_a, nc_a),
"Dimensiuni diferite pentru %s: asteptat %d randuri x %d coloane, "
"gasit %d randuri x %d coloane" % (golden.name, nr_a, nc_a, nr_g, nc_g),
)
diferente = []
for rand in range(1, max(nr_g, nr_a) + 1):
for col in range(1, max(nc_g, nc_a) + 1):
gasit = ws_gasit.cell(rand, col).value
asteptat = ws_asteptat.cell(rand, col).value
if gasit != asteptat:
diferente.append((rand, col, asteptat, gasit))
if diferente:
linii = ["%d celule difera fata de %s:" % (len(diferente), golden.name)]
for rand, col, asteptat, gasit in diferente[:MAX_DIFERENTE_RAPORTATE]:
linii.append(
" %s: rand %d, coloana %d: asteptat %r, gasit %r"
% (golden.name, rand, col, asteptat, gasit)
)
if len(diferente) > MAX_DIFERENTE_RAPORTATE:
linii.append(" ... si alte %d celule"
% (len(diferente) - MAX_DIFERENTE_RAPORTATE))
self.fail("\n".join(linii))
def test_fundatia(self):
self._verifica("FUNDATIA")
def test_master(self):
self._verifica("MASTER")
if __name__ == "__main__":
unittest.main()