Mocha是一个简单易用的JavaScript测试框架,可以运行在Node.js中,也可以运行在浏览器中。 Mocha提供了多种类型的测试报告,支持多种断言库(包括should.jsexpect.jschai,等等)。 本文介绍利用chaiMocha中进行BDD风格的单元测试。

对于Github仓库,利用Mocha组织的测试还可以利用Git做持续集成,在Github上显示实时的代码测试状态,详见跟踪Github项目的持续集成状态一文。

编写一项测试

环境配置

创建一个叫做my-project的项目,以及一个空的测试文件test.jsMocha可以通过NPM来安装,我们需要一个全局的mocha以供命令行调用,以及一个本地的mocha以供代码中require

mkdir my-project && cd my-project
npm install -g mocha
npm install mocha chai

编写测试文件

现在来编写第一个测试文件my-project/test.js

var expect require('chai').expect;
describe('Array', function() {
    describe('#indexOf()', function () {
        it('should return -1 when the value is not present', function () {
            expect([1, 2, 3].indexOf(5)).to.equal(-1);
            expect([1, 2, 3].indexOf(0)).to.equal(-1);
        });
    });
});

my-project目录中,运行mocha即可运行所有的测试项(当然这里只有一项)。

➜  my-project mocha

  Array
    #indexOf()
      ✓ should return -1 when the value is not present

  1 passing (11ms)

测试代码组织

有时一个模块可能会非常复杂,单个测试文件可能会很长:

var expect require('chai').expect;
describe('Array', function() {
    describe('#indexOf()', function () {
        it('should return -1 when the value is not present', function () {
            expect([1, 2, 3].indexOf(5)).to.equal(-1);
            expect([1, 2, 3].indexOf(0)).to.equal(-1);
        });
        it('should return index when the value exist', function () {
            expect([1, 2, 3].indexOf(2)).to.equal(1);
            expect([1, 2, 3].indexOf(3)).to.equal(2);
        });
    });
    describe('#map()', function () {
        ...
    });
    ...
});

每个describe可以单独组织为文件,例如:

// file: test.js
describe('Array', function() {
    require('./array/indexOf.js');
    require('./array/map.js');
    ...
});
// file: array/indexOf.js
describe('#indexOf()', function () {
    it('should return -1 when the value is not present', function () {
        expect([1, 2, 3].indexOf(5)).to.equal(-1);
        expect([1, 2, 3].indexOf(0)).to.equal(-1);
    });
    ...
});
// file: array/map.js
describe('#map()', function () {
    ...
});

BDD:should 还是 expect

Chai为Mocha提供了BDD风格的断言库, BDD(Behaviour Driven Development)是TDD的一种, 倾向于断言被测对象的行为特征而非输入输出。 Chai的BDD风格断言库包括两部分:expectshould。 Harttle推荐使用expect。先看例子:

expect测试

var expect = require('chai').expect;
it('should return -1 when the value is not present', function () {
    expect([1, 2, 3].indexOf(5)).to.equal(-1);
    expect([1, 2, 3].indexOf(0)).to.equal(-1);
});

可见expect是个函数,它接受的输入是被测试的值,返回值拥有.to属性。

should测试

上述测试也可以使用should断言库来编写:

var should = require('chai').should();
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);
});

可见shouldObject.prototype增加了一个.should属性。 该操作是在require('chai').should()should()函数调用中完成的。

区别之处

shouldexpect只是语法有细微区别,都属于BDD风格测试断言。 但Harttle推荐使用expect,因为当被测对象为空时should就会失效, 而expect仍然能够给出有效的调试信息。例如:

// foo === undefined
foo.should.equal('bar');

should给出的错误信息是:TypeError: Cannot read property 'should' of undefined。 而使用expect写法时:

// foo === undefined
expect(foo).to.equal('bar');

Mocha给出的错误信息更加有用:AssertionError: expected undefined to equal 'foo'

本文采用 知识共享署名 4.0 国际许可协议(CC-BY 4.0)进行许可,转载注明来源即可: https://harttle.land/2016/06/23/mocha-chai-bdd.html。如有疏漏、谬误、侵权请通过评论或 邮件 指出。