Skip to content

Commit 72d0fb7

Browse files
committed
Update bowling canonical-data
This is based on my work implementing this problem for Rust exercism/rust#213 I'm addressing a few things here. - The description at the top is now about implementing the tests, not about the problem domain. - I've reordered the test to (hopefully) make things flow more smoothly. I found that the previous set of tests introduced concepts in kind of a mix, instead of one at a time. They are now: - Score a 0 point game - Score a game with no spares/strikes - Spares - Simple spare - Spare with bonus - Spare in last frame - Strikes - Simple strike - Strike with bonus - Strike in last frame - Exceptions - Updated descriptions. My goal here was to try to clearly state what bit of scoring logic was being tested in each test, without relying too much on bowling-specific terms. 'strike', 'spare' and 'frame' are unavoidable, but other terms were replaceable. - Remove unnecessary tests. There were a few different tests of games without spares & strikes when only one is really necessary. My goal is that each test should lead the student to make one change to their code. If a bunch of tests can pass because of the same change then some of those tests can be removed. - Explicit description of arity removed. I tried to cover the expected API in the description text. - Expectations of exceptions changed from specific error text to `-1`, which is what I normally see for exception test definitions.
1 parent c5ec354 commit 72d0fb7

File tree

1 file changed

+70
-77
lines changed

1 file changed

+70
-77
lines changed

exercises/bowling/canonical-data.json

Lines changed: 70 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,110 @@
11
{
22
"#": [
3-
"Bowling is game where players roll a heavy ball to knock down pins",
4-
"arranged in a triangle. Write code to keep track of the score of a",
5-
"game of bowling."
3+
"Students should implement roll and score methods.",
4+
"Roll should accept a single integer.",
5+
"Score should return the game's final score, when possible",
6+
"For brevity the tests all the rolls in an array;",
7+
"each element of the rolls array should be passed to the roll method",
8+
"The final tests define situations where the score can not be returned",
9+
"The expection for these tests is -1, indicating an exception",
10+
"In these cases you should expect an exception as is idomatic for your language"
611
],
7-
"methods": {
8-
"description": [
9-
"Check the public API is correct."
10-
],
11-
"cases": [{
12-
"description": "must be able to roll with a number of pins",
13-
"method": "roll",
14-
"arity": 1
15-
}, {
16-
"description": "must have a score",
17-
"method": "score",
18-
"arity": 0
19-
}]
20-
},
2112
"score": {
2213
"description": [
23-
"Check game can be scored correctly."
14+
"Returns the final score of a bowling game"
2415
],
2516
"cases": [{
26-
"description": "should be able to score open frame",
27-
"rolls": [3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
28-
"expected": 7
29-
}, {
30-
"description": "should be able to score multiple frames",
31-
"rolls": [3, 4, 2, 3, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
32-
"expected": 19
33-
}, {
34-
"description": "should be able to score a game with all gutterballs",
17+
"description": "should be able to score a game with all zeros",
3518
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
3619
"expected": 0
3720
}, {
38-
"description": "should be able to score a game with all single pin rolls",
39-
"rolls": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
40-
"expected": 20
41-
}, {
42-
"description": "should be able to score a game with all open frames",
21+
"description": "should be able to score a game with no strikes or spares",
4322
"rolls": [3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6],
4423
"expected": 90
4524
}, {
46-
"description": "should be able to score a strike not in the last frame",
25+
"description": "a spare followed by zeros is worth ten points",
26+
"rolls": [6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
27+
"expected": 10
28+
}, {
29+
"description": "points scored in the roll after a spare are counted twice",
30+
"rolls": [6, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
31+
"expected": 16
32+
}, {
33+
"description": "consecutive spares each get a one roll bonus",
34+
"rolls": [5, 5, 3, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
35+
"expected": 31
36+
}, {
37+
"description": "a spare in the last frame gets a one roll bonus that is counted once",
38+
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 7],
39+
"expected": 17
40+
}, {
41+
"description": "a strike earns ten points in frame with a single roll",
42+
"rolls": [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
43+
"expected": 10
44+
}, {
45+
"description": "points scored in the two rolls after a strike are counted twice as a bonus",
4746
"rolls": [10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
4847
"expected": 26
4948
}, {
50-
"description": "should be able to score a spare not in the last frame",
51-
"rolls": [5, 5, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
52-
"expected": 20
53-
}, {
54-
"description": "should be able to score multiple strikes in a row",
49+
"description": "consecutive strikes each get the two roll bonus",
5550
"rolls": [10, 10, 10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
5651
"expected": 81
5752
}, {
58-
"description": "should be able to score multiple spares in a row",
59-
"rolls": [5, 5, 3, 7, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
60-
"expected": 32
61-
}, {
62-
"description": "should allow fill balls when the last frame is a strike",
53+
"description": "a strike in the last frame gets a two roll bonus that is counted once",
6354
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 1],
6455
"expected": 18
6556
}, {
66-
"description": "should allow fill ball when the last frame is a spare",
67-
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 1, 7],
68-
"expected": 17
57+
"description": "rolling a spare with the two roll bonus does not get a bonus roll",
58+
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 3],
59+
"expected": 20
6960
}, {
70-
"description": "should allow fill balls to be a strike",
61+
"description": "strikes with the two roll bonus do not get bonus rolls",
7162
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10],
7263
"expected": 30
7364
}, {
74-
"description": "should be able to score a perfect game",
65+
"description": "a strike with the one roll bonus after a spare in the last frame does not get a bonus",
66+
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 10],
67+
"expected": 20
68+
}, {
69+
"description": "all strikes is a perfect game",
7570
"rolls": [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
7671
"expected": 300
77-
}]
78-
},
79-
"validations": {
80-
"description": [
81-
"Check game rules."
82-
],
83-
"cases": [{
84-
"description": "should not allow rolls with negative pins",
85-
"rolls": [-1],
86-
"expected": "Pins must have a value from 0 to 10"
8772
}, {
88-
"description": "should not allow rolls better than strike",
89-
"rolls": [11],
90-
"expected": "Pins must have a value from 0 to 10"
73+
"description": "Rolls can not score negative points",
74+
"rolls": [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
75+
"expected": -1
9176
}, {
92-
"description": "should not allow two normal rolls better than strike",
93-
"rolls": [5, 6],
94-
"expected": "Pin count exceeds pins on the lane"
77+
"description": "A roll can not score more than 10 points",
78+
"rolls": [11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
79+
"expected": -1
9580
}, {
96-
"description": "should not allow two normal rolls better than strike in last frame",
97-
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6],
98-
"expected": "Pin count exceeds pins on the lane"
81+
"description": "Two rolls in a frame can not score more than 10 points",
82+
"rolls": [5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
83+
"expected": -1
9984
}, {
100-
"description": "should not allow to take score at the beginning of the game",
85+
"description": "An unstarted game can not be scored",
10186
"rolls": [],
102-
"expected": "Score cannot be taken until the end of the game"
87+
"expected": -1
10388
}, {
104-
"description": "should not allow to take score before the game has ended",
105-
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
106-
"expected": "Score cannot be taken until the end of the game"
89+
"description": "An incomplete game can not be scored",
90+
"rolls": [0, 0],
91+
"expected": -1
10792
}, {
108-
"description": "should not allow rolls after the tenth frame",
93+
"description": "A game with more than ten frames can not be scored",
10994
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
110-
"expected": "Should not be able to roll after game is over"
95+
"expected": -1
96+
}, {
97+
"description": "bonus rolls for a strike in the last frame must be rolled before score can be calculated",
98+
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
99+
"expected": -1
100+
}, {
101+
"description": "both bonus rolls for a strike in the last frame must be rolled before score can be calculated",
102+
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10],
103+
"expected": -1
111104
}, {
112-
"description": "should not calculate score before fill balls have been played",
113-
"rolls": [10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
114-
"expected": "Score cannot be taken until the end of the game"
105+
"description": "bonus roll for a spare in the last frame must be rolled before score can be calculated",
106+
"rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3],
107+
"expected": -1
115108
}]
116109
}
117110
}

0 commit comments

Comments
 (0)