tests and small refactors for exchange rates
This commit is contained in:
parent
4973d4c61a
commit
56c6bd7620
2 changed files with 218 additions and 2 deletions
172
tests/tests_unit/test_exchange_rates.py
Normal file
172
tests/tests_unit/test_exchange_rates.py
Normal 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
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue