Files
nifodea/tests/test_cli.py
T
oqyude b6b64a9878 T6: Decompose CLI — main.py → 9 command files, config.py → config_cmd.py
Split infrastructure/cli/:
- main.py (330 LOC) → 9 files in infrastructure/cli/commands/:
  * init.py, forecast.py, scenario.py, whatif.py, compare.py
  * import_xlsx.py, export_xlsx.py, analyze.py, info.py
- config.py (428 LOC) → commands/config_cmd.py (15 sub-commands)
- main.py → app.py (entry point: registers all commands)
- New: paths.py (MODEL_PATH, DATA_DIR)
- New: services.py (composition root + helpers: load_model, save_model,
  build_services, resolve_currency, convert_value, fmt_amount)
- cli/__init__.py (empty) удалён

Each command module: <100 LOC.
pyproject.toml: cf = infrastructure.cli.app:app
tests/test_cli.py: import обновлён на infrastructure.cli.app

CLI behavior идентично, все команды работают.
Tests: 67/67 pass.
2026-10-08 16:56:49 +03:00

170 lines
5.3 KiB
Python

from typer.testing import CliRunner
from infrastructure.cli.app import app
from infrastructure.cli.paths import MODEL_PATH
runner = CliRunner()
def _cleanup():
if MODEL_PATH.exists():
MODEL_PATH.unlink()
class TestCli:
def test_init(self):
_cleanup()
result = runner.invoke(app, ["init"])
assert result.exit_code == 0
assert "Пустая модель" in result.stdout
def test_forecast_after_init(self):
_cleanup()
runner.invoke(app, ["init"])
result = runner.invoke(app, ["forecast", "--months", "3"])
assert result.exit_code == 0
def test_forecast_with_currency(self):
_cleanup()
runner.invoke(app, ["init"])
result = runner.invoke(app, ["forecast", "--months", "3", "--currency", "USD"])
assert result.exit_code == 0
assert "$" in result.stdout
def test_unknown_scenario(self):
result = runner.invoke(app, ["scenario", "unknown"])
assert result.exit_code != 0
def test_help(self):
result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
def test_info_empty(self):
_cleanup()
runner.invoke(app, ["init"])
result = runner.invoke(app, ["info"])
assert result.exit_code == 0
assert "Базовая валюта" in result.stdout
def test_config_base_currency_set(self):
_cleanup()
runner.invoke(app, ["init"])
result = runner.invoke(app, ["config", "base-currency", "EUR"])
assert result.exit_code == 0
assert "EUR" in result.stdout
info = runner.invoke(app, ["info"])
assert "EUR" in info.stdout
def test_config_base_currency_show(self):
_cleanup()
runner.invoke(app, ["init"])
result = runner.invoke(app, ["config", "base-currency"])
assert result.exit_code == 0
assert "RUB" in result.stdout
def test_config_account_crud(self):
_cleanup()
runner.invoke(app, ["init"])
args = ["config", "account-add", "--name", "Тестовый", "--balance", "1000"]
add = runner.invoke(app, args)
assert add.exit_code == 0
assert "Тестовый" in add.stdout
lst = runner.invoke(app, ["config", "account-list"])
assert "Тестовый" in lst.stdout
remove = runner.invoke(app, ["config", "account-remove", "Тестовый"])
assert remove.exit_code == 0
lst2 = runner.invoke(app, ["config", "account-list"])
assert "Тестовый" not in lst2.stdout
def test_config_transaction_crud(self):
_cleanup()
runner.invoke(app, ["init"])
runner.invoke(app, ["config", "account-add", "--name", "Счёт", "--balance", "0"])
add = runner.invoke(app, [
"config", "transaction-add",
"--account", "Счёт",
"--amount", "5000",
"--category", "income",
"--description", "Зарплата",
])
assert add.exit_code == 0
assert "доход" in add.stdout
lst = runner.invoke(app, ["config", "transaction-list"])
assert "Зарплата" in lst.stdout
def test_config_asset_crud(self):
_cleanup()
runner.invoke(app, ["init"])
add = runner.invoke(app, [
"config", "asset-add",
"--name", "Квартира",
"--value", "5000000",
"--growth", "5",
])
assert add.exit_code == 0
assert "Квартира" in add.stdout
lst = runner.invoke(app, ["config", "asset-list"])
assert "Квартира" in lst.stdout
def test_config_liability_crud(self):
_cleanup()
runner.invoke(app, ["init"])
add = runner.invoke(app, [
"config", "liability-add",
"--name", "Кредит",
"--balance", "100000",
"--interest", "10",
"--payment", "5000",
])
assert add.exit_code == 0
assert "Кредит" in add.stdout
def test_config_recurring_crud(self):
_cleanup()
runner.invoke(app, ["init"])
add = runner.invoke(app, [
"config", "recurring-add",
"--amount", "-500",
"--category", "аренда",
"--frequency", "monthly",
])
assert add.exit_code == 0
lst = runner.invoke(app, ["config", "recurring-list"])
assert "аренда" in lst.stdout
def test_config_rate_crud(self):
_cleanup()
runner.invoke(app, ["init"])
set_r = runner.invoke(app, ["config", "rate-set", "EUR", "RUB", "90"])
assert set_r.exit_code == 0
lst = runner.invoke(app, ["config", "rate-list"])
assert "EUR" in lst.stdout
assert "90" in lst.stdout
def test_info_with_data(self):
_cleanup()
runner.invoke(app, ["init"])
acc_args = ["config", "account-add", "--name", "Основной", "--balance", "50000"]
runner.invoke(app, acc_args)
asset_args = ["config", "asset-add", "--name", "Акции",
"--value", "100000", "--growth", "8.0"]
runner.invoke(app, asset_args)
result = runner.invoke(app, ["info"])
assert "Основной" in result.stdout
assert "Акции" in result.stdout