83 lines
2.7 KiB
Python
83 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import date
|
|
|
|
import pytest
|
|
|
|
from app.jobs import update_market as job
|
|
from app.services.fx_rates import FxRatesUpdateResult
|
|
from app.services.market_data import MarketDataUpdateResult
|
|
|
|
|
|
@pytest.fixture
|
|
def calls(monkeypatch) -> dict:
|
|
"""Подменяет сервисы: запоминает аргументы, отдаёт заданный результат."""
|
|
state: dict = {
|
|
"market": MarketDataUpdateResult(on_date=date(2026, 10, 8), updated=1),
|
|
"fx": FxRatesUpdateResult(date_to=date(2026, 10, 8), saved=1),
|
|
"market_args": None,
|
|
"fx_args": None,
|
|
}
|
|
|
|
async def _market_update(on_date, user): # noqa: ANN001
|
|
state["market_args"] = (on_date, user)
|
|
if isinstance(state["market"], Exception):
|
|
raise state["market"]
|
|
return state["market"]
|
|
|
|
async def _fx_update(up_to, user): # noqa: ANN001
|
|
state["fx_args"] = (up_to, user)
|
|
return state["fx"]
|
|
|
|
monkeypatch.setattr(job.market_data, "update", _market_update)
|
|
monkeypatch.setattr(job.fx_rates, "update", _fx_update)
|
|
return state
|
|
|
|
|
|
def test_explicit_date_runs_both_updates_as_system(calls: dict) -> None:
|
|
code = job.main(["--date", "2026-10-08"])
|
|
|
|
assert code == 0
|
|
assert calls["market_args"] == (date(2026, 10, 8), "system")
|
|
assert calls["fx_args"] == (date(2026, 10, 8), "system")
|
|
|
|
|
|
def test_default_date_is_previous_business_day(calls: dict, monkeypatch) -> None:
|
|
monkeypatch.setattr(job, "previous_business_day", lambda: date(2026, 10, 9))
|
|
|
|
assert job.main([]) == 0
|
|
assert calls["market_args"][0] == date(2026, 10, 9)
|
|
|
|
|
|
def test_no_trades_is_not_an_error(calls: dict) -> None:
|
|
calls["market"] = MarketDataUpdateResult(on_date=date(2026, 10, 8), no_trades=2)
|
|
|
|
assert job.main(["--date", "2026-10-08"]) == 0
|
|
|
|
|
|
def test_security_errors_give_nonzero_exit(calls: dict) -> None:
|
|
calls["market"] = MarketDataUpdateResult(on_date=date(2026, 10, 8), errors=1)
|
|
|
|
assert job.main(["--date", "2026-10-08"]) == 1
|
|
|
|
|
|
def test_fx_error_gives_nonzero_exit(calls: dict) -> None:
|
|
calls["fx"] = FxRatesUpdateResult(date_to=date(2026, 10, 8), error="ЦБ недоступен")
|
|
|
|
assert job.main(["--date", "2026-10-08"]) == 1
|
|
|
|
|
|
def test_crash_in_quotes_still_updates_fx_and_fails(calls: dict) -> None:
|
|
calls["market"] = RuntimeError("БД недоступна")
|
|
|
|
assert job.main(["--date", "2026-10-08"]) == 1
|
|
assert calls["fx_args"] is not None
|
|
|
|
|
|
def test_bad_date_argument_exits_with_2(calls: dict) -> None:
|
|
with pytest.raises(SystemExit) as exc_info:
|
|
job.main(["--date", "08.10.2026"])
|
|
|
|
assert exc_info.value.code == 2
|
|
assert calls["market_args"] is None
|