tests and small refactors for exchange rates

This commit is contained in:
Pablo Martin 2024-06-11 23:47:07 +02:00
parent 4973d4c61a
commit 56c6bd7620
2 changed files with 218 additions and 2 deletions

View file

@ -0,0 +1,172 @@
import datetime
from decimal import Decimal
from money.currency import Currency
from money.money import Money
from xexe.exchange_rates import ExchangeRate, ExchangeRates, add_equal_rates
def test_exchange_rate_creation_works():
a_rate = ExchangeRate(
from_currency=Currency.USD,
to_currency=Currency.EUR,
rate=Decimal("1.2"),
rate_date=datetime.date.today(),
)
assert a_rate.from_currency.value == "USD"
assert a_rate.to_currency.value == "EUR"
assert a_rate.rate.amount == Decimal("1.2")
assert a_rate.rate_date == datetime.date.today()
def test_descriptor_builds_properly():
a_rate = ExchangeRate(
from_currency=Currency.USD,
to_currency=Currency.EUR,
rate=Decimal("1.2"),
rate_date=datetime.date(2020, 3, 10),
)
assert a_rate.descriptor == "USDEUR2020-03-10"
def test_exchange_rates_builds_index_properly():
a_rate = ExchangeRate(
from_currency=Currency.USD,
to_currency=Currency.EUR,
rate=Decimal("1.2"),
rate_date=datetime.date(2020, 3, 10),
)
another_rate = ExchangeRate(
from_currency=Currency.GBP,
to_currency=Currency.JPY,
rate=Decimal("10"),
rate_date=datetime.date(2019, 10, 3),
)
a_third_rate = ExchangeRate(
from_currency=Currency.NZD,
to_currency=Currency.PLN,
rate=Decimal("1.2"),
rate_date=datetime.date(2025, 1, 10),
)
rates = ExchangeRates({a_rate, another_rate, a_third_rate})
assert len(rates._rate_index) == 3
assert "USDEUR2020-03-10" in rates._rate_index
assert "GBPJPY2019-10-03" in rates._rate_index
assert "NZDPLN2025-01-10" in rates._rate_index
def test_present_currencies_works_fine():
a_rate = ExchangeRate(
from_currency=Currency.USD,
to_currency=Currency.EUR,
rate=Decimal("1.2"),
rate_date=datetime.date(2020, 3, 10),
)
another_rate = ExchangeRate(
from_currency=Currency.GBP,
to_currency=Currency.JPY,
rate=Decimal("10"),
rate_date=datetime.date(2019, 10, 3),
)
a_third_rate = ExchangeRate(
from_currency=Currency.NZD,
to_currency=Currency.PLN,
rate=Decimal("1.2"),
rate_date=datetime.date(2025, 1, 10),
)
rates = ExchangeRates({a_rate, another_rate, a_third_rate})
assert rates.present_currencies == {
Currency.USD,
Currency.EUR,
Currency.JPY,
Currency.GBP,
Currency.NZD,
Currency.PLN,
}
def test_present_dates_works_fine():
a_rate = ExchangeRate(
from_currency=Currency.USD,
to_currency=Currency.EUR,
rate=Decimal("1.2"),
rate_date=datetime.date(2020, 3, 10),
)
another_rate = ExchangeRate(
from_currency=Currency.GBP,
to_currency=Currency.JPY,
rate=Decimal("10"),
rate_date=datetime.date(2019, 10, 3),
)
a_third_rate = ExchangeRate(
from_currency=Currency.NZD,
to_currency=Currency.PLN,
rate=Decimal("1.2"),
rate_date=datetime.date(2025, 1, 10),
)
rates = ExchangeRates({a_rate, another_rate, a_third_rate})
assert rates.present_dates == {
datetime.date(2025, 1, 10),
datetime.date(2019, 10, 3),
datetime.date(2020, 3, 10),
}
def test_add_equal_rates_returns_expected_values():
a_rate = ExchangeRate(
from_currency=Currency.USD,
to_currency=Currency.EUR,
rate=Decimal("1.2"),
rate_date=datetime.date(2020, 3, 10),
)
another_rate = ExchangeRate(
from_currency=Currency.GBP,
to_currency=Currency.JPY,
rate=Decimal("10"),
rate_date=datetime.date(2019, 10, 3),
)
a_third_rate = ExchangeRate(
from_currency=Currency.NZD,
to_currency=Currency.PLN,
rate=Decimal("1.2"),
rate_date=datetime.date(2025, 1, 10),
)
rates = ExchangeRates({a_rate, another_rate, a_third_rate})
assert len(rates) == 3
rates = add_equal_rates(rates)
equal_rate_entry_count = len(list(rates.present_currencies)) * len(
rates.present_dates
)
assert len(rates) == equal_rate_entry_count + 3
assert (
len([rate for rate in rates if rate.from_currency == rate.to_currency])
== equal_rate_entry_count
)
for rate in rates:
if rate.from_currency == rate.to_currency:
assert rate.amount == Decimal(1)
def test_add_equal_rates_runs_on_empty_rates():
empty_rates = ExchangeRates()
empty_rates = add_equal_rates(empty_rates)
assert True

View file

@ -1,5 +1,7 @@
import datetime import datetime
from typing import Iterable, Union from decimal import Decimal
from numbers import Number
from typing import Iterable, Set, Union
from money.currency import Currency from money.currency import Currency
from money.money import Money from money.money import Money
@ -11,11 +13,13 @@ class ExchangeRate:
self, self,
from_currency: Currency, from_currency: Currency,
to_currency: Currency, to_currency: Currency,
rate: Money, rate: Union[Money, Number],
rate_date: datetime.date, rate_date: datetime.date,
) -> None: ) -> None:
self.from_currency = from_currency self.from_currency = from_currency
self.to_currency = to_currency self.to_currency = to_currency
if not isinstance(rate, Money):
rate = Money(rate, to_currency)
self.rate = rate self.rate = rate
self.rate_date = rate_date self.rate_date = rate_date
@ -27,6 +31,10 @@ class ExchangeRate:
+ str(self.rate_date.strftime("%Y-%m-%d")) + str(self.rate_date.strftime("%Y-%m-%d"))
) )
@property
def amount(self) -> Decimal:
return self.rate.amount
class ExchangeRates: class ExchangeRates:
@ -40,8 +48,44 @@ class ExchangeRates:
raise TypeError("ExchangeRates can only hold Rates.") raise TypeError("ExchangeRates can only hold Rates.")
self._rate_index[rate.descriptor] = rate self._rate_index[rate.descriptor] = rate
@property
def present_currencies(self) -> Set[Currency]:
present_currencies = set()
for rate in self:
present_currencies.add(rate.from_currency)
present_currencies.add(rate.to_currency)
return present_currencies
@property
def present_dates(self) -> Set[datetime.date]:
return {rate.rate_date for rate in self}
def add_rate(self, new_rate: ExchangeRate) -> None: def add_rate(self, new_rate: ExchangeRate) -> None:
self._rate_index[new_rate.descriptor] = new_rate self._rate_index[new_rate.descriptor] = new_rate
def __iter__(self): def __iter__(self):
return iter(self._rate_index.values()) return iter(self._rate_index.values())
def __len__(self):
return len(self._rate_index)
def add_equal_rates(rates: ExchangeRates) -> ExchangeRates:
present_currencies = rates.present_currencies
present_dates = rates.present_dates
for date in present_dates:
for currency in present_currencies:
rates.add_rate(
ExchangeRate(
from_currency=currency,
to_currency=currency,
rate=Money(1, currency),
rate_date=date,
)
)
return rates