"""Unit-тесты services/metrics.py — чистая логика, без БД.""" from decimal import Decimal import pytest from services.metrics import ( check_arithmetic, normalize_date, _to_decimal, ClassifyMetrics, ) class TestNormalizeDate: def test_dd_mm_yyyy(self): assert normalize_date("01.01.2025") == "2025-01-01" def test_already_iso(self): assert normalize_date("2025-01-01") == "2025-01-01" def test_empty(self): assert normalize_date("") is None assert normalize_date(None) is None def test_unrecognized_passthrough(self): assert normalize_date("01 января 2025") == "01 января 2025" class TestToDecimal: def test_int(self): assert _to_decimal("50000") == Decimal("50000") def test_russian_number(self): assert _to_decimal("50 000,00") == Decimal("50000.00") def test_nbsp(self): assert _to_decimal("1\u00a0000,50") == Decimal("1000.50") def test_none(self): assert _to_decimal(None) is None assert _to_decimal("") is None def test_garbage(self): assert _to_decimal("не число") is None class TestCheckArithmetic: def test_ok(self): ops = [{"action": "ADD", "new_row": {"name": "x", "price": 100, "qty": 2, "sum": 200}}] assert check_arithmetic(ops) == [] def test_mismatch(self): ops = [{"action": "ADD", "new_row": {"name": "x", "price": 100, "qty": 2, "sum": 250}}] m = check_arithmetic(ops) assert len(m) == 1 assert m[0]["expected_sum"] == 200.0 assert m[0]["actual_sum"] == 250.0 assert m[0]["diff"] == 50.0 def test_update_values(self): ops = [{"action": "UPDATE", "new_values": {"price": 10, "qty": 3, "sum": 30}}] assert check_arithmetic(ops) == [] def test_skip_incomplete(self): # нет qty → пропуск ops = [{"action": "ADD", "new_row": {"name": "x", "price": 100, "sum": 200}}] assert check_arithmetic(ops) == [] def test_skip_non_add_update(self): ops = [{"action": "DELETE", "target_hash": "h"}] assert check_arithmetic(ops) == [] class TestClassifyMetrics: def test_fix_rate(self): m = ClassifyMetrics() m.record(False) m.record(True) m.record(False) assert m.total == 3 assert m.fixes == 1 assert m.fix_rate == pytest.approx(1 / 3) def test_empty(self): m = ClassifyMetrics() assert m.fix_rate == 0.0 assert m.summary()["total_classifications"] == 0