Eric Hartford
Eric Hartford

Reputation: 17962

mocha as a library

I would like to use mocha (the node.js test framework, not the ruby mocking library) as a library, rather than using the mocha executable to run my test.

Is it possible to run a mocha test this way? The examples all just call mocha libraries assuming they are already "require'd", and the mocha executable does all the "require-ing" ahead of time, but I would really prefer to do them explicitly in my script so that I can simply set +x on my script and call it directly.

Can I do something like this?

#!/usr/bin/env coffee
mocha = require 'mocha'
test = mocha.Test
suite = mocha.Suite
assert = require("chai").assert

thing = null

suite "Logging", () ->
  setup (done) ->
    thing = new Thing()
    done()
  test "the thing does a thing.", (done) ->
    thing.doThing () ->
      assert.equal thing.numThingsDone, 1
      done()
  teardown (done) ->
    thing = null
    done()

Upvotes: 7

Views: 3457

Answers (3)

crishushu
crishushu

Reputation: 565

The following snippet allows you to control programmatically Mocha main features outside of Node, like adding suites and run suites in different steps. The crucial point was finding out how to make mocha interfaces globally accessible (the code is also available as a gist)

var Mocha = require("mocha");
var mocha = new Mocha();
var _suites = [];
var _done = false;

/**
 * default mocha options
 * for other configurations, check out bin/_mocha
 */
mocha.reporter("nyan");
mocha.useColors(true);
mocha.growl();

module.exports = {
    /**
     * set interface (bdd is default) and make it global to node
     * @param  {string} interface bdd|tdd|exports|qunit
     */
    init: function(interface) {
        interface && mocha.ui(interface);
        mocha.suite.emit('pre-require', global, undefined, mocha);
    },
    /**
     * add suite
     * @param {function} suite to be executed later
     */
    add: function(suite) {
        mocha.suite && _suites.push(suite) && suite();
    },
    /**
     * run added suites
     */
    run: function(cb) {
        console.info('run mocha');

        var done = function () {
            _done = true;
            cb && cb();
            process.on('exit', function() {
                console.info("exit mocha");
                process.exit(1);
            });
        };

        mocha.run(done);
    },
    /**
     * end mocha test
     */
    exit: function() {
        if (_done) {
            process.exit();
        } else {
            var start = new Date().getTime(),
            interval = setInterval(function() {
                if (_done) {
                    console.log("test suites finished");
                    clearInterval(interval);
                    process.exit();
                } else if (new Date().getTime() - start > 5000) {
                    console.log("wait for nothing!");
                    clearInterval(interval);
                    process.exit();
                }
            }, 250);
        }
    },
    /**
     * change mocha options at runtime, e.g., "reporter", "nyan"
     */
    _set: function(key, val){
        mocha[property](val);
    }
};

Upvotes: 0

Eric Hartford
Eric Hartford

Reputation: 17962

This feature has since been added. I include an example below.

I got information from here:

You will need 2 files. One test, and one to run the test. You can mark runTest as executable, and set its output in the mocha options.

runTest.js

#!/usr/bin/env node

var Mocha = require('mocha'),
    fs    = require('fs'),
    path  = require('path');

var mocha = new Mocha(
{
  ui: 'tdd'     
});

mocha.addFile(
  path.join(__dirname, 'test.js')
);

mocha.run(function(failures){
  process.on('exit', function () {
    process.exit(failures);
  });
});

test.js

var assert = require('chai').assert

suite('Array', function(){
  setup(function(){});
  suite('#indexOf()', function(){
    test('should return -1 when not present', function(){
      assert.equal(-1, [1,2,3].indexOf(4));
    });
  });
});

Upvotes: 2

Trevor Burnham
Trevor Burnham

Reputation: 77416

It's possible, but certainly not recommended.

Look at the mocha binary's source (specifically bin/_mocha) to get an idea of what it does. In particular, look at the run function. Everything it's using—Runner, Reporter, etc.—is exported by the mocha library, so there's nothing stopping you from reverse-engineering it.

Upvotes: 3

Related Questions