def test_to_float() -> None: ## Vanilla: with pytest.raises(TypeError): Money.NA.as_float() assert Money.of(usd, half, today).as_float() == 0.5 assert type(Money.of(usd, half, today).as_float()) == float ## With overload: with pytest.raises(TypeError): float(Money.NA) assert float(Money.of(usd, half, today)) == 0.5 assert type(float(Money.of(usd, half, today))) == float
def test_to_integer() -> None: ## Vanilla: with pytest.raises(TypeError): int(Money.NA) assert int(Money.of(usd, half, today)) == 0 assert type(int(Money.of(usd, half, today))) == int ## With overload: with pytest.raises(TypeError): Money.NA.as_integer() assert Money.of(usd, half, today).as_integer() == 0 assert type(Money.of(usd, half, today).as_integer()) == int
def test_implementation() -> None: ## Define instances: _money = Money() # type: ignore smoney = SomeMoney(usd, one, today) nmoney = NoneMoney() ## Check structure: assert _money.__slots__ == () assert smoney.__slots__ == () assert nmoney.__slots__ == () assert not hasattr(_money, "__dict__") assert not hasattr(smoney, "__dict__") assert not hasattr(nmoney, "__dict__") ## Check types assert isinstance(Money.NA, Money) assert isinstance(Money.NA, NoneMoney) assert not isinstance(Money.NA, SomeMoney) assert not isinstance(Money.NA, Price) assert isinstance(_money, Money) assert not isinstance(_money, SomeMoney) assert not isinstance(_money, NoneMoney) assert isinstance(smoney, Money) assert isinstance(smoney, SomeMoney) assert not isinstance(smoney, NoneMoney) assert isinstance(nmoney, Money) assert not isinstance(nmoney, SomeMoney) assert isinstance(nmoney, NoneMoney)
def test_of() -> None: assert Money.of(usd, one, None) == Money.NA assert Money.of(usd, None, today) == Money.NA assert Money.of(usd, one, None) == Money.NA assert Money.of(usd, one, today) == SomeMoney(usd, one, today) assert Money.of(usd, Decimal("0.055"), today) == Money.of(usd, Decimal("0.06"), today) assert Money.of(usd, Decimal("0.045"), today) == Money.of(usd, Decimal("0.04"), today)
def test_with() -> None: ## First use `Money.NA`s: assert Money.NA.with_ccy(usd) == Money.NA assert Money.NA.with_qty(one) == Money.NA assert Money.NA.with_dov(today) == Money.NA ## Now with some: assert Money.of(usd, zero, today).with_ccy(eur) == Money.of(eur, zero, today) assert Money.of(usd, zero, today).with_qty(one) == Money.of(usd, one, today) assert Money.of(usd, zero, today).with_dov(yesterday) == Money.of( usd, zero, yesterday) ## Extras: assert Money.of(usd, zero, today).with_qty(Decimal("0.005")) == Money.of( usd, zero, today) assert Money.of(usd, zero, today).with_qty(Decimal("0.054")) == Money.of( usd, Decimal("0.05"), today)
def test_monetary_multiplication() -> None: ## First use `Price.NA`s: assert Price.NA.times(1) == Money.NA ## Vanilla multiplication: assert Price.of(usd, one, today).times(1) == Money.of(usd, one, today) assert Price.of(usd, one, today).times(2) == Money.of(usd, two, today) assert Price.of(usd, -one, today).times(1) == Money.of(usd, -one, today) assert Price.of(usd, -one, today).times(2) == Money.of(usd, -two, today) ## Other types: assert Price.of(usd, one, today).times(1) == Money.of(usd, one, today) assert Price.of(usd, one, today).times(1.0) == Money.of(usd, one, today) assert Price.of(usd, one, today).times(one) == Money.of(usd, one, today)
def test_to_boolean() -> None: ## Vanilla: assert not Money.NA.as_boolean() assert not Money.of(usd, zero, today).as_boolean() assert Money.of(usd, half, today).as_boolean() assert Money.of(usd, -half, today).as_boolean() ## With semantic overload assert not bool(Money.NA) assert not Money.of(usd, zero, today) assert Money.of(usd, half, today) assert Money.of(usd, -half, today)
def test_is_equal() -> None: ## Vanilla: assert Money.NA.is_equal(NoMoney) assert Money.NA.is_equal(NoneMoney()) assert not Money.NA.is_equal(Money.of(usd, zero, today)) assert Money.of(usd, zero, today).is_equal(Money.of(usd, zero, today)) assert Money.of(usd, half, today).is_equal(Money.of(usd, half, today)) assert not Money.of(usd, zero, today).is_equal(Money.of(eur, zero, today)) assert not Money.of(usd, zero, today).is_equal(Money.of(usd, half, today)) assert not Money.of(usd, zero, today).is_equal( Money.of(usd, zero, yesterday)) ## With operator overload: assert Money.NA == NoneMoney() assert Money.NA != Money.of(usd, zero, today) assert Money.of(usd, zero, today) == Money.of(usd, zero, today) assert Money.of(usd, half, today) == Money.of(usd, half, today) assert Money.of(usd, zero, today) != Money.of(eur, zero, today) assert Money.of(usd, zero, today) != Money.of(usd, half, today) assert Money.of(usd, zero, today) != Money.of(usd, zero, yesterday)
def test_subtraction() -> None: ## First use `Money.NA`s: assert Money.NA.subtract(Money.NA) == Money.NA assert Money.NA.subtract(Money.of(usd, zero, today)) == Money.of(usd, zero, today) assert Money.of(usd, zero, today).subtract(Money.NA) == Money.of(usd, zero, today) ## Vanilla subtraction: assert Money.of(usd, zero, today).subtract(Money.of(usd, zero, today)) == Money.of( usd, zero, today) assert Money.of(usd, zero, today).subtract(Money.of(usd, one, today)) == Money.of( usd, -one, today) assert Money.of(usd, one, today).subtract(Money.of(usd, one, today)) == Money.of( usd, zero, today) assert Money.of(usd, one, today).subtract(Money.of(usd, -one, today)) == Money.of( usd, two, today) ## Carry dates forward: assert Money.of(usd, zero, today).subtract(Money.of(usd, one, yesterday)) == Money.of( usd, -one, today) assert Money.of(usd, zero, yesterday).subtract(Money.of(usd, one, today)) == Money.of( usd, -one, today) ## Incompatible currency errors: with pytest.raises(IncompatibleCurrencyError): Money.of(usd, zero, today).subtract(Money.of(eur, zero, today)) ## Operator overload: assert Money.of(usd, zero, today) - Money.of(usd, one, today) == Money.of( usd, -one, today) assert Money.NA - Money.NA == Money.NA assert Money.NA - Money.of(usd, zero, today) == Money.of(usd, zero, today) assert Money.of(usd, zero, today) - Money.NA == Money.of(usd, zero, today)
def test_negative() -> None: ## Vanilla: assert Money.NA.negative() == Money.NA assert Money.of(usd, zero, today).negative() == Money.of(usd, zero, today) assert Money.of(usd, -one, today).negative() == Money.of(usd, +one, today) assert Money.of(usd, +one, today).negative() == Money.of(usd, -one, today) ## With overload: assert -Money.NA == Money.NA assert -Money.of(usd, zero, today) == Money.of(usd, zero, today) assert -Money.of(usd, -one, today) == Money.of(usd, +one, today) assert -Money.of(usd, +one, today) == Money.of(usd, -one, today)
def test_abs() -> None: ## Vanilla: assert Money.NA.abs() == Money.NA assert Money.of(usd, zero, today).abs() == Money.of(usd, zero, today) assert Money.of(usd, -one, today).abs() == Money.of(usd, +one, today) assert Money.of(usd, +one, today).abs() == Money.of(usd, +one, today) ## With overload: assert abs(Money.NA) == Money.NA assert abs(Money.of(usd, zero, today)) == Money.of(usd, zero, today) assert abs(Money.of(usd, -one, today)) == Money.of(usd, +one, today) assert abs(Money.of(usd, +one, today)) == Money.of(usd, +one, today)
def test_floor_division() -> None: ## First use `Money.NA`s: assert Money.NA.floor_divide(1) == Money.NA ## Vanilla subtraction: assert Money.of(usd, one, today).floor_divide(1) == Money.of(usd, one, today) assert Money.of(usd, one, today).floor_divide(2) == Money.of(usd, zero, today) assert Money.of(usd, -one, today).floor_divide(1) == Money.of(usd, -one, today) assert Money.of(usd, -one, today).floor_divide(2) == Money.of(usd, zero, today) ## Various divisor types: assert Money.of(usd, one, today).floor_divide(2) == Money.of(usd, zero, today) assert Money.of(usd, one, today).floor_divide(2.0) == Money.of(usd, zero, today) assert Money.of(usd, one, today).floor_divide(two) == Money.of(usd, zero, today) ## Division by zero: assert Money.of(usd, one, today).floor_divide(0) == Money.NA assert Money.of(usd, one, today).floor_divide(zero) == Money.NA assert Money.of(usd, one, today).floor_divide(0.0) == Money.NA ## Operator overload: assert Money.NA / 1 == Money.NA assert Money.of(usd, one, today) // 1 == Money.of(usd, one, today) assert Money.of(usd, one, today) // 2 == Money.of(usd, zero, today) assert Money.of(usd, -one, today) // 1 == Money.of(usd, -one, today) assert Money.of(usd, -one, today) // 2 == Money.of(usd, zero, today) assert Money.of(usd, -one, today) // 0 == Money.NA ## Extras assert Money.of(usd, Decimal("10"), today).floor_divide(Decimal("10")) == Money.of( usd, Decimal("1.00"), today) assert Money.of(usd, Decimal("10"), today).floor_divide(Decimal("11")) == Money.of( usd, Decimal("0.00"), today)
def test_comparisons() -> None: ## First use `Money.NA`s: assert not (Money.NA < Money.NA) assert Money.NA <= Money.NA assert not (Money.NA > Money.NA) assert Money.NA >= Money.NA ## Try mixed: assert Money.NA < Money.of(usd, -one, today) assert Money.NA <= Money.of(usd, -one, today) assert not (Money.NA > Money.of(usd, -one, today)) assert not (Money.NA >= Money.of(usd, -one, today)) ## ... and: assert not (Money.of(usd, -one, today) < Money.NA) assert not (Money.of(usd, -one, today) <= Money.NA) assert Money.of(usd, -one, today) > Money.NA assert Money.of(usd, -one, today) >= Money.NA ## With defined values: assert not (Money.of(usd, zero, today) < Money.of(usd, zero, today)) assert Money.of(usd, zero, today) <= Money.of(usd, zero, today) assert not (Money.of(usd, zero, today) > Money.of(usd, zero, today)) assert Money.of(usd, zero, today) >= Money.of(usd, zero, today) ## ... and: assert Money.of(usd, zero, today) < Money.of(usd, one, today) assert Money.of(usd, zero, today) <= Money.of(usd, one, today) assert not (Money.of(usd, zero, today) > Money.of(usd, one, today)) assert not (Money.of(usd, zero, today) >= Money.of(usd, one, today)) ## ... and: assert not (Money.of(usd, one, today) < Money.of(usd, zero, today)) assert not (Money.of(usd, one, today) <= Money.of(usd, zero, today)) assert Money.of(usd, one, today) > Money.of(usd, zero, today) assert Money.of(usd, one, today) >= Money.of(usd, zero, today)
def test_scalar_multiplication() -> None: ## First use `Money.NA`s: assert Money.NA.multiply(1) == Money.NA ## Vanilla subtraction: assert Money.of(usd, one, today).multiply(1) == Money.of(usd, one, today) assert Money.of(usd, one, today).multiply(2) == Money.of(usd, two, today) assert Money.of(usd, -one, today).multiply(1) == Money.of(usd, -one, today) assert Money.of(usd, -one, today).multiply(2) == Money.of(usd, -two, today) ## Other types: assert Money.of(usd, one, today).multiply(1) == Money.of(usd, one, today) assert Money.of(usd, one, today).multiply(1.0) == Money.of(usd, one, today) assert Money.of(usd, one, today).multiply(one) == Money.of(usd, one, today) ## Operator overload: assert Money.NA * 1 == Money.NA assert Money.of(usd, one, today) * 1 == Money.of(usd, one, today) assert Money.of(usd, one, today) * 2 == Money.of(usd, two, today) assert Money.of(usd, -one, today) * 1 == Money.of(usd, -one, today) assert Money.of(usd, -one, today) * 2 == Money.of(usd, -two, today) ## Extras assert Money.of(usd, one, today).multiply(Decimal("0.050")) == Money.of( usd, Decimal("0.05"), today) assert Money.of(usd, one, today).multiply(Decimal("0.005")) == Money.of( usd, Decimal("0.00"), today) assert Money.of(usd, one, today).multiply(Decimal("0.015")) == Money.of( usd, Decimal("0.02"), today)
def test_scalar_subtraction() -> None: ## First use `Money.NA`s: assert Money.NA.scalar_subtract(1) == Money.NA ## Vanilla subtraction: assert Money.of(usd, zero, today).scalar_subtract(1) == Money.of(usd, -one, today) assert Money.of(usd, zero, today).scalar_subtract(1.0) == Money.of(usd, -one, today) assert Money.of(usd, zero, today).scalar_subtract(one) == Money.of(usd, -one, today) assert Money.of(usd, zero, today).scalar_subtract(-1) == Money.of(usd, one, today) ## Operator overload: assert Money.of(usd, zero, today).scalar_subtract(1) == Money.of(usd, -one, today) assert Money.of(usd, zero, today).scalar_subtract(-1) == Money.of(usd, one, today) ## Extras: assert Money.of(usd, zero, today).scalar_subtract(0.5) == Money.of(usd, -half, today) assert Money.of(usd, zero, today).scalar_subtract( Decimal("0.05")) == -Money.of(usd, Decimal("0.05"), today) assert Money.of(usd, zero, today).scalar_subtract( Decimal("0.005")) == -Money.of(usd, Decimal("0"), today) assert Money.of(usd, zero, today).scalar_subtract( Decimal("0.015")) == -Money.of(usd, Decimal("0.02"), today)
def test_positive() -> None: ## Vanilla: assert Money.NA.positive() == Money.NA assert Money.of(usd, zero, today).positive() == Money.of(usd, zero, today) assert Money.of(usd, -one, today).positive() == Money.of(usd, -one, today) assert Money.of(usd, +one, today).positive() == Money.of(usd, +one, today) ## With overload: assert +Money.NA == Money.NA assert +Money.of(usd, zero, today) == Money.of(usd, zero, today) assert +Money.of(usd, -one, today) == Money.of(usd, -one, today) assert +Money.of(usd, +one, today) == Money.of(usd, +one, today)
def test_scalar_addition() -> None: ## First use `Money.NA`s: assert Money.NA.scalar_add(1) == Money.NA ## Vanilla addition: assert Money.of(usd, zero, today).scalar_add(1) == Money.of(usd, one, today) assert Money.of(usd, zero, today).scalar_add(1.0) == Money.of(usd, one, today) assert Money.of(usd, zero, today).scalar_add(one) == Money.of(usd, one, today) assert Money.of(usd, zero, today).scalar_add(-1) == Money.of(usd, -one, today) ## Extras: assert Money.of(usd, zero, today).scalar_add(0.5) == Money.of(usd, half, today) assert Money.of(usd, zero, today).scalar_add(Decimal("0.05")) == Money.of( usd, Decimal("0.05"), today) assert Money.of(usd, zero, today).scalar_add(Decimal("0.005")) == Money.of( usd, Decimal("0"), today) assert Money.of(usd, zero, today).scalar_add(Decimal("0.015")) == Money.of( usd, Decimal("0.02"), today)
def test_round() -> None: ## Vanilla: assert Money.NA.round(2) == Money.NA assert Money.of(usd, zero, today).round(2) == Money.of(usd, zero, today) assert Money.of(usd, -one, today).round(2) == Money.of(usd, -one, today) assert Money.of(usd, +one, today).round(2) == Money.of(usd, +one, today) ## Quick tests: assert Money.of(usd, Decimal("1.555"), today).round(2) == Money.of(usd, Decimal("1.56"), today) assert Money.of(usd, Decimal("1.545"), today).round(2) == Money.of(usd, Decimal("1.54"), today) ## With overload: assert round(Money.NA, 2) == Money.NA assert round(Money.of(usd, zero, today), 2) == Money.of(usd, zero, today) assert round(Money.of(usd, -one, today), 2) == Money.of(usd, -one, today) assert round(Money.of(usd, +one, today), 2) == Money.of(usd, +one, today) assert round(Money.of(usd, Decimal("1.555"), today), 2) == Money.of(usd, Decimal("1.56"), today) assert round(Money.of(usd, Decimal("1.545"), today), 2) == Money.of(usd, Decimal("1.54"), today) ## Extras: assert round(Money.of(usd, Decimal("0.545"), today), 0) == Money.of(usd, Decimal("1"), today) assert round(Money.of(usd, Decimal("1.545"), today), 0) == Money.of(usd, Decimal("2"), today) assert round(Money.of(usd, Decimal("0.545"), today), 1) == Money.of(usd, Decimal("0.5"), today) assert round(Money.of(usd, Decimal("1.545"), today), 1) == Money.of(usd, Decimal("1.5"), today) assert round(Money.of(usd, Decimal("0.45"), today), 1) == Money.of(usd, Decimal("0.4"), today) assert round(Money.of(usd, Decimal("1.45"), today), 1) == Money.of(usd, Decimal("1.4"), today) ## TODO: Following two are not really what round function signature says. mypy can't detect it! assert round(Money.of(usd, Decimal("1.4"), today)) == Money.of(usd, Decimal("1"), today) assert round(Money.of(usd, Decimal("1.5"), today)) == Money.of(usd, Decimal("2"), today)