Wednesday, June 29, 2011

Learning Python: #5 - Finish Bowling Game Kata

My finished test class TestGame.py:
import unittest
import Game

class TestGame(unittest.TestCase):

    def setUp(self):
        self.game = Game.Game()

    def testGutterGameHasZeroScore(self):
        for i in range(20):
            self.game.roll(0)
        assert self.game.score() == 0, "Score is zero"
  
    def testGameAllOnesHasScoreOfTwenty(self):
        for i in range(20):
            self.game.roll(1)
        assert self.game.score() == 20
        
    def testGameThrowsExceptionWithMoreThanTwentyOneRolls(self):
        try:
            for i in range(22):
                self.game.roll(10)
        except ValueError:
            pass
        else:
            self.fail("Expected a ValueError")
            
    def testGameWithOneSpare(self):
        self.game.roll(1)
        self.game.roll(9)
        self.game.roll(5)
        
        for i in range(17):
            self.game.roll(0)
        
        assert self.game.score() == 20
        
    def testGameWithOneStrike(self):
        self.game.roll(10)
        self.game.roll(1)
        self.game.roll(1)
        
        for i in range(17):
            self.game.roll(0)
        
        assert self.game.score() == 14
            
    def testPerfectGameScores300(self):
        for i in range(12):
            self.game.roll(10)
        assert self.game.score() == 300, "Perfect Game should score 300"
         
if __name__ == "__main__":
    unittest.main()

My finished Game.py:
MAX_ROLLS = 21
FRAMES = 10
STRIKE = 10
SPARE = 10
    
class Game:
     
    def __init__(self):
        self.scoreArr = []
        
    def roll(self, pins):
        if self.numberOfRollsTaken() > MAX_ROLLS:
            raise ValueError
        self.scoreArr.append(pins)
        
    def score(self):
        score = 0
        currentRoll = 0
        frame = 0
        while frame < FRAMES:
            if self.scoreArr[currentRoll] == STRIKE:
                score += self.scoreNextTwoBalls(currentRoll)
                currentRoll += 1
            elif self.frameScore(currentRoll) == SPARE:
                score += self.scoreNextTwoBalls(currentRoll)
                currentRoll += 2
            else:
                score += self.frameScore(currentRoll)
                currentRoll += 2
                
            frame = frame + 1
        return score

    def numberOfRollsTaken(self):
        return len(self.scoreArr) +1

    def scoreNextTwoBalls(self, index):
        return self.scoreArr[index] + self.scoreArr[index + 1] + self.scoreArr[index + 2]
        
    def frameScore(self, index):
        return self.scoreArr[index] + self.scoreArr[index + 1]
A couple of things that I learned while doing this Bowling Game kata:
  • It appears that it is a requirement for test methods to start with the word 'test' or PyUnit will not recognize them as tests that need to be run.
  • A variable and a method in the same class cannot both have the same name, or at least my syntax was wrong
  • The ':' at the end of class/method definitions and control statements gets me almost everytime; I cannot seem to remember that it needs to be there

No comments:

Post a Comment