Bowling Game Kata Part Three - The Normal Score Game

Let's write our next few tests. In these tests we score a normal game in which there are no strikes or spares. We throw the ball down the lane and knock down a single pin.

Normal Game

BowlingGame.Test/GameTest.cs
[Test]
public void Game_AllOnes_ReturnsScore()
{
    var game = new Game();

    for ( var i = 0; i < 20; i++ )
    {
        game.Roll( 1 );
    }

    Assert.That( game.Score(), Is.EqualTo( 20 ) );
}

Let's compile and run the test.

1 test failed "Expected: 20 But was: 0"

We need to get this code passing. Looking at the score method we are returning a 0. This is because we are at the "constant" stage of Uncle Bob's Transformation Priority Premise. We need to move to the level of "scalar". This will be a variable to hold the score of the game.

BowlingGame/Game.cs
private int score;

public void Roll( int pins )
{
    score += pins;
}

public int Score()
{
    return score;
}

Compile and run the tests.

2 tests passed

Now that our tests are passing, we can do some refactoring.

  1. Both tests instantiate a new Game.
  2. Both tests have a loop that rolls the ball.

Let's extract this duplicate code out.

BowlingGame.Test/GameTest.cs
[SetUp]
public void TestSetup()
{
    game = new Game();
}

private Game game;

private void RollMany( int rolls, int pins )
{
    for ( var i = 0; i < rolls; i++ )
    {
        game.Roll( pins );
    }
}

[Test]
public void Game_AllOnes_ReturnsScore()
{
    RollMany( 20, 1 );

    Assert.That( game.Score(), Is.EqualTo( 20 ) );
}

[Test]
public void Game_AllZeros_ReturnsScore()
{
    RollMany( 20, 0 );

    Assert.That( game.Score(), Is.EqualTo( 0 ) );
}

The SetUp attribute indicates code that should run before each test. Before each test runs, we want to instantiate a new Game.

We created a RollMany method to take care of the loop.

At the end of the Normal Game tests, our code looks like this:

BowlingGame/Game.cs
namespace BowlingGame
{
    public class Game
    {
        private int score;

        public void Roll( int pins )
        {
            score += pins;
        }

        public int Score()
        {
            return score;
        }
    }
}
BowlingGame.Test/GameTest.cs
using NUnit.Framework;

namespace BowlingGame.Test
{
    [TestFixture]
    public class GameTest
    {
        [SetUp]
        public void TestSetup()
        {
            game = new Game();
        }

        private Game game;

        private void RollMany( int rolls, int pins )
        {
            for ( var i = 0; i < rolls; i++ )
            {
                game.Roll( pins );
            }
        }

        [Test]
        public void Game_AllOnes_ReturnsScore()
        {
            RollMany( 20, 1 );

            Assert.That( game.Score(), Is.EqualTo( 20 ) );
        }

        [Test]
        public void Game_AllZeros_ReturnsScore()
        {
            RollMany( 20, 0 );

            Assert.That( game.Score(), Is.EqualTo( 0 ) );
        }
    }
}