(sometimes done in the reverse order)
package.json:
{ "name": "test-program", ... "scripts": { "test": "mocha" } "devDependencies": { "mocha": "~2.3.3" } }
Some options for directory structure:
test/test-index.js test-index.js
describe('User', function() { it('should save without error', function(done) { var user = new User('Luna'); user.save(function(err) { if (err) throw err; user.delete(); done(); }); }); it('should save without error', function(done) { // ... }); }); describe('Group', function() { it('should save without error', function(done) { // .. }); it('accepts user additions', function(done) { // .. }); });
User ✓ should save without error ✓ can log in Group ✓ should save without error ✓ accepts user additions 4 passing (10ms)
User 1) should save without error ✓ can log in Group ✓ should save without error ✓ accepts user additions 3 passing (11ms) 1 failing 1) User should save without error: Error: Database full at Object.User.save (user.js:5:10) at Context.(test-user.js:16:10)
describe('User', function() { beforeEach(function(done) { var user = new User('Luna'); }); it('should save without error', function(done) { user.save(function(err) { if (err) throw err; user.delete(); done(); }); }); it('should change name without error', function(done) { user.newName("Sol", function(err) { if (err) throw err; user.delete(); done(); }); }); });
describe('User', function() { beforeEach(function(done) { var user = new User('Luna'); }); afterEach(function(done) { user.delete(); }); it('should save without error', function(done) { user.save(function(err) { if (err) throw err; done(); }); }); it('should change name without error', function(done) { user.newName("Sol", function(err) { if (err) throw err; done(); }); }); });
describe('User', function() { beforeEach(function(done) { var user = new User('Luna'); }); afterEach(function(done) { user.delete(); }); it('should save without error', function(done) { user.save(done); }); it('should change name without error', function(done) { user.newName("Sol", done); }); });
assert(myString == "ok")
myString.should.equal('ok');
expect(myString).to.be('ok')
assert.equal(myString, 'ok');
myString.should.equal('ok'); expect(myString).to.equal('ok'); assert.equal(myString, 'ok');
describe("RhythmGuard", () => { it("can lookup", done => { rhythmguard.lookup({ip: "127.0.0.1", checkset: "testSet"}, (err, result, extras) => { expect(err).to.not.exist; expect(result).to.be.true; expect(extras).to.deep.equal({ "ip": { result: true, lists: ["nonroutable"] } }); done(); }); }); });
expect(parseInt(matches[1])).to.be.at.least(loadCutoff); expect(finalizer.commit).to.be.a('Function'); expect(data[0]).to.match(/^Your new bucket is [0-9a-zA-Z]{20}$/) expect(objs).to.have.members(["wazoo", "woohoo", "StaggeringlyLessEfficient"]) expect(data).to.be.empty
(there's really nothing else worth bothering with)
function duckCount(db) { var values = db.query("SELECT COUNT(*) FROM DUCKS"); return values[0]; } // ... it("gives the expected number of ducks", done => { var stub = sinon.stub().returns(42); var result = duckCount(stub); expect(result).to.equal(42); done(); });
// count.js var db = require('db'); function duckCount() { var values = db.query("SELECT COUNT(*) FROM DUCKS"); return values[0]; } // test-count.js var count = require('./count'); var db = require('db'); it("gives the expected number of ducks", done => { sinon.stub(db, 'query', () => { return 28 }); var result = duckCount() expect(result).to.equal(28); done(); });
var sinon = require('sinon'), redis = require('redis'), fakeredis = require('fakeredis'); sinon.stub(redis, 'createClient', fakeredis.createClient);
mockFs({ 'path/to/fake/dir': { 'some-file.txt': 'file content here', 'empty-dir': {/** empty directory */} }, 'path/to/some.png': new Buffer([8, 6, 7, 5, 3, 0, 9]), 'some/other/path': {/** another empty directory */} });
sinon.stub(fs, 'open', (path, flags, mode, callback) => { callback(new Error("Open failed!")); });
// blocklist.js class Blocklist extends BaseCheck { constructor(checkset_name) { // ... } prepareChecksetConfig(config, callback) { // ... } run(msg, callback) { // ... } }
// test-blocklist.js describe("Blocklist check", () => { before( done => { var BL = new block_list(); }); it("prepares its config", cb => { BL.prepareChecksetConfig(null, (error, finalizer) => { // ... }); )}; it("run does the right thing", cb => { BL.run({"page": "http://www.cnn.com"}, (error, result) => { // ... }); )}; });
class RhythmGuard extends EventEmitter { constructor() { // .. } init(config, callback) { if (cluster.isMaster) { process.on('SIGHUP', () => { async.forEachOf(cluster.workers, (obj, id) => { cluster.workers[id].send("reload"); }); }); } else { process.on('message', msg => { if (msg === "reload") // ... } } }) }
describe("Clustering", () => { it("reloads children on HUP", done => { // Fire up a cluster child = child_process.fork("sample-server.js", [workerCount]); process.kill(child.pid, 'SIGHUP'); } });