OdeToCode IC Logo

Karma Is Not Just For AngularJS

Tuesday, August 19, 2014

The AngularJS team created Karma, but Karma isn’t tied to AngularJS. As a test runner, I can use Karma to run tests against any JavaScript code using a variety of testing frameworks in a variety of browsers. All I need is Node.js.

Pretend I am writing code to represent a point in two dimensional space. I might create a file point.js.

var Point = function(x,y) {
    this.x = x;
    this.y = y;
}

I’ll test the code using specifications in a file named pointSpecs.js.

describe("a point", function() {
    it("initializes with x and y", function() {
        var p1 = new Point(3,5);
        
        expect(p1.x).toBe(3);
        expect(p1.y).toBe(5);
    });
});

What Karma can do is:

- Provide web browsers with all of the HTML and JavaScript required to run the tests I’ve written.

- Automate web browsers to execute all the tests

- Tell me if the tests are passing or failing

- Monitor the file system to re-execute tests whenever a file changes.

Setup

The first step is using npm to install the Karma command line interface globally, so I can run Karma from anywhere.

npm install karma-cli –g

Then I can install Karma locally in the root of my project where the Point code resides.

npm install karma --save-dev

Karma requires a configuration file so it knows what browsers to automate, and which files I’ve authored that I need Karma to load into the browser. The easiest way to create a basic configuration file is to run karma init from the command line. The init command will walk you through a series of questions to create the karma.conf.js file. Here is a sample session.

>karma init 

Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> jasmine 

Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no 

Do you want to capture any browsers automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> PhantomJS
> Chrome
> 

What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.
> js/**/*.js
> specs/**/*.js
> 

Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.
> 

Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes 

Config file generated at "C:\temp\testjs\karma.conf.js".

I can open the config file to tweak settings and maintain the configuration in the future. The code is simple.

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine'],
    files: [
      'js/**/*.js',
      'specs/**/*.js'
    ],
    exclude: [
    ],
    preprocessors: {
    },
    reporters: ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['PhantomJS', 'Chrome'],
    singleRun: false
  });
};

Note that when I enter the location of the source and test files, I want to enter the location of the source files first. It’s helpful if you can organize source and test files into a directory structure so you can use globbing (**) patterns, but sometimes you need to explicitly name individual files to control the order of loading.

At this point I can start Karma, and the tests will execute in two browsers (Chrome, which I can see, and PhantomJS, which is headless). I’d probably tweak the config file to only use Phantom in the future.

Karma in action!

Now, Karma will continuously run tests in the background while I work.

Easy!