Overview
This tutorial walks through the steps need to configure Karma to work with a Maven web project. It will also be used as a base for my future Karma related posts.
Install Node.js
First, download Node.js from http://nodejs.org/download/ and install it. Once installed, we should be able to invoke npm
command from the command line, for example:-
npm -version
Create package.json
Let’s assume we have the following Maven project:-
testKarma
βββ pom.xml
βββ src
βΒ Β βββ main
βΒ Β βΒ Β βββ java
βΒ Β βΒ Β βββ resources
βΒ Β βΒ Β βββ webapp
βΒ Β βββ test
βΒ Β βββ java
βββ testKarma.iml
Please ignore testKarma.iml
, which is an IntelliJ specific file.
Create a file called package.json
under project root directory…
testKarma
βββ package.json
βββ pom.xml
βββ src
βΒ Β βββ main
βΒ Β βΒ Β βββ java
βΒ Β βΒ Β βββ resources
βΒ Β βΒ Β βββ webapp
βΒ Β βββ test
βΒ Β βββ java
βββ testKarma.iml
… with the following content…
{
"name": "testKarma",
"private": true
}
In this case, we created a private repository by setting private
to true
.
Without this flag set, when you run npm install ...
, we will get these annoying warnings:-
npm WARN package.json testKarma@ No description
npm WARN package.json testKarma@ No repository field.
npm WARN package.json testKarma@ No README data
Install Karma and Plugins
From the project root directory, run the following command:-
npm install karma karma-jasmine@0.2.2 karma-chrome-launcher karma-phantomjs-launcher karma-junit-reporter karma-coverage --save-dev
At the time of this post, by default, karma-jasmine
will install version 0.1.5. So, we will manually specify the latest version that allows us to use Jasmine 2.x.
For local testing, we will run our tests against both Chrome browser and PhantomJS, which is a headless browser. So, make sure Chrome browser is already installed.
The project structure now contains the installed plugins for JavaScript testing:-
testKarma
βββ node_modules
βΒ Β βββ karma
βΒ Β βββ karma-chrome-launcher
βΒ Β βββ karma-coverage
βΒ Β βββ karma-jasmine
βΒ Β βββ karma-junit-reporter
βΒ Β βββ karma-phantomjs-launcher
βββ package.json
βββ pom.xml
βββ src
βΒ Β βββ main
βΒ Β βββ test
βββ testKarma.iml
The package.json
contains a history of the plugins we installed within this project:-
{
"name": "testKarma",
"private": true,
"devDependencies": {
"karma": "^0.12.24",
"karma-chrome-launcher": "^0.1.5",
"karma-coverage": "^0.2.6",
"karma-jasmine": "^0.2.2",
"karma-junit-reporter": "^0.2.2",
"karma-phantomjs-launcher": "^0.1.4"
}
}
A couple of important notes:-
- Basically, since we are not running
npm install
with -g
option, the plugins will not be installed globally. Rather, they are installed within the project root directory.
- Using
--save-dev
option, if package.json
exists, this file will be automatically updated to keep track of the installed plugins and versions.
- If we decided to update the plugin versions, we just need to modify this file and run
npm install
to update them.
- We do not want to commit
node_modules
directory into any VCS because there are at least 5000 files in this directory. So, remember to configure a VCS exclusion on this directory (see IntelliJ: Handling SVN Global Ignore List).
- When other peers check out this project from VCS, they will run
npm install
, which will automatically install all the dependencies listed in package.json
.
Create Karma Configuration File
Instead of running karma init karma.conf.js
to step through the process to create a configuration file, we will manually create two Karma configuration files under src/test/resources
directory.
testKarma
βββ node_modules
βββ package.json
βββ pom.xml
βββ src
βΒ Β βββ main
βΒ Β βΒ Β βββ java
βΒ Β βΒ Β βββ resources
βΒ Β βΒ Β βββ webapp
βΒ Β βββ test
βΒ Β βββ java
βΒ Β βββ resources
βΒ Β βββ karma.conf.js
βΒ Β βββ karma.jenkins.conf.js
karma.conf.js
This configuration is used for local testing.
module.exports = function ( config ) {
config.set( {
basePath : '../../../',
frameworks : ['jasmine'],
files : [
'src/main/webapp/resources/js/**/*.js',
'src/test/js/**/*.js'
],
exclude : [],
preprocessors : {
'src/main/webapp/resources/js/**/*.js' : ['coverage']
},
reporters : ['progress', 'coverage'],
port : 9876,
colors : true,
logLevel : config.LOG_INFO,
autoWatch : true,
browsers : ['Chrome', 'PhantomJS'],
singleRun : false,
plugins : [
'karma-jasmine',
'karma-chrome-launcher',
'karma-phantomjs-launcher',
'karma-junit-reporter',
'karma-coverage'
],
coverageReporter : {
type : 'html',
dir : 'target/coverage/'
}
} );
};
karma.jenkins.conf.js
This configuration is used for automated testing on Jenkins.
module.exports = function ( config ) {
config.set( {
basePath : '../../../',
frameworks : ['jasmine'],
files : [
'src/main/webapp/resources/js/**/*.js',
'src/test/js/**/*.js'
],
exclude : [],
preprocessors : {
'src/main/webapp/resources/js/**/*.js' : ['coverage']
},
// added `junit`
reporters : ['progress', 'junit', 'coverage'],
port : 9876,
colors : true,
logLevel : config.LOG_INFO,
// don't watch for file change
autoWatch : false,
// only runs on headless browser
browsers : ['PhantomJS'],
// just run one time
singleRun : true,
// remove `karma-chrome-launcher` because we will be running on headless
// browser on Jenkins
plugins : [
'karma-jasmine',
'karma-phantomjs-launcher',
'karma-junit-reporter',
'karma-coverage'
],
// changes type to `cobertura`
coverageReporter : {
type : 'cobertura',
dir : 'target/coverage-reports/'
},
// saves report at `target/surefire-reports/TEST-*.xml` because Jenkins
// looks for this location and file prefix by default.
junitReporter : {
outputFile : 'target/surefire-reports/TEST-karma-results.xml'
}
} );
};
Write JS Production Code and Test Code
Now, it’s time to write some tests and run them.
testKarma
βββ node_modules
βββ package.json
βββ pom.xml
βββ src
βΒ Β βββ main
βΒ Β βΒ Β βββ java
βΒ Β βΒ Β βββ resources
βΒ Β βΒ Β βββ webapp
βΒ Β βΒ Β βββ resources
βΒ Β βΒ Β βββ js
βΒ Β βΒ Β βββ hello.js
βΒ Β βββ test
βΒ Β βββ java
βΒ Β βββ js
βΒ Β βΒ Β βββ hello-spec.js
βΒ Β βββ resources
βΒ Β βββ karma.conf.js
βΒ Β βββ karma.jenkins.conf.js
βββ testKarma.iml
hello.js
We will keep our production code to the minimum in this example:-
var hello = {
speak : function () {
return 'Hello!';
}
};
hello-spec.js
A very simple test case:-
describe( 'hello module', function () {
'use strict';
it( 'speak()', function () {
expect( hello.speak() ).toBe( 'Hello!' );
} );
} );
Run Karma using karma.conf.js
From the project root directory, run Karma:-
node_modules/karma/bin/karma start src/test/resources/karma.conf.js
The console should now look like this:-
INFO [karma]: Karma v0.12.24 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.8 (Mac OS X)]: Connected on socket YNMziWTsyeaf6DZzw06D with id 3320523
INFO [Chrome 38.0.2125 (Mac OS X 10.9.5)]: Connected on socket rYQeni1xm1bbqfa3w06E with id 50259203
PhantomJS 1.9.8 (Mac OS X): Executed 1 of 1 SUCCESS (0.003 secs / 0.001 secs)
Chrome 38.0.2125 (Mac OS X 10.9.5): Executed 1 of 1 SUCCESS (0.008 secs / 0.001 secs)
TOTAL: 2 SUCCESS
The target/coverage
directory should contain Chrome and PhantomJS subdirectories.
testKarma
βββ node_modules
βββ package.json
βββ pom.xml
βββ src
βββ target
βΒ Β βββ coverage
βΒ Β βββ Chrome 38.0.2125 (Mac OS X 10.9.5)
βΒ Β βΒ Β βββ index.html
βΒ Β βΒ Β βββ js
βΒ Β βΒ Β βΒ Β βββ hello.js.html
βΒ Β βΒ Β βΒ Β βββ index.html
βΒ Β βΒ Β βββ prettify.css
βΒ Β βΒ Β βββ prettify.js
βΒ Β βββ PhantomJS 1.9.8 (Mac OS X)
βΒ Β βββ index.html
βΒ Β βββ js
βΒ Β βΒ Β βββ hello.js.html
βΒ Β βΒ Β βββ index.html
βΒ Β βββ prettify.css
βΒ Β βββ prettify.js
βββ testKarma.iml
When opening one of the index.html
files, we should see the coverage report.

Run Karma using karma.jenkins.conf.js
Although we will only use karma.jenkins.conf.js
for automated testing on Jenkins, we will run this configuration file to see the generated output differences.
Clean the target
directory:-
mvn clean
Run Karma with karma.jenkins.conf.js
instead:-
node_modules/karma/bin/karma start src/test/resources/karma.jenkins.conf.js
Since this configuration only runs on the headless browser, we will not see Chrome results here:-
INFO [karma]: Karma v0.12.24 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.8 (Mac OS X)]: Connected on socket SM_5sy2wzHdL4ru9yg0X with id 42922522
PhantomJS 1.9.8 (Mac OS X): Executed 1 of 1 SUCCESS (0.002 secs / 0.001 secs)
The target
directory should contain cobertura-coverage.xml
for coverage result and TEST-karma-results.xml
for test result.
testKarma
βββ node_modules
βββ package.json
βββ pom.xml
βββ src
βββ target
βΒ Β βββ coverage-reports
βΒ Β βΒ Β βββ PhantomJS 1.9.8 (Mac OS X)
βΒ Β βΒ Β βββ cobertura-coverage.xml
βΒ Β βββ surefire-reports
βΒ Β βββ TEST-karma-results.xml
βββ testKarma.iml