Example #1
0
class BallTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        pygame.init()
        pygame.mixer.set_num_channels(0)

    def setUp(self):
        self.ball = Ball()
        self.ball.rect.center = (SCREEN_HEIGHT // 2, SCREEN_WIDTH // 2)
        self.ball.vx, self.ball.vy = 1, 1

    def test_reset_state(self):
        Ball.is_fiery = True
        Ball.is_tiny = True
        Ball.image = None
        Ball.reset_state()

        msg = "state hasn't been reset properly"
        self.assertFalse(Ball.is_fiery, msg=msg)
        self.assertFalse(Ball.is_tiny, msg=msg)
        self.assertEqual(Ball.image, Ball.images["base"], msg=msg)

    def test_init(self):
        msg = "ball shouldn't start with bonuses"
        self.assertFalse(self.ball.is_fiery, msg=msg)
        self.assertFalse(self.ball.is_tiny, msg=msg)

        msg = "ball should start attached"
        self.assertTrue(self.ball.is_attached, msg=msg)

    def test_update(self):
        x0, y0 = self.ball.rect.center
        self.ball.update()

        msg = "attached ball shouldn't move by itself"
        self.assertEqual((x0, y0), self.ball.rect.center, msg=msg)

        self.ball.is_attached = False
        self.ball.update()

        msg = "wrong position update"
        self.assertEqual((x0 + self.ball.vx, y0 + self.ball.vy),
                         self.ball.rect.center,
                         msg=msg)

        self.ball.rect.center = MARGIN, SCREEN_HEIGHT // 2
        vx, vy = -1, -1
        self.ball.vx, self.ball.vy = vx, vy
        self.ball.update()

        msg = "wrong position after hitting the left margin"
        self.assertGreaterEqual(self.ball.rect.left, MARGIN, msg=msg)

        msg = "wrong speed after hitting the left margin"
        self.assertAlmostEqual(self.ball.vx, -vx, msg=msg)
        self.assertAlmostEqual(self.ball.vy, vy, msg=msg)

        self.ball.rect.center = SCREEN_WIDTH - MARGIN, SCREEN_HEIGHT // 2
        vx, vy = 1, -1
        self.ball.vx, self.ball.vy = vx, vy
        self.ball.update()

        msg = "wrong position after hitting the right margin"
        self.assertLessEqual(self.ball.rect.right,
                             SCREEN_WIDTH - MARGIN,
                             msg=msg)

        msg = "wrong speed after hitting the right margin"
        self.assertAlmostEqual(self.ball.vx, -vx, msg=msg)
        self.assertAlmostEqual(self.ball.vy, vy, msg=msg)

        self.ball.rect.center = SCREEN_WIDTH // 2, 2 * MARGIN
        vx, vy = -1, -1
        self.ball.vx, self.ball.vy = vx, vy
        self.ball.update()

        msg = "wrong position after hitting the top"
        self.assertGreaterEqual(self.ball.rect.top, 2 * MARGIN, msg=msg)

        msg = "wrong speed after hitting the top"
        self.assertAlmostEqual(self.ball.vx, vx, msg=msg)
        self.assertAlmostEqual(self.ball.vy, -vy, msg=msg)

        self.ball.rect.center = SCREEN_WIDTH // 2, SCREEN_HEIGHT + 2 * MARGIN
        ball_group = pygame.sprite.Group()
        ball_group.add(self.ball)

        msg = "ball added to a group but not present there (PYGAME ISSUE)"
        self.assertTrue(self.ball.alive(), msg=msg)
        self.ball.update()

        msg = "ball disappeared but is not dead"
        self.assertFalse(self.ball.alive(), msg=msg)

    def test_draw(self):
        surface = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))  # pylint: disable=too-many-function-args
        self.ball.draw(surface)

        msg = "ball is not displayed"
        white = (255, 255, 255, 255)
        self.assertEqual(surface.get_at(self.ball.rect.center), white, msg=msg)

    def test_on_hit(self):
        paddle = Paddle()
        paddle.rect.center = self.ball.rect.left + 5, self.ball.rect.bottom + 1
        paddle.is_magnetic = True
        self.ball.is_attached = False
        vx, vy = self.ball.vx, self.ball.vy
        self.ball.on_hit(paddle)

        msg = "ball hit a magnetic paddle but didn't get attached"
        self.assertTrue(self.ball.is_attached, msg=msg)
        self.assertIn(self.ball, paddle.attached_balls, msg=msg)

        self.ball.on_hit(paddle)

        msg = "ball didn't get detached from the paddle"
        self.assertFalse(self.ball.is_attached, msg=msg)

        msg = "wrong ball direction after hitting the paddle"
        self.assertTrue(self.ball.vy * vy < 0, msg=msg)

        msg = "ball speed didn't increase after hitting the paddle"
        self.assertGreater(math.hypot(self.ball.vx, self.ball.vy),
                           math.hypot(vx, vy),
                           msg=msg)

        self.ball.rect.center = paddle.rect.left + 5, paddle.rect.top + 1
        self.ball.vx, self.ball.vy = self.ball.MAXSPEED * 3 // 5, self.ball.MAXSPEED * 4 // 5
        self.ball.on_hit(paddle)

        msg = "max ball speed exceded"
        self.assertLessEqual(math.hypot(self.ball.vx, self.ball.vy),
                             self.ball.MAXSPEED,
                             msg=msg)

    def test_hit(self):
        tile = RegularTile(self.ball.rect.center[0] + 10,
                           self.ball.rect.center[1] + 10)
        tile_group = pygame.sprite.Group()
        tile_group.add(tile)
        vx, vy = self.ball.vx, self.ball.vy
        self.ball.hit(tile)

        msg = "wrong ball direction after hit"
        self.assertAlmostEqual(self.ball.vx, vx, msg=msg)
        self.assertAlmostEqual(self.ball.vy, -vy, msg=msg)

        msg = "tile hit but not updated"
        self.assertFalse(tile.alive(), msg=msg)
        self.assertEqual(pygame.event.poll().type, events.POINTS, msg=msg)

        self.ball.is_fiery = True
        tile = RegularTile(self.ball.rect.center[0] + 10,
                           self.ball.rect.center[1])
        vx, vy = self.ball.vx, self.ball.vy
        self.ball.hit(tile)

        msg = "wrong ball direction after hit"
        self.assertAlmostEqual(self.ball.vx, -vx, msg=msg)
        self.assertAlmostEqual(self.ball.vy, vy, msg=msg)

        msg = "ball is fiery but there was no explosion after hit"
        self.assertIn(events.EXPLOSION,
                      (event.type for event in pygame.event.get()),
                      msg=msg)