JavaScript has remained a popular, if often derided, language since its very inception back in 1995. In recent years its adoption has skyrocketed as demand for standards- and cross device-compliant Web applications has soared. Such applications tend to be pretty complex projects, and appropriately developers have sought to employ sound testing approaches which ensure the code is operating as expected. While manual testing has its place, automated testing strategies can help to ensure maximum and prolonged coverage of code throughout the project lifetime.
Server-side developers have long experienced the benefits of automated testing solutions, taking advantage of testing frameworks such as RSpec for Ruby, PHPUnit for PHP, and JUnit for Java. If you fall into this crowd but are starting to spend more time with JavaScript, chances are you're fretting over how to apply similar techniques on the client (or or server!) side. Not to worry, as several interesting JavaScript testing frameworks exist, perhaps chief among them Jasmine, a popular open source behavior-driven development framework.
Installing Jasmine
Unlike many of the JavaScript testing frameworks which preceded it, Jasmine is dependency-free, allowing you to run Jasmine without further configuration in any environment which runs JavaScript. While you're able to install Jasmine by downloading it from the project page (or more conveniently by cloning it), I suggest installing it as a Ruby gem as the gem offers a few additional convenience features not available via the download. Don't worry if your JavaScript project doesn't otherwise involve Ruby or Rails, because the gem can be used in conjunction with any language! Begin by installing the gem:
$ gem install jasmine
Once installed, create and enter a new directory which we'll use as the basis for exploring Jasmine's capabilities, and then execute the following two commands:
$ jasmine init
Jasmine has been installed with example specs.
...
$ rake jasmine
(in /var/www)
your tests are here:
http://localhost:8888/
To make sure the Jasmine server is properly running, head over to http://localhost:8888/
. You should see the same output as that presented in Figure 1.
Click here for larger image
Figure 1. The Jasmine Spec Suite
Running the Example Specs
If you click the passed
checkbox located at the top right of the page presented in Figure 1, you'll be provided with more details about the five sample tests (known as specs in Jasmine parlance) provided with the Jasmine example spec suite (Figure 2).
Click here for larger image
Figure 2. Viewing the Example Specs
These specs correspond to the Player.js
class, found in the newly created public/javascripts
directory. This class is representative of a JavaScript-based music player. Here's the code:
function Player() {
}
Player.prototype.play = function(song) {
this.currentlyPlayingSong = song;
this.isPlaying = true;
};
Player.prototype.pause = function() {
this.isPlaying = false;
};
Player.prototype.resume = function() {
if (this.isPlaying) {
throw new Error("song is already playing");
}
this.isPlaying = true;
};
Player.prototype.makeFavorite = function() {
this.currentlyPlayingSong.persistFavoriteStatus(true);
};
Let's use this class as the basis for exploring Jasmine's capabilities. Incidentally, if you're not familiar with JavaScript's prototype-based OOP design, see the article, Object-Oriented JavaScript Demystified.
The example specs which are used to validate the Player
class' behavior are found in a file named PlayerSpec.js
which is located in the spec/javascripts
directory. While I certainly suggest you review PlayerSpec.js
as it offers a great example of how to write a proper spec suite, consider first following along with the ensuing creation of our own suite, as it will serve to introduce several concepts demonstrated in the PlayerSpec.js
suite.
Begin by creating a file named Play2Spec.js
, saving it to the spec/javascripts
directory. Add the following contents to this file:
describe("Play2", function() {
it('Hello world test passes', function() {
expect(true).toBe(true);
});
});
Save the file and refresh the browser. You'll see that the Play2
suite has been added to the list of running specs (Figure 3).
Click here for larger image
Figure 3. Running Multiple Test Suites
So what does this spec accomplish? The spec starts by defining the expected behavior in plain English. In our case, we expect the hello world spec to pass. In order to test the behavior, the it
method accepts a callback which defines the expectation. We are simply expecting the value true
to be true
.
it('Hello world test passes', function() {
expect(true).toBe(true);
});
Change one of the compared values to false
and refresh the browser. You'll see that the spec fails, as depicted in Figure 4.
Click here for larger image
Figure 4. Viewing a Failed Spec
So far, so good. Let's revise the Play2
spec to put the Player
class through the ringer.