- test_models.py: 10 tests for Room/Horse/Bet/RaceResult dataclasses - test_payout_logic.py: 12 tests for payout formula (max+round) - test_room_store_lock.py: 5 tests for get_lock() setdefault pattern - All 34 tests pass in 0.27s
59 lines
1.8 KiB
Python
59 lines
1.8 KiB
Python
"""Test payout calculation logic - pure function tests per verify_sop.
|
|
|
|
Tests the formula: payout = max(1, round(amount * odds))
|
|
These are pure logic tests with no mocking needed.
|
|
"""
|
|
import pytest
|
|
|
|
|
|
def payout(amount: int, odds: float) -> int:
|
|
"""Extracted payout formula from points_service.py:56"""
|
|
return max(1, round(amount * odds))
|
|
|
|
|
|
class TestPayoutCalculation:
|
|
"""Core payout formula: max(1, round(amount * odds))"""
|
|
|
|
def test_basic_payout(self):
|
|
assert payout(100, 2.0) == 200
|
|
|
|
def test_fractional_odds(self):
|
|
assert payout(100, 1.5) == 150
|
|
|
|
def test_small_amount_rounds_up(self):
|
|
# 10 * 0.06 = 0.6 → round = 1
|
|
assert payout(10, 0.06) == 1
|
|
|
|
def test_small_amount_rounds_down_still_1(self):
|
|
# 1 * 0.4 = 0.4 → round = 0 → max(1, 0) = 1
|
|
assert payout(1, 0.4) == 1
|
|
|
|
def test_zero_odds_gives_minimum_1(self):
|
|
"""Even with 0 odds, payout is at least 1"""
|
|
assert payout(1000, 0.0) == 1
|
|
|
|
def test_zero_amount_gives_minimum_1(self):
|
|
"""Even with 0 amount, payout is at least 1"""
|
|
assert payout(0, 5.0) == 1
|
|
|
|
def test_both_zero_gives_1(self):
|
|
assert payout(0, 0.0) == 1
|
|
|
|
def test_high_odds(self):
|
|
assert payout(10, 100.0) == 1000
|
|
|
|
def test_large_amount(self):
|
|
assert payout(100000, 1.5) == 150000
|
|
|
|
def test_negative_odds_boundary(self):
|
|
"""If negative odds somehow pass through, result is max(1, negative)"""
|
|
assert payout(100, -1.0) == 1
|
|
|
|
def test_round_half_even(self):
|
|
# Python bankers rounding: round(0.5) = 0, so max(1, 0) = 1
|
|
assert payout(1, 0.5) == 1
|
|
|
|
def test_round_1_5(self):
|
|
# round(1*1.5) = round(1.5) = 2
|
|
assert payout(1, 1.5) == 2
|