def test_hand_must_have_two_cards(): available_cards = [Card("H", "2"), Card("H", "3"), Card("H", "4")] for i in [0, 1, 3]: with pytest.raises(ValueError) as exception: simulator.probability_of_winning(available_cards[:i], 3, [ Card("H", "T"), Card("H", "A"), Card("D", "5"), Card("C", "J"), Card("C", "9") ]) assert "hand" in str(exception)
def test_table_must_have_the_right_number_of_cards(): available_cards = [ Card("H", "T"), Card("H", "A"), Card("D", "5"), Card("C", "J"), Card("C", "9"), Card("D", "T") ] for i in [1, 2, 6]: with pytest.raises(ValueError) as exception: simulator.probability_of_winning( [Card("H", "2"), Card("H", "3")], 3, available_cards[:i]) assert "table" in str(exception)
def test_best_five_card_subhand(): best_subhand_cards = [Card("C", "J"), Card("C", "T"), Card("C", "9"), Card("C", "8"), Card("C", "7")] seven_cards = best_subhand_cards + [Card("H", "8"), Card("D", "A")] # in case order matters somehow random.shuffle(seven_cards) assert set(SevenCardHand(seven_cards).best_five_card_subhand().cards) == set(best_subhand_cards)
def test_must_have_between_one_and_twentythree_opponents(): for i in [0, 24]: with pytest.raises(ValueError) as exception: simulator.probability_of_winning( [Card("H", "2"), Card("H", "3")], i, [ Card("H", "T"), Card("H", "A"), Card("D", "5"), Card("C", "J"), Card("C", "9") ]) assert "opponents" in str(exception)
def test_hand_scoring(): raw_hands_in_winning_order = [ ["CJ", "CT", "C9", "C8", "C7"], # Straight flush ["C5", "D5", "H5", "S5", "D2"], # Four of a kind ["S6", "H6", "D6", "CK", "HK"], # Full house ["DJ", "D9", "D8", "D7", "D6"], # Flush ["DT", "S9", "H8", "D7", "C6"], # Straight ["CQ", "SQ", "HQ", "H7", "S6"], # Three of a kind ["HJ", "SJ", "C3", "S3", "H2"], # Two pair ["ST", "HT", "S8", "H7", "C4"], # One pair ["DK", "DQ", "S7", "S4", "H3"] # High card ] hands_in_winning_order = [FiveCardHand([Card(raw_card[0], raw_card[1]) for raw_card in rh]) for rh in raw_hands_in_winning_order] hand_scores_in_winning_order = [hand.score() for hand in hands_in_winning_order] assert all(higher_score < lower_score for higher_score, lower_score in zip(hands_in_winning_order, hand_scores_in_winning_order[:1]))
def test_low_straight(): weaker_hand = FiveCardHand([Card("H", "A"), Card("C", "A"), Card("S", "4"), Card("C", "5"), Card("H", "6")]) stronger_hand = FiveCardHand([Card("H", "A"), Card("S", "2"), Card("C", "3"), Card("S", "4"), Card("H", "5")]) assert weaker_hand.score() < stronger_hand.score()
def test_exception_thrown_with_bad_suit(): with pytest.raises(ValueError) as exception: Card("X", "K") assert "suit" in str(exception.value)
def test_gt(): assert Card("C", "A") > Card("C", "K")
def test_lt(): assert Card("C", "K") < Card("C", "A")
def test_hash(): assert Card("H", "A").__hash__() == Card("H", "A").__hash__() assert Card("H", "A").__hash__() != Card("C", "A").__hash__() assert Card("H", "A").__hash__() != Card("H", "T").__hash__()
def test_equality(): assert Card("H", "A") == Card("H", "A") assert Card("H", "A") != Card("C", "A") assert Card("H", "A") != Card("H", "T")
def test_numeric_ranks_monotonicity(): ranks = "23456789TJQKA" numeric_ranks = [Card("H", r).numeric_rank() for r in ranks] assert all(larger > smaller for larger, smaller in zip(numeric_ranks[1:], numeric_ranks))
def test_exception_thrown_with_bad_rank(): with pytest.raises(ValueError) as exception: Card("H", "X") assert "rank" in str(exception.value)
def test_simulator_sanity(): # No chance of losing with the highest royal flush assert 1.0 == simulator.probability_of_winning( [Card("D", "A"), Card("D", "K")], 3, [ Card("D", "Q"), Card("D", "J"), Card("D", "T"), Card("H", "A"), Card("H", "9") ]) # No chance of winning with 2 and 3 as highest cards assert 0.0 == simulator.probability_of_winning( [Card("H", "2"), Card("D", "3")], 3, [ Card("H", "T"), Card("H", "A"), Card("D", "5"), Card("C", "J"), Card("C", "9") ]) # no certainty, want this to be close to 50% to avoid failures due to inaccurate answers being 1 or 0 chance_of_winning = simulator.probability_of_winning( [Card("D", "T"), Card("H", "7")], 3, [ Card("H", "T"), Card("H", "A"), Card("D", "5"), Card("C", "J"), Card("C", "9") ]) assert chance_of_winning not in (1.0, 0.0)
def test_strongest_full_house_wins(): weaker_hand = FiveCardHand([Card("H", "T"), Card("C", "T"), Card("S", "6"), Card("C", "6"), Card("H", "6")]) stronger_hand = FiveCardHand([Card("H", "7"), Card("S", "7"), Card("C", "7"), Card("S", "2"), Card("H", "2")]) assert weaker_hand.score() < stronger_hand.score()
def test_strongest_two_pair_wins(): stronger_hand = FiveCardHand([Card("H", "T"), Card("C", "T"), Card("S", "6"), Card("C", "6"), Card("H", "3")]) weaker_hand = FiveCardHand([Card("H", "A"), Card("S", "9"), Card("C", "9"), Card("S", "7"), Card("H", "7")]) assert weaker_hand.score() < stronger_hand.score()
def test_strongest_pair_wins(): weaker_hand = FiveCardHand([Card("H", "A"), Card("C", "K"), Card("S", "Q"), Card("C", "3"), Card("H", "3")]) stronger_hand = FiveCardHand([Card("H", "A"), Card("S", "K"), Card("C", "K"), Card("S", "7"), Card("H", "6")]) assert weaker_hand.score() < stronger_hand.score()
def test_high_card_does_the_job(): best_straight_flush = [Card("C", rank) for rank in "AKQJT"] next_best_straight_flush = [Card("C", rank) for rank in "KQJT9"] assert FiveCardHand(best_straight_flush).score() > FiveCardHand(next_best_straight_flush).score()