Files
nifodea/tests/test_model.py
T
oqyude 3f7268d14c T4: Repository pattern — ModelRepository, JsonFileRepository, ExcelRepository
- application/repositories/model_repository.py: ModelRepository Protocol
  with load(path) and save(model, path)
- infrastructure/repositories/json_file_repository.py: JsonFileRepository
  (вынесен из FinancialModel.save/load)
- infrastructure/repositories/excel_repository.py: ExcelRepository
  (бывший ExcelSync, переименован)
- FinancialModel.save/load удалены — теперь только данные
- infrastructure/sync/ удалён (ExcelSync перенесён в repositories/)
- infrastructure/cli/main.py и config.py используют JsonFileRepository +
  ExcelRepository через локальные singletons
- test_excel_sync.py переименован в test для ExcelRepository
- Новый test_repositories.py: 5 тестов для JsonFileRepository + протокол
- test_model.py: использован JsonFileRepository

Tests: 68/68 pass (было 63 + 5 новых).
2026-10-08 16:50:06 +03:00

119 lines
4.0 KiB
Python

from decimal import Decimal
from pathlib import Path
from domain import (
Account,
Asset,
ExchangeRate,
FinancialModel,
ForecastScenario,
Liability,
RecurringCashflow,
Transaction,
)
from infrastructure.repositories import JsonFileRepository
_repo = JsonFileRepository()
class TestAccount:
def test_create(self):
a = Account(name="Test", balance=Decimal("100.0"))
assert a.name == "Test"
assert a.balance == Decimal("100.0")
assert a.currency == "USD"
def test_to_dict_roundtrip(self):
a = Account(name="Test", balance=Decimal("100.0"))
d = a.model_dump(mode="json")
a2 = Account.model_validate(d)
assert a2.name == a.name
assert a2.balance == a.balance
assert a2.currency == a.currency
class TestTransaction:
def test_create(self):
t = Transaction(amount=Decimal("500.0"), category="food")
assert t.amount == Decimal("500.0")
def test_roundtrip(self):
t = Transaction(amount=Decimal("-100.0"), category="rent", description="test")
d = t.model_dump(mode="json")
t2 = Transaction.model_validate(d)
assert t2.amount == t.amount
assert t2.category == t.category
assert t2.description == t.description
class TestFinancialModel:
def test_default_base_currency(self):
model = FinancialModel()
assert model.base_currency == "RUB"
def test_base_currency_roundtrip(self, tmp_path: Path):
model = FinancialModel(base_currency="EUR")
p = tmp_path / "model.json"
_repo.save(model, p)
loaded = _repo.load(p)
assert loaded.base_currency == "EUR"
def test_base_currency_backward_compat(self, tmp_path: Path):
import json
p = tmp_path / "legacy.json"
with open(p, "w") as f:
json.dump({"accounts": []}, f)
loaded = _repo.load(p)
assert loaded.base_currency == "RUB"
def test_exchange_rates_default(self):
model = FinancialModel()
assert len(model.exchange_rates) == 1
assert model.exchange_rates[0].from_currency == "USD"
assert model.exchange_rates[0].to_currency == "RUB"
assert model.exchange_rates[0].rate == Decimal("80")
def test_save_load(self, tmp_path: Path):
model = FinancialModel()
model.accounts.append(Account(name="Test", balance=Decimal("100")))
model.transactions.append(Transaction(amount=Decimal("50"), category="income"))
p = tmp_path / "model.json"
_repo.save(model, p)
assert p.exists()
loaded = _repo.load(p)
assert len(loaded.accounts) == 1
assert len(loaded.transactions) == 1
assert loaded.accounts[0].name == "Test"
def test_empty_model(self):
model = FinancialModel()
d = model.to_dict()
assert d["accounts"] == []
assert d["transactions"] == []
assert d["base_currency"] == "RUB"
assert "exchange_rates" in d
def test_all_entities_roundtrip(self, tmp_path: Path):
model = FinancialModel(
accounts=[Account(name="A"), Account(name="B")],
transactions=[Transaction(amount=Decimal("100"))],
recurring=[RecurringCashflow(amount=Decimal("50"))],
assets=[Asset(name="Stock", value=Decimal("1000"))],
liabilities=[Liability(name="Loan", balance=Decimal("500"), interest=Decimal("5"), payment=Decimal("100"))],
scenarios=[ForecastScenario(name="test")],
exchange_rates=[ExchangeRate(from_currency="USD", to_currency="RUB", rate=Decimal("80"))],
)
p = tmp_path / "full.json"
_repo.save(model, p)
loaded = _repo.load(p)
assert len(loaded.accounts) == 2
assert len(loaded.transactions) == 1
assert len(loaded.recurring) == 1
assert len(loaded.assets) == 1
assert len(loaded.liabilities) == 1
assert len(loaded.scenarios) == 1
assert len(loaded.exchange_rates) == 1