This is a paired-programming exercise.
The goal of this activity is to practice the red-green-refactor cycle:
RED
: You must add a new test or some new code to an ongoing test, which causes the test to fail.GREEN
: You must add the code needed to make the failing test pass.REFACTOR
: You must clean up the code, including test code, to make them more readable; must do before moving on to writing the next test.Use the red-green-refactor prop as you work through this activity to help you internalize the process.
General Rules to follow (TDD Rules):
Frame | Roll 1 | Roll 2 | Special | Extra Points | Frame Score | Game Score |
---|---|---|---|---|---|---|
1 | 1 | 4 | 0 | 5 | 5 | |
2 | 4 | 5 | 0 | 9 | 14 | |
3 | 6 | 4 | Spare | 5 | 15 | 29 |
4 | 5 | 5 | Spare | 10 | 20 | 49 |
5 | 10 | Strike | 1 | 11 | 60 | |
6 | 0 | 1 | 0 | 1 | 61 | |
7 | 7 | 3 | Spare | 6 | 16 | 77 |
8 | 6 | 4 | Spare | 10 | 20 | 97 |
9 | 10 | Strike | 10 | 20 | 117 | |
10 | 2 | 8 | Spare | 6 | 16 | 133 |
6 | 133 |
Frame | Roll 1 | Roll 2 | Special | Extra Points | Frame Score | Game Score |
---|---|---|---|---|---|---|
1 | 10 | Strike | 20 | 30 | 30 | |
2 | 10 | Strike | 20 | 30 | 60 | |
3 | 10 | Strike | 20 | 30 | 90 | |
4 | 10 | Strike | 20 | 30 | 120 | |
5 | 10 | Strike | 20 | 30 | 150 | |
6 | 10 | Strike | 20 | 30 | 180 | |
7 | 10 | Strike | 20 | 30 | 210 | |
8 | 10 | Strike | 20 | 30 | 240 | |
9 | 10 | Strike | 20 | 30 | 270 | |
10 | 10 | Strike | 20 | 30 | 300 | |
10 | 10 | 300 |
These are the steps (as represented by test cases) that you will be going through to develop the bowling game scorer.
RED
BowlingTest.java
class in the test directory.nothing()
test with the @Test
annotation.GREEN
org.junit.test
.REFACTOR
RED
nothing
test to canCreateGame
.Game g = new Game();
line to the test.GREEN
Game
.REFACTOR
RED
canCreateGame
test to canRoll
.g.roll(0);
to the test.GREEN
roll
in Game
.pins
.REFACTOR
RED
gutterGame
test.g
, then roll twenty zeroes (for loop).GREEN
assertEquals
to import the static method from org.junit
.score
to create a score method in Game
.REFACTOR
Game g
variable, and have it initialized in the setUp
method.g
variable from any of the tests, so that the field variable is used.canRoll
test.Exception
to remove the unneeded throws Exception
.RED
allOnes
test.assertEquals(20, g.score());
.GREEN
Game
, create a field score
, initialize it to 0, and return it in the score
method.roll
method, increment the score
by the pins
.REFACTOR
gutterGame
test, perform Extract Variable on the 0
within the roll
, to variable pins
. Move it above the loop.20
in the loop, to variable n
.rollMany
, place parameters in order n
, pins
, and replace duplicates.gutterGame
test, perform Inline on the local variables n
and pins
.rollMany
method, to the Game
class.PRE-REFACTOR
rolls
in Game
, to store array of ints. Initialize it to an array of length 21.currentRoll
in Game
, initialized to 0. Delete the score
field.roll
method, add the pins
to the currentRoll
spot in the rolls
array, and increment currentRoll
. Remove the score
increment.score
method, loop over the rolls
array up to the currentRoll
, and accumulate the values in a local variable score
, then return that variable.for
loop in score
so that it loops over 10 frames. Create a local firstInFrame
variable starting at 0. For each frame
add to the score the value of rolls
at firstInFrame
and firstInFrame + 1
, then increment firstInFrame
by 2.RED
oneSpare
test, on which you roll 5, 5 and 3, then roll 17 zeroes (using rollMany
).GREEN
rolls[firstInFrame] + rolls[firstInFrame + 1]
equals 10. If it is, increment the score
by 10 + rolls[firstInFrame + 2]
then increment firstInFrame
by 2.REFACTOR
if
into a method isSpare
.rollSpare
method.RED
oneStrike
test, on which you roll 10, then 3 and 4, then 17 zeroes.GREEN
rolls[firstInFrame]
equals 10. Place an else before the next if.score
by 10 plus rolls[firstInFrame + 1] + rolls[firstInFrame + 2]
, then increment firstInFrame
by 1.REFACTOR
isStrike
method (don’t fold parameters).rolls[firstInFrame + 1] + rolls[firstInFrame + 2]
part of the strike conditional branch into a nextTwoBallsForStrike
method.rolls[firstInFrame + 2]
part of the spare conditional branch into a nextBallForSpare
method (don’t process duplicates).rolls[firstInFrame] + rolls[firstInFrame + 1];
part of the normal frame part into a twoBallsInFrame
method.RED
perfectGame
test, on which you roll twelve 10s.GREEN
REFACTOR