Back to blog home

Testing Javascript: get started with Jasmine

This article will introduce unit testing, show you how to set up Jasmine, and cover how automation with Karma can streamline your work.

Javascript has come a long way since its humble beginnings of making things underlined when a cursor passes over them. The 'modern' website uses a whole bunch of libraries and tools to provide both snappy UX and connectivity-tolerant usage, allowing both mobile and desktop users far more usability than ever before.

Such a new dependency on sites to elevate Javascript to a first-class citizen in the application comes with a proportional need to test that everything works in all the browsers the audience is using.

Tools like Jasmine have played a big part in Javascript’s maturation, allowing software to be written with greater certainty. Jasmine allows you to define behaviour specifications, or specs for short, for your software and tests to determine whether your software meets your specification.

The whole process is automated, meaning that any tests you write with Jasmine are tests that you no longer have to spend time conducting manually. You can run these tests whenever you like, giving you feedback for the smallest of code changes. The more you automate, the less work you have to do. The more you test, the greater insight you have into changes you make to your code.

Why Jasmine?

Jasmine follows the principles of behaviour-driven development, or BDD for short, which starts with behavioural specifications as the basis for all your tests. If you use user stories in your software development process, behaviour specifications will look familiar to you as they contain natural language definitions of the behaviours you are testing for. Dan North, creator of BDD, has an excellent introductory article, and I recommend it as background reading if this is a new topic for you.

Jasmine’s web-based test runner also makes it a great fit for testing JS written specifically for the web. If you’re considering also writing tests for Node.JS, you might be interested in an alternative JavaScript testing framework such as Mocha.

How Jasmine works?

Jasmine describes behaviours in specs. Specs usually comprise of three functions: describeit and expect.

describe("A spec", function() {
    it("is just a function, so it can contain any code", function() {
        var foo = 0;
        foo += 1;
        expect(foo).toEqual(1);
    });
 
    it("can have more than one expectation", function () {
        var foo = 0;
        foo += 1;
 
        expect(foo).toEqual(1);
        expect(true).toEqual(true);
    });
});

 

The describe function is used to group related tests together. Tests inside each describe block are grouped together when their results are reported. You can also define code to run before each test in a describe block using the beforeEach() function.

The it function defines a test that must be satisfied for it to pass. Both the describe and it functions let you define part of the specification in natural language as the first parameter. Writing specifications in natural language also has the advantage that you can describe the business value of the feature being tested, and good specs should be just as easily read by anyone as the original developer. These specs can derived from your user stories, and will appear in the test results to tell you which specs pass or do not pass.

The expect function is a statement that must evaluate to true for a test to pass, in much the same way that an if statement must evaluate to true for the code inside it is to be executed. Jasmine gives us some helpful methods called matchers (in the above example uses the toEqual() matcher) which test a value in your own code. Jasmine has a range of matchers to suit various kinds of data that you may need to test.

Integrate Jasmine into your project

If you haven't met Yeoman and Bower before, let me introduce you. Bower is a package manager, and automates the installation of JS libraries such as jQuery and Jasmine. Yeoman will set you up with some specs and a specrunner as a good starting point. Both Yeoman and Jasmine are installed using npm, a command-line JavaScript package manager that distributes hundreds of useful Node.JS and frontend tools, so we will get that installed first.

npm is bundled with Node.js's installers. The Node.JS website has installers for Windows and Mac OS. A list of package managers that offer Node.JS can be found here, though you may need to install Nods.JS and npm separately depending on which manager you use. After you’ve finished installing Node.JS and npm, you should be able to use them. To check that npm has installed successfully, you can use the following command on your command-line:

$ npm --version
1.4.28

 

If you see output like the version number above, you should be ready to go. Next, use npm to install Yeoman, Bower and the Jasmine generator:

$ npm install -g yo
$ npm install -g bower
$ npm install -g generator-jasmine

 

The generator instructs Yeoman what it needs to do to set up a working Jasmine environment for you. Navigate to the root of your project directory (in my case, jasmine-demo) and run the Jasmine generator:

$ cd ~/Sites/jasmine-demo/
$ yo jasmine

 

There should now be a directory called test, with a spec runner (index.html) and a directory for specs (spec).

$ ls test/
bower.json      index.html
bower_components    spec

 

If you open index.html in a web browser, you should see the Jasmine spec runner.

 

If you open index.html in an editor, you should see a space below the comment 'include source files here' for you to add your scripts. If your scripts are loaded, your code should be in-scope in your unit tests.

<!doctype html>
<html>
    <head>
        <title>Jasmine Spec Runner</title>
        <link rel="stylesheet" href="bower_components/jasmine/lib/jasmine-core/jasmine.css">
    </head>
    <body>
        <script src="bower_components/jasmine/lib/jasmine-core/jasmine.js"></script>
        <script src="bower_components/jasmine/lib/jasmine-core/jasmine-html.js"></script>
 
        <!-- include source files here... -->
 
        <!-- include spec files here... -->
        <script src="spec/test.js"></script>

 

You can also add more spec files in the space after the comment 'include spec files here'. Now if you open test/spec/test.js, you should be able examine the example specs and start adding your own.

Automate Jasmine

So far we’ve taken a look at Jasmine and seen its web-based test runner. The Jasmine test runner is useful for testing your own code at-a-glance during development, but what if you would like to deploy unit tests to project with a handful of developers, or more? 

Karma is a more sophisticated test runner that automates testing in a range of browsers. It also supports other testing tools such as Mocha and QUnit. Karma can even watch your source files to test them in real-time, and work with continuous integration servers such as Jenkins to help you manage software quality across multiple projects.

Once again Yeoman can help us out by helping us to scaffold Karma inside the project:

$ npm install -g karma
$ npm install -g generator-karma
$ yo karma --test-framework=jasmine

 

You should now have Karma installed and a new configuration file named karma.conf.js. This is used to locate your source code and your spec files so that your tests can be run in a browser. Here’s what it looks like:

// Karma configuration
// http://karma-runner.github.io/0.10/config/configuration-file.html
 
module.exports = function(config) {
  config.set({
    // base path, that will be used to resolve files and exclude
    basePath: '',
 
    // testing framework to use (jasmine/mocha/qunit/...)
    frameworks: ['jasmine'],
 
    // list of files / patterns to load in the browser
    files: [
      'app/bower_components/angular/angular.js',
      'app/bower_components/angular/angular-mocks.js',
      'app/scripts/*.js',
      'app/scripts/**/*.js',
      'test/mock/**/*.js',
      'test/spec/**/*.js'
    ],
 
 
    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,
 
 
    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: ['Chrome'],
 
 
    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: false
  });
};

 

The configuration for Karma is more complex than Jasmine. There are quite a few settings available in its configuration file, I’ve highlighted the three major ones here.

The files array allows you to declare scripts to be loaded by Karma needed for your testing. This means not just loading your source but also your spec files, too. The defaults created by the Karma generator will include the spec files created by the Jasmine generator, and this will also be the case if you use other tools such as the Angular generator.

The autowatch setting tells Karma to watch your files and will re-run your tests whenever changes are saved. This is a useful feature to have running in the corner of a second monitor while you write your code, so that you do not have to interrupt your workflow to run your tests.

The browsers setting tells Karma which browsers to test your code in. As Karma can load and test your code in real browsers, you’ll see the browsers you declare launch when your start. Among the choices available are Chrome, Firefox, Safari and Internet Explorer (you must be running an OS that supports a given browser in order to use it with Karma). PhantomJS is also available as a 'headless' tool that runs your tests without a browser.

If you run the following command in your project root:

$ karma start

 

Karma should start up, launch a new Chrome window, run the example tests created by the Karma generator and wait for changes to be made to your files.

 

The next step is to declare your source code and spec files in the Karma config file and begin testing your own code.

Karma is also very useful for integrating your project into Jenkins. Jenkins is a continuous integration server, software that runs your unit tests on your projects when commit code to version control. It’s particularly useful for organisations that want to view the results of unit tests across many projects. A great example to look at is the Node.JS project’s public Jenkins server. Another great resource is an article by the Karma project on how Karma can be integrated into Jenkins.

Using Jasmine in your own projects

We have covered quite a selection of tools in this article, and you can apply them to your own projects. Jasmine is a useful tool for testing JavaScript code in web browsers. Yeoman and Bower can setup and install Jasmine for you, ready for you to use. Karma is a test runner that runs your Jasmine unit tests from the command-line and makes automated testing easy.

Unit testing frameworks such as Jasmine offer a valuable insight into the quality of the code you write. Not only can you call on it to report on the code you deploy on-demand, but building your code against a spec will make you think harder about what you actually expect your system to do. Many software developers find this insight indispensable after they are introduced to unit testing, and it is no surprise that it is now becoming a very big deal for JavaScript.

Resources

 


 

Image: © Christiaan Colen via Flickr under Creative Commons Attribution-ShareAlike 2.0 Generic