Karma Test Runner with QUnit in 10 Minutes

This is a ten minute primer for using Karma and QUnit to unit test JavaScript.

Getting ready

Install Karma[1], plugins, and Qunit[2].

# Install Karma
npm install karma --save-dev
# Install plugins
npm install karma-qunit karma-phantomjs-launcher --save-dev
# Add global CLI
npm install -g karma-cli
# Install QUnit
npm install --save-dev qunitjs

How do it…

In your project directory, run the Karma initialization script:

karma init karma.conf.js

Answer the following questions[3]:

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

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.
> yes or 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
>

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.
> src/js/**/*.js
> test/js/**/*.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.
> no

This will create the karma.conf.js configuration file for your project. To run your tests:

karma start

Put your code under the ./src/js/... directory:

src/js/core/class.js
src/js/core/input.js
src/js/core/game.js
src/js/lib/underscore-min.js
…

Put your test code under ./test/js/... directory (I mirror the src directory):

test/js/core/class.js
test/js/core/input.js
test/js/core/game.js
…

Your QUnit tests should looks something like[4]:

QUnit.test('Name of Test', function(assert) {
    // Setup the various states of the code you want to test and assert conditions.
    assert.equal(1, 1, '1 === 1');
    assert.ok(true, 'true is truthy');
    assert.ok(1, '1 is also truthy');
    assert.ok([], 'so is an empty array or object');
});

How it works…

Karma is a configurable test runner for executing any number of testing frameworks (Jasmine is really popular), but I prefer the simplicity of QUnit. It basically creates a web page, including all the files specified in the configuration, JS files followed by testing files. This runs the tests as they would be if including manually in a normal browser.

We have setup the tests to run in the PhantomJS headless browser (but you can run it against your favorite browser by updating the configuration), including all JavaScript files in the directory ./src/js/... and all testing JavaScript files in the directory ./test/js/.... Running karma start will look for a file named karma.conf.js and use it for the test runner, but you can specify another configuration with karma start other.conf.js.

Using requireJS works well with the above inclusion strategy, because the order of files doesn't matter, since each file manages its own dependencies. When not using requireJS, feel free to manually specify each file to include in karma.conf.js; they will be included in the order specified. Modifying karma.conf.js is easy and can be done any time between tests.

QUnit is a straight forward testing framework that allows you to setup conditions and assert them. Combining the two allows for quick and easy automated testing of an entire application.

When tests are setup correctly, running karma start will produce output like:

INFO [karma]: Karma v0.12.30 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.8 (Mac OS X)]: Connected on socket Cxgy5NBaHiEsOOJkawVE with id 16057191
PhantomJS 1.9.8 (Mac OS X): Executed 3 of 3 SUCCESS (0.001 secs / 0.006 secs)

Hopefully, this primer will help you get started testing your application. I have adopted Karma and QUnit for testing my simple Gaming Engine and already improved the code dramatically.

There’s more…

The errors are pretty obvious, but lets explore some common errors.

Import order issues or a file wasn’t included:

PhantomJS 1.9.8 (Mac OS X) ERROR
  ReferenceError: Can't find variable: _
  at /Volumes/UltraDisk/projects/html5-game-engine/src/js/core/asset.js:1

One of the tests fails an assertion:

INFO [karma]: Karma v0.12.30 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.8 (Mac OS X)]: Connected on socket GUH_fUDIuyUgQgO7jYE9 with id 88038210
PhantomJS 1.9.8 (Mac OS X)  Class Test FAILED
	failed, expected argument to be truthy, was: false
	Expected: true
	Actual: false
	    at /Volumes/UltraDisk/projects/html5-game-engine/node_modules/qunitjs/qunit/qunit.js:1314
	    at /Volumes/UltraDisk/projects/html5-game-engine/test/js/core/classTest.js:12
	    at /Volumes/UltraDisk/projects/html5-game-engine/node_modules/qunitjs/qunit/qunit.js:903
	    at /Volumes/UltraDisk/projects/html5-game-engine/node_modules/qunitjs/qunit/qunit.js:1032
	    at process (/Volumes/UltraDisk/projects/html5-game-engine/node_modules/qunitjs/qunit/qunit.js:591)
	    at begin (/Volumes/UltraDisk/projects/html5-game-engine/node_modules/qunitjs/qunit/qunit.js:636)
	    at /Volumes/UltraDisk/projects/html5-game-engine/node_modules/qunitjs/qunit/qunit.js:652

There is an error in karma.conf.js:

INFO [karma]: Karma v0.12.30 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
WARN [watcher]: Pattern "/Volumes/UltraDisk/projects/html5-game-engine/test/js/*^&**/*.js" does not match any file.
INFO [PhantomJS 1.9.8 (Mac OS X)]: Connected on socket 0uCl1Pg_8cbHM90Kjmfz with id 60207047

References

  1. Karma Runner
  2. QUnit
  3. Karma Configuration
  4. QUnit Assertions

Running Android Tests on a Device or Emulator

I have not been doing much web development lately, so its been difficult to come with interesting topics. However, I have been doing a lot of android development and since many engineers have to work cross discipline, I think an android article be relevant. This article will discuss how to run unit tests against your android code, directly on the android device or emulator.

Getting ready

You will need to install the

Using PhantomCSS for Regression Testing Your CSS

I finally had a chance to play with PhantomCSS, a CSS regression testing tool that compares screenshots to see if CSS changes have affected the design, and wanted to share my experience with you. We are using it at Ariba to validate that I do not break any designs as I migrate us from two giant, unmanageable CSS files into smaller, modularize and better written lessCSS files. PhantomCSS uses

Coverage and Mock

This article continues the series on building a continuous deployment environment using Python and Django.

So far we have covered the basics of setting up a Django project and testing it. Today we will discuss how to ensure your tests fully cover the ...

Testing and Django

This article continues last weeks series on building a continuous deployment environment using Python and Django.

Before we discuss testing in Django, lets define what makes up good testing infrastructure. There are many schools of thoughts on testing, but that's another article. Ignoring ...