Mocha
Installation
$ npm install -g mocha
Getting Started
$ npm install -g mocha
$ mkdir test
$ $EDITOR test/test.js
Test Program
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
$ mocha
Array
#indexOf()
✓ should return -1 when the value is not present
1 passing (12ms)
chai
- BDD/TDD Assertion library for node.js and the browser.
$ npm install chai
- package.json
"devDependencies": {
"chai": "*",
"mocha": "*"
},
Assertions
- should.js : BDD styler shown throughout these docs
- expect.js : expect() style assertions
- chai : expect(), assert() and should style assertions
- better-assert : c-style self-documenting assert()
- unexpected : the extensible BDD assertion toolkit
Synchronous code
describe('Array', function() {
describe('#indexOf()', function() {
it('should return -1 when the value is not present', function() {
[1,2,3].indexOf(5).should.equal(-1);
[1,2,3].indexOf(0).should.equal(-1);
});
});
});
Asynchronous code
describe('User', function() {
describe('#save()', function() {
it('should save without error', function(done) {
var user = new User('Luna');
user.save(function(err) {
if (err) throw err;
done();
});
});
});
});
Dynamically Generating Tests
var assert = require('chai').assert;
function add() {
return Array.prototype.slice.call(arguments).reduce(function(prev, curr) {
return prev + curr;
}, 0);
}
describe('add()', function() {
var tests = [
{args: [1, 2], expected: 3},
{args: [1, 2, 3], expected: 6},
{args: [1, 2, 3, 4], expected: 10}
];
tests.forEach(function(test) {
it('correctly adds ' + test.args.length + ' args', function() {
var res = add.apply(null, test.args);
assert.equal(res, test.expected);
});
});
});
Result
$ mocha
add()
✓ correctly adds 2 args
✓ correctly adds 3 args
✓ correctly adds 4 args
TDD vs BDD
TDD
- Test driven Development
Test Suite
var assert = require('assert'),
factorial = require('../index');
suite('Test', function (){
setup(function (){
// Create any objects that we might need
});
suite('#factorial()', function (){
test('equals 1 for sets of zero length', function (){
assert.equal(1, factorial(0));
});
test('equals 1 for sets of length one', function (){
assert.equal(1, factorial(1));
});
test('equals 2 for sets of length two', function (){
assert.equal(2, factorial(2));
});
test('equals 6 for sets of length three', function (){
assert.equal(6, factorial(3));
});
});
});
Code
module.exports = function (n) {
if (n < 0) return NaN;
if (n === 0) return 1;
return n * factorial(n - 1);
};
Mocha TDD
- suite(), test(), suiteSetup(), suiteTeardown(), setup(), and teardown()
suite('Array', function() {
setup(function() {
// ...
});
suite('#indexOf()', function() {
test('should return -1 when not present', function() {
assert.equal(-1, [1,2,3].indexOf(4));
});
});
});
Mocha BDD
- describe(), context(), it(), specify(), before(), after(), beforeEach(), and afterEach()
describe('Array', function() {
before(function() {
// ...
});
describe('#indexOf()', function() {
context('when not present', function() {
it('should not throw an error', function() {
(function() {
[1,2,3].indexOf(4);
}).should.not.throw();
});
it('should return -1', function() {
[1,2,3].indexOf(4).should.equal(-1);
});
});
context('when present', function() {
it('should return the index where the element first appears in the array', function() {
[1,2,3].indexOf(3).should.equal(2);
});
});
});
});
BDD
- Behaviour Driven Development
- BDD is meant to eliminate issues that TDD might cause
- The ability to read your tests like a sentence is a cognitive shift in how you will think about your tests
- BDD is to help design the software, not test it like what TDD is meant to do
var assert = require('assert'),
factorial = require('../index');
describe('Test', function (){
before(function(){
// Stuff to do before the tests, like imports, what not
});
describe('#factorial()', function (){
it('should return 1 when given 0', function (){
factorial(0).should.equal(1);
});
it('should return 1 when given 1', function (){
factorial(1).should.equal(1);
});
it('should return 2 when given 2', function (){
factorial(2).should.equal(2);
});
it('should return 6 when given 3', function (){
factorial(3).should.equal(6);
});
});
after(function () {
// Anything after the tests have finished
});
});
TDD vs BDD
-
It depends on if there is an appropriate testing framework for your given target language, what your coworkers are comfortable with, and sometimes other factors.
-
BDD is more about specification then testing
assertEquals(count,5) // TDD
$(count).should_be(5) // BDD
TDD
- define a test set for the unit first
- implement the unit
- finally verify that the implementation of the unit makes the tests success
BDD
- working outside-in, starting from a business or organizational goal
- using examples to clarify requirements
-
developing and using a ubiquitous language
- Scenario 1 : Refunded items should be returned to stock
- Given : a customer previously bought a black sweater from me
- And : I currently have three black sweater left in stock
- When : he returns the sweater for a refund
- Then : I should have four black sweaters in stock
Written on August 2, 2016