JSpec is a behavior driven development framework based on RSpec. Snice I do all of my unit level testing with RSpec, JSpec was a comfortable fit for me. It has a DSL to define specifications (before, after, describe, and it blocks). And also a matcher library to add some syntactic sugar to your assertions.
…let’s go bowlin'!
The following is JSpec in action. It uses the Ron Jeffries' bowling game as an example. This is generally the first bit of TDD a developer sees. It explains the general red-green-refactor workflow of TDD, and stresses the importance of keeping your code clean.
To begin a JSpec project needs to be created.
First, install JSpec and set up the project:
The library file and its spec file get renamed to something that has meaning. The test runner also needs to get updated to reference the renamed files:
Now, start the spec watcher:
This starts a process that detects changes in the spec or implementation files then opens a Firefox tab that runs all specs for the project.
There needs to be a place to hang the code, so the initial test will ensure that the library exists.
It fails with “ReferenceError: BowlingGame is not defined”. Make it pass by adding a factory to generate a BowlingGame object:
Then create a spec to excercise the game logic. The simplest game a player can roll is all gutterballs:
And this fails with “TypeError: game.roll is not a function”. So define the methods under test on the BowlingGame lib:
And the spec passes. The next simplest game is one where the player rolls all 1s.
In this iteration I extracted the “player rolls” part of the describe blocks into a shared describe block. The output still has “player rolls” in it. I also pulled the for loop into the “roll_a” helper located in the spec.helper.js file. This file gets loaded before any of the specs run.
Now make the spec pass:
So far the design is simple. There is an accumulator variable that gets incremented by the number of pins felled for a roll.
The next case to test is when the player rolls a spare:
This fails with the message “expected 15 to eql 18”. Now the design needs to change. In order to detect that the player rolled a spare, the code needs to be able to look forward and backward in the history of rolls.
This design changes satisfies the previous specs, but it doesn’t satisfy the case that exercises a spare. It needs further refinement.
In this iteration, the score is calculated by frame (like any good bowling game should). This allows for the game to detect if the player has rolled a spare. It can also look ahead to calculate the bonus for the spare.
Now to test for a strike:
And it fails with ‘expected NaN to eql 28’. There’s an indexing error. And the fix:
Success! Now for the grand finale, the perfect game:
Our game logic satisfies this case. We’ve made some manly code! Even if JSpec isn’t a good fit for you, at least give some form of TDD a try. The final code for this exercise is available on my github account.