| 1 | import unittest | |
| 2 | from main import BowlingGame | |
| 3 | ||
| 4 | class TestBowlingGameComprehensive(unittest.TestCase): | |
| 5 | ||
| 6 | def test_negative_pins(self): | |
| 7 | game = BowlingGame() | |
| 8 | with self.assertRaises(ValueError) as context: | |
| 9 | game.roll(-1) | |
| 10 | self.assertIn("invalid pin count", str(context.exception)) | |
| 11 | ||
| 12 | def test_too_many_pins(self): | |
| 13 | game = BowlingGame() | |
| 14 | with self.assertRaises(ValueError) as context: | |
| 15 | game.roll(11) | |
| 16 | self.assertIn("invalid pin count", str(context.exception)) | |
| 17 | ||
| 18 | def test_invalid_frame_pins(self): | |
| 19 | game = BowlingGame() | |
| 20 | game.roll(5) | |
| 21 | with self.assertRaises(ValueError) as context: | |
| 22 | game.roll(6) # Would make 11 in frame | |
| 23 | self.assertIn("invalid pin count", str(context.exception)) | |
| 24 | ||
| 25 | def test_game_already_completed(self): | |
| 26 | game = BowlingGame() | |
| 27 | for _ in range(20): | |
| 28 | game.roll(0) | |
| 29 | with self.assertRaises(ValueError) as context: | |
| 30 | game.roll(0) | |
| 31 | self.assertIn("game already completed", str(context.exception)) | |
| 32 | ||
| 33 | def test_score_before_completion(self): | |
| 34 | game = BowlingGame() | |
| 35 | game.roll(10) | |
| 36 | with self.assertRaises(ValueError) as context: | |
| 37 | game.score() | |
| 38 | self.assertIn("game not yet completed", str(context.exception)) | |
| 39 | ||
| 40 | def test_all_strikes(self): | |
| 41 | game = BowlingGame() | |
| 42 | for _ in range(12): | |
| 43 | game.roll(10) | |
| 44 | self.assertEqual(game.score(), 300) | |
| 45 | ||
| 46 | def test_alternating_strike_spare(self): | |
| 47 | game = BowlingGame() | |
| 48 | # Frame 1: Strike | |
| 49 | game.roll(10) | |
| 50 | # Frame 2: Spare (5,5) | |
| 51 | game.roll(5) | |
| 52 | game.roll(5) | |
| 53 | # Frame 3: Strike | |
| 54 | game.roll(10) | |
| 55 | # Frame 4: Spare (2,8) | |
| 56 | game.roll(2) | |
| 57 | game.roll(8) | |
| 58 | # Frame 5: Strike | |
| 59 | game.roll(10) | |
| 60 | # Frame 6: Open (3,4) | |
| 61 | game.roll(3) | |
| 62 | game.roll(4) | |
| 63 | # Frame 7: Strike | |
| 64 | game.roll(10) | |
| 65 | # Frame 8: Spare (6,4) | |
| 66 | game.roll(6) | |
| 67 | game.roll(4) | |
| 68 | # Frame 9: Open (1,2) | |
| 69 | game.roll(1) | |
| 70 | game.roll(2) | |
| 71 | # Frame 10: Strike, Spare, 5 | |
| 72 | game.roll(10) | |
| 73 | game.roll(5) | |
| 74 | game.roll(5) | |
| 75 | ||
| 76 | # Let's calculate: | |
| 77 | # Frame 1: 10 + 5 + 5 = 20 | |
| 78 | # Frame 2: 5 + 5 + 10 = 20 | |
| 79 | # Frame 3: 10 + 2 + 8 = 20 | |
| 80 | # Frame 4: 2 + 8 + 10 = 20 | |
| 81 | # Frame 5: 10 + 3 + 4 = 17 | |
| 82 | # Frame 6: 3 + 4 = 7 | |
| 83 | # Frame 7: 10 + 6 + 4 = 20 | |
| 84 | # Frame 8: 6 + 4 + 1 = 11 | |
| 85 | # Frame 9: 1 + 2 = 3 | |
| 86 | # Frame 10: 10 + 5 + 5 = 20 | |
| 87 | # Total: 158 | |
| 88 | self.assertEqual(game.score(), 158) | |
| 89 | ||
| 90 | def test_tenth_frame_edge_cases(self): | |
| 91 | # Test 10th frame with strike, then open frame | |
| 92 | game = BowlingGame() | |
| 93 | for _ in range(18): | |
| 94 | game.roll(0) | |
| 95 | game.roll(10) # Strike | |
| 96 | game.roll(3) | |
| 97 | game.roll(4) | |
| 98 | self.assertEqual(game.score(), 17) | |
| 99 | ||
| 100 | def test_tenth_frame_spare_then_strike(self): | |
| 101 | game = BowlingGame() | |
| 102 | for _ in range(18): | |
| 103 | game.roll(0) | |
| 104 | game.roll(5) | |
| 105 | game.roll(5) # Spare | |
| 106 | game.roll(10) # Fill ball - strike | |
| 107 | self.assertEqual(game.score(), 20) | |
| 108 | ||
| 109 | def test_invalid_tenth_frame(self): | |
| 110 | # This should test invalid fill ball scenarios | |
| 111 | pass # Will implement if needed | |
| 112 | ||
| 113 | if __name__ == "__main__": | |
| 114 | unittest.main() |
| 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.