How to set up an environment with unit testing tools (Mocha & Karma) and E2E testing tools (Nightwatch & Selenium)
This guide shows you the basics to create an environment where you can test your code with the following tools:
-
Global tools:
- Gulp, a toolkit that help you automate painful tasks
-
Unit testing tools:
- Mocha, a test framework with sopport for BDD and TDD
- Chai for assertion types than can be used with Mocha
- Sinon.JS for test spies, stubs and mocks
- Karma, a test runner. A js command line tool to spawn a web server which loads your app source code and executes your test
- PhamtomJS, a Webkit scriptable, headless browser used for automating web page interaction
- Istambul, a js code coverage tool that computes statement line, functions and branchs
-
E2E (End to End) testing tools:
- Nightwatch.js, a solution to write E2E tests in Node.js quickly and effortlessly that run against a Selenium server
- Selenium to automate browsers. It is composed of:
- Selenium Server needed in order to run Selenium WebDriver
- Selenium WebDriver for driving a browser natively as a user would using the Selenium Server
$ npm install -g gulp
$ npm install
The command above will install the next devDependencies from package.json file among the others:
- karma-chrome-launcher, a plugin launcher for Chrome browser
- karma-phantomjs-launcher, a plugin launcher for PhamtonJS browser
- karma-coverage, a plugin to generate coverage using Istanbul
- karma-mocha, a adapter for Mocha testing framework
- karma-mocha-reporter, a plugin to report with mocha style logging
- gulp-nightwatch, a gulp plugin for Nightwatch.js
The rest of tools in package.json are for gulp tasks like create web server, livereloading, open browser... or a promises polyfill, etc.
This will run the app on port 8080
$ gulp serve
$ gulp specs
-
Create a folder for install Selenium Server and the ChromeDriver in your project, e.g.: bin/selenium and bin/chromedriver
$ mkdir -p ./bin/selenium $ mkdir ./bin/chromedriver -
Install Selenium Server. Download the latest version of selenium-server-standalone-{VERSION}.jar file from the Selenium downloads page and place it on bin/selenium folder
-
Install ChromeDriver. Download the latest version of WebDriver if you want to run the e2e test under Chrome browser environment (You must have installed Chrome browser as well) and place it on bin/chromedriver folder
-
Running the e2e tests
$ gulp e2e
Mocha is a test framework running on Node.js and in the browser. If you would like to try Mocha in Node.js:
$ npm install -g mocha
$ npm install chai
$ mkdir test
$ $EDITOR test/test.js
var assert = require('chai').assert;
describe('Array', function() {
describe('#indexOf()', function () {
it('should return -1 when the value is not present', function () {
assert.equal(-1, [1,2,3].indexOf(5));
assert.equal(-1, [1,2,3].indexOf(0));
});
});
});$ mocha
.
✔ 1 test complete (1ms)
Mocha's interfaces system allows developers to choose their style. Mocha has BDD and TDD among other interfaces
-
The BDD interface provides describe(), context(), it(), before(), after(), beforeEach() and afterEach()
describe('', function() { before(function() { // }); describe('', function() { it('', function() { // }) }); after(function() { // }) });
-
The TDD interface provides suite(), test(), suiteSetup(), suiteTeardown(), setup() and teardown():
suite('', function() { setup(function() { // }); suite('', function() { test('', function() { // }) }); teardown(function() { // }) });
Mocha allows you to use any library you want. We use Chai since allows you expect(), assert() and should() style assertions. Chai has several interfaces that allow the developer to choose the most confortable. The chain-capable BDD styles provide an expressive language & readable style, while the TDD assert style provides a more classical feel.
-
chai.should(); foo.should.be.a('string'); foo.should.equal('bar'); foo.should.have.length(3); tea.should.have.property('flavors') .with.length(3);
-
var expect = chai.expect; expect(foo).to.be.a('string'); expect(foo).to.equal('bar'); expect(foo).to.have.length(3); expect(tea).to.have.property('flavors') .with.length(3);
-
var assert = chai.assert; assert.typeOf(foo, 'string'); assert.equal(foo, 'bar'); assert.lengthOf(foo, 3) assert.property(tea, 'flavors'); assert.lengthOf(tea.flavors, 3);
Sinon.JS is a really helpfull library when you want to unit test your code. It has browser support and also can run on the server using Node.js
-
A spy is a function that records arguments, return value, the value of this and exception thrown for all its calls. It can be an anonymous function or it can wrap an existing function
-
A stub is also a spy but it is also a functions that has some predefinied behabiour. It is used when you want to fake some functionality
-
A mock is like a stub and a spy but with a slight twist. With a mock you define up front all the things you want to expect, then when you are all done with your tests you assert that all those things happened as planned
- Spec is the default reporter. The spec reporter outputs a hierarchical view nested just as the test cases are
- Dot is simply a series of dots that represent test cases, failures highlight in red, pending in blue, slow as yellow. Good if you would like minimal output
Mocha has browser support and it is able to run the test in a browser environment instead of Node.js environment. A typical setup might look something like the following, where we call mocha.setup('bdd') to use the BDD interface before loading the test scripts, running them with mocha.run()
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link href="../node_modules/mocha/mocha.css" rel="stylesheet" />
</head>
<body>
<div id="mocha"></div>
<script src="../node_modules/mocha/mocha.js"></script>
<script src="../node_modules/chai/chai.js"></script>
<script src="../node_modules/sinon/pkg/sinon.js"></script>
<script>
mocha.setup({
ui: 'bdd'
});
</script>
<script src="../src/math.js"></script>
<script src="../src/app.js"></script>
<script src="app.spec.js"></script>
<script>
mocha.run();
</script>
</body>
</html>## 6. Karma
Karma runs on Node.js and is available as an NPM package. The main goal for Karma is to bring a productive testing environment to developers where they don't have to set up loads of configurations. Karma is essentially a tool which spawns a web server that executes source code against test code for each of the browsers connected. The results for each test against each browser are examined and displayed via the command line to the developer such that they can see which browsers and tests passed or failed.
The recommended approach is to install karma locally in the project's directory
# Install Karma
$ npm install karma --save-dev
In order to serve you well, Karma needs to know about your project in order to test it and this is done via a configuration file (karma.conf.js) If you install Karma globally, the easiest way to generate an initial configuration file is by using the karma init command
$ npm install -g karma-cli
$ karma init
Note: Check out karma.conf.js file in this project, for more information about its configure (testing framework, reporters, browsers...)
Karma can be easily extended through plugins. In fact, all the existing preprocessors, reporters, browser launchers and frameworks are plugins
Main plugin needed:
- karma-mocha is an adapter for Mocha testing framework
- karma-chrome-launcher is a launcher for Chrome browser
- karma-phantom-launcher is a launcher for PhantomJS browser
- karma-mocha-reporter is Karma reporter with mocha style logging
- karma-coverage generate code coverage using Istambul
PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG. One major use case of PhantomJS is headless testing of web applications. It is suitable for general command-line based testing and as part of a continuous integration system.
To install PhantomJS via NPM use phantomjs-prebuilt. What this installer is really doing is just grabbing a particular "blessed" (by this module) version of Phantom
Istambum is a JS code coverage tool that computes statement, line, function and branch coverage with module loader hooks to transparently add coverage when running tests. Supports all JS coverage use cases including unit tests, server side functional tests and browser tests.
The easiest way is to install karma-coverage as a devDependency, by running
$ npm install --save-dev karma-coverage
To know how configure Istambul through karma.conf.js file take a look at the following attributes
// karma.conf.js
module.exports = function(config) {
config.set({
files: [
'src/**/*.js',
'test/**/*.js'
],
// coverage reporter generates the coverage
reporters: ['progress', 'coverage'],
preprocessors: {
// source files, that you wanna generate coverage for
// do not include tests or libraries
// (these files will be instrumented by Istanbul)
'src/**/*.js': ['coverage']
},
// optionally, configure the reporter
coverageReporter: {
type : 'html',
dir : 'coverage/'
}
});
};To launch the unit tests through a gulp task, just create a new Karma Server with its configuration file and start it
var Server = require('karma').Server;
gulp.task('specs', function(done) {
new Server({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, done).start();
});Selenium is a very popular set of tools for browser automation. It is composed of several main projects like Selenium WebDriver, among others. Nightwatch uses de WebDriver to perform the browser automation related tasks
The Selenium Server runs separately on the machine with the browser you want to test. You will need to have the Java Development Kit (JDK) installed, minimum required version is 7. You can check this by running java -version from the command line. Download the latest version of selenium-server-standalone-{VERSION}.jar file from the Selenium downloads page and place it on the computer with the browser you want to test
If the server is on the same machine where Nightwatch is running, it can be started/stopped directly by the Nightwatch
$ java -jar selenium-server-standalone-{VERSION}.jar
Nightwatch is an easy to use Node.js based E2E testing solution. It uses Selenium WebDriver API to perform commands and assertions on DOM elements. It works by sending HTTP requests to the Selenium server with the right parameters and interpreting the response. If you would like to try Nightwatch in Node.js:
$ npm install -g nightwatch
Nightwatch expects a configuration file to be passed, using by default a nightwatch.json file in the project's root folder. Note: Check out nightwatch.json file in this project or Nightwatch Web Page for more information about its configure
Some of the most important:
- src_folders
- selenium.start_process
- selenium.server_path
- selenium.cli_args.webdriver.chromedriver
- test_runner
- test_settings.default
selenium-server-standalone-{VERSION}.jar includes the WebDriver for some browsers like Firefox. But if you want to run the tests using Chrome browser you have to download the ChromeDriver binary and specify it's location in nightwath.json Also don't forget to specify chrome as the browser name in the desiredCapabilities property.
Create a separate folder for tests in your project, e.g.: E2E. Each file inside it will be loaded as a test by the Nightwatch test runner. A basic test will look like this:
module.exports = {
'Demo test Google' : function (browser) {
browser
.url('http://www.google.com')
.waitForElementVisible('body', 1000)
.setValue('input[type=text]', 'nightwatch')
.waitForElementVisible('button[name=btnG]', 1000)
.click('button[name=btnG]')
.pause(1000)
.assert.containsText('#main', 'Night Watch')
.end();
}
};-
Run the app. It's posible to use gulp connect if you don't want the browser to open
$ gulp serve -
Launch selenium server and E2E test in a chrome environment instead of firefox default environment
$ nightwatch --env chrome_env . Starting selenium server... started - PID: 18806 Demo E2E ✓ Demo test Google (320ms) 1 passing (4s)
Nightwatch is bundled with a custom version of the popular Mocha test runner which allows running tests using Mocha, thus taking advantage of its interfaces and reporters. This is done by specifying the "test_runner" option in the nightwatch.json configuration file.
{
...
"test_runner" : "mocha"
...
}{
...
"test_runner" : {
"type" : "mocha",
"options" : {
"ui" : "tdd",
"reporter" : "list"
}
}
...
}describe('Google demo test for Mocha', function() {
before(function(client, done) {
done();
});
after(function(client, done) {
client.end(function() {
done();
});
});
it('uses BDD to run the Google simple test', function(client) {
client
.url('http://google.com')
.expect.element('body').to.be.present.before(1000);
client.setValue('input[type=text]', ['nightwatch', client.Keys.ENTER])
.pause(1000)
.assert.containsText('#main', 'Night Watch');
});
});Running the E2E tests through a gulp task (in chrome_env enviroment)
var nightwatch = require('gulp-nightwatch');
gulp.task('e2e', function() {
connect.server({
root: '.',
port: 8081,
livereload: false
});
return gulp.src('')
.pipe(nightwatch({
configFile: 'nightwatch.json',
cliArgs: ['--env chrome_env']}));
});

