RethinkDB and BDD on CI

How to unit test Node applications that use RethinkDB.

I like RethinkDB for its simplicity, API and local admin tool. Recently I wanted to unit test NodeJS code that interfaces with a RethinkDB on a continuous build server. I love using TravisCI, Codeship and CircleCI and consider well tested code a prerequisite to a solid application. Here is how to install and run the database while executing BDD tests (in my case using Mocha).

Install RethinkDB

To install RethinkDB on CircleCI instance I added the following config file

cirle.yml
1
2
3
4
5
6
dependencies:
pre:
- source /etc/lsb-release && echo "deb http://download.rethinkdb.com/apt $DISTRIB_CODENAME main" | sudo tee /etc/apt/sources.list.d/rethinkdb.list
- wget -qO- http://download.rethinkdb.com/apt/pubkey.gpg | sudo apt-key add -
- sudo apt-get update
- sudo apt-get install rethinkdb=1.16\*

This will install the latest available 1.16 version of the database. If you want to install the 2.x version instead use sudo apt-get install rethinkdb=2.\* command.

Unit tests

To start RethinkDB process I wrote the following helper js code

start-rethinkdb.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var spawn = require('child_process').spawn;
// returns function to kill the spawned rethinkdb
module.exports = function startRethinkDb(cwd) {
var options = {};
if (cwd) {
options.cwd = cwd;
}
var rethinkdb = spawn('rethinkdb', options);
rethinkdb.stdout.setEncoding('utf8');
rethinkdb.stdout.on('data', function (txt) {
process.stdout.write('rethinkdb: ' + txt);
});
rethinkdb.stderr.setEncoding('utf8');
rethinkdb.stderr.on('data', function (txt) {
process.stderr.write('rethinkdb error: ' + txt);
});
return function killRethinkDb() {
console.log('stopping rethinkdb');
rethinkdb.kill('SIGKILL');
};
};

The above function returns another function that can kill the started database process.

To start the DB before running the unit tests I call startRethinkDB inside the Gulpfile.js.

Gulpfile.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var startRethinkDb = require('./start-rethinkdb');
gulp.task('mocha', function (done) {
var stopDb = startRethinkDb();
console.log('sleeping after starting rethinkdb before starting tests');
var delay = 7500;
setTimeout(function () {
// Run Mocha tests
gulp.src(specs, {read: false})
.pipe(mocha({
reporter: 'spec',
ui: 'bdd'
}))
.on('end', function () {
console.log('mocha tests finished');
setTimeout(function () {
stopDb();
done();
}, delay);
});
}, delay);
});

There is a short timeout to let db to come up, then another short delay after the tests are finished to close all open DB connections.

The CI is now happy and runs the tests against the database. Just remember that any local DB data persists unless you delete the saved database folder.