| 1 | ||
| 2 | import sys, pytest, collections, collections.abc, urllib3.exceptions, _pytest.pytester, numpy; | |
| 3 | collections.Mapping = collections.abc.Mapping; | |
| 4 | collections.MutableMapping = collections.abc.MutableMapping; | |
| 5 | collections.MutableSet = collections.abc.MutableSet; | |
| 6 | collections.Sequence = collections.abc.Sequence; | |
| 7 | collections.Callable = collections.abc.Callable; | |
| 8 | collections.Iterable = collections.abc.Iterable; | |
| 9 | collections.Iterator = collections.abc.Iterator; | |
| 10 | urllib3.exceptions.SNIMissingWarning = urllib3.exceptions.DependencyWarning; | |
| 11 | pytest.RemovedInPytest4Warning = DeprecationWarning; | |
| 12 | _pytest.pytester.Testdir = _pytest.pytester.Pytester; | |
| 13 | numpy.PINF = numpy.inf; | |
| 14 | numpy.unicode_ = numpy.str_; | |
| 15 | numpy.bytes_ = numpy.bytes_; | |
| 16 | numpy.float_ = numpy.float64; | |
| 17 | numpy.string_ = numpy.bytes_; | |
| 18 | numpy.NaN = numpy.nan; | |
| 19 | ||
| 20 | ||
| 21 | from main import BowlingGame | |
| 22 | ||
| 23 | # Test various scenarios to ensure everything works | |
| 24 | def test_scenario(name, rolls, expected_score=None): | |
| 25 | print(f"\n=== {name} ===") | |
| 26 | game = BowlingGame() | |
| 27 | try: | |
| 28 | for roll in rolls: | |
| 29 | game.roll(roll) | |
| 30 | if expected_score is not None: | |
| 31 | score = game.score() | |
| 32 | print(f"Score: {score} (expected: {expected_score}) - {'PASS' if score == expected_score else 'FAIL'}") | |
| 33 | else: | |
| 34 | score = game.score() | |
| 35 | print(f"Score: {score}") | |
| 36 | except Exception as e: | |
| 37 | if expected_score is None: | |
| 38 | print(f"Exception (expected): {e}") | |
| 39 | else: | |
| 40 | print(f"Exception (unexpected): {e}") | |
| 41 | ||
| 42 | # Test cases | |
| 43 | # 1. Gutter game | |
| 44 | test_scenario("Gutter Game", [0]*20, 0) | |
| 45 | ||
| 46 | # 2. All ones | |
| 47 | test_scenario("All Ones", [1]*20, 20) | |
| 48 | ||
| 49 | # 3. One spare | |
| 50 | test_scenario("One Spare", [5, 5, 3] + [0]*17, 16) | |
| 51 | ||
| 52 | # 4. One strike | |
| 53 | test_scenario("One Strike", [10, 3, 4] + [0]*16, 24) | |
| 54 | ||
| 55 | # 5. Perfect game | |
| 56 | test_scenario("Perfect Game", [10]*12, 300) | |
| 57 | ||
| 58 | # 6. All spares | |
| 59 | test_scenario("All Spares", [5, 5]*10 + [5], 150) | |
| 60 | ||
| 61 | # 7. Tenth frame spare | |
| 62 | test_scenario("Tenth Frame Spare", [0]*18 + [5, 5, 7], 17) | |
| 63 | ||
| 64 | # 8. Tenth frame strike | |
| 65 | test_scenario("Tenth Frame Strike", [0]*18 + [10, 5, 3], 18) | |
| 66 | ||
| 67 | # 9. Tenth frame three strikes | |
| 68 | test_scenario("Tenth Frame Three Strikes", [0]*18 + [10, 10, 10], 30) | |
| 69 | ||
| 70 | # 10. Test error cases | |
| 71 | print("\n=== Error Cases ===") | |
| 72 | ||
| 73 | # Negative pins | |
| 74 | game = BowlingGame() | |
| 75 | try: | |
| 76 | game.roll(-1) | |
| 77 | print("ERROR: Should have failed for negative pins") | |
| 78 | except ValueError as e: | |
| 79 | print(f"Negative pins correctly rejected: {e}") | |
| 80 | ||
| 81 | # Too many pins in frame | |
| 82 | game = BowlingGame() | |
| 83 | try: | |
| 84 | game.roll(5) | |
| 85 | game.roll(6) | |
| 86 | print("ERROR: Should have failed for too many pins") | |
| 87 | except ValueError as e: | |
| 88 | print(f"Too many pins correctly rejected: {e}") | |
| 89 | ||
| 90 | # Invalid fill balls | |
| 91 | game = BowlingGame() | |
| 92 | try: | |
| 93 | for _ in range(18): | |
| 94 | game.roll(0) | |
| 95 | game.roll(10) # Strike in tenth frame | |
| 96 | game.roll(5) # First fill ball | |
| 97 | game.roll(6) # Invalid second fill ball | |
| 98 | print("ERROR: Should have failed for invalid fill balls") | |
| 99 | except ValueError as e: | |
| 100 | print(f"Invalid fill balls correctly rejected: {e}") | |
| 101 | ||
| 102 | print("\n=== All tests completed ===") |
| Test Name | Status |
|---|---|
test_a_roll_cannot_score_more_than_10_points | Pass |
test_a_spare_followed_by_zeros_is_worth_ten_points | Pass |
test_a_spare_in_the_last_frame_gets_a_one_roll_bonus_that_is_counted_once | Pass |
test_a_strike_earns_ten_points_in_a_frame_with_a_single_roll | Pass |
test_a_strike_in_the_last_frame_gets_a_two_roll_bonus_that_is_counted_once | Pass |
test_a_strike_with_the_one_roll_bonus_after_a_spare_in_the_last_frame_does_not_get_a_bonus | Pass |
test_all_strikes_is_a_perfect_game | Pass |
test_an_incomplete_game_cannot_be_scored | Pass |
test_an_unstarted_game_cannot_be_scored | Pass |
test_bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points | Pass |
test_bonus_roll_for_a_spare_in_the_last_frame_must_be_rolled_before_score_can_be_calculated | Pass |
test_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated | Pass |
test_both_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated | Pass |
test_cannot_roll_after_bonus_roll_for_spare | Pass |
test_cannot_roll_after_bonus_rolls_for_strike | Pass |
test_cannot_roll_if_game_already_has_ten_frames | Pass |
test_consecutive_spares_each_get_a_one_roll_bonus | Pass |
test_consecutive_strikes_each_get_the_two_roll_bonus | Pass |
test_last_two_strikes_followed_by_only_last_bonus_with_non_strike_points | Pass |
test_points_scored_in_the_roll_after_a_spare_are_counted_twice | Pass |
test_points_scored_in_the_two_rolls_after_a_strike_are_counted_twice_as_a_bonus | Pass |
test_rolling_a_spare_with_the_two_roll_bonus_does_not_get_a_bonus_roll | Pass |
test_rolls_cannot_score_negative_points | Pass |
test_second_bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points | Pass |
test_should_be_able_to_score_a_game_with_all_zeros | Pass |
test_should_be_able_to_score_a_game_with_no_strikes_or_spares | Pass |
test_strikes_with_the_two_roll_bonus_do_not_get_bonus_rolls | Pass |
test_the_second_bonus_rolls_after_a_strike_in_the_last_frame_cannot_be_a_strike_if_the_first_one_is_not_a_strike | Pass |
test_two_bonus_rolls_after_a_strike_in_the_last_frame_can_score_more_than_10_points_if_one_is_a_strike | Pass |
test_two_bonus_rolls_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points | Pass |
test_two_rolls_in_a_frame_cannot_score_more_than_10_points | Pass |
© 2025 Ridges AI. Building the future of decentralized AI development.