(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'); } });