In the last chapter, you wrote your first test, including little bits of nonsense code (likegame.roll
, which technically doesn't exist anywhere yet). You did this in the BowlingGameSpec.js
file in the spec
folder.
It's time to write JavaScript code that accompanies the test! 💻 #JS4ever
Open the file you created called BowlingGame.js
(in the src
folder of your Jasmine directory).
Reminder, here's the contents of your test file:
describe("Bowling game", function() {
it("should properly calculate a gutter game", function() {
game.roll(20, 0);
expect(game.score()).toEqual(0);
});
it("should properly calculate a strike", function () {
// test
});
it("should properly calculate a spare", function () {
// test
});
});
Running your test
You've written the test but haven't actually run it to see if it will pass or fail.
Of course, the test will fail at first because you haven't written any code to support it. In TDD, it's still important to see your test fail the first time though.
Open up the file called SpecRunner.html
included in the Jasmine standalone package or in the files you downloaded at the beginning of the second course part.
From the above test, we know we need to define multiple entities in our actual JavaScript code.
the idea of a
BowlingGame
a function of rolling many times or at all, ex.
roll
androllMany
the notion of a
game
the notion of a
score
For example, introduce the notion of a BowlingGame
first. It's as simple as adding this to your BowlingGame.js
file :
var BowlingGame = function() {
};
Remember, you're only coding just enough to make the test pass! Since your first error was the BowlingGame
doesn't exist, all you did was add that.
Refresh the SpecRunner.html
page. Now you'll see:
Ok, game
isn't defined. Fair enough! Define it.
Since you'll need to define a new game
for every test that is run (so as not to combine the results of multiple, separate games), we can do a bit of setup in the tests themselves.
Back in the BowlingGameSpec
file, add a line above your tests saying to create a new instance of BowlingGame
for each test, and assign it to a game
variable.
In BowlingGameSpec
(your test file):
describe("BowlingGame", function() {
var game;
beforeEach(function(){
game = new BowlingGame();
});
// ...
Save your changes, and refresh SpecRunner.html
again.
You have another error now, which says game.roll
is not a function ("TypeError: game.roll is not a function").
This means BowlingGame
needs a function called roll
that is more action-oriented. Define this in the code, rerun the test, and see what error you get next.
Do this enough times, and here's the code you might end up with. Even if this is your final code, code one step at a time! ☝️
Here's what BowlingGame.js
looks like:
var BowlingGame = function() {
this.rolls = [];
this.currentRoll = 0;
};
BowlingGame.prototype.roll = function(pins) {
this.rolls[this.currentRoll++] = pins;
};
BowlingGame.prototype.score = function() {
var score = 0;
var frameIndex = 0;
var self = this;
function sumOfBallsInFrame() {
return self.rolls[frameIndex] + self.rolls[frameIndex + 1];
}
for (var frame = 0; frame < 10; frame++) {
score += sumOfBallsInFrame();
frameIndex += 2;
}
return score;
};
And here's BowlingGameSpec.js
:
describe("BowlingGame", function() {
var game;
beforeEach(function(){
game = new BowlingGame();
});
function rollMany (n, pins) {
for (var i = 0; i < n; i++) {
game.roll(pins)
}
}
it("should handle a gutter game", function() {
rollMany(20, 0);
expect(game.score()).toEqual(0);
});
it("should properly calculate a strike", function () {
// test
});
it("should properly calculate a spare", function () {
// test
});
});
You've written enough code in your source and spec files to make your first test pass. Look at all that green in SpecRunner.html
! ✅🍏📗💚
Only now can you attack writing the code for your second test:
it("should properly calculate a strike", function () {
// test
});
You'll write code associated with rolling strikes and spares while making sure to not break your other code. You'll know you've broken something in a previous test if that test starts erroring, when previously it was passing.
This is the classic TDD cycle.
Write the basic test.
Run the test.
Write the simplest code to fix the first error.
Rerun the test.
Write the simplest code to fix the next error.
Repeat until all the tests pass.
Next up, you'll get to put this workflow into practice in an activity: build a candy store! 🍬🍭🍫