理解断言库
断言库可以理解为比较函数,也就是断言函数是否和预期一致,如果一致则表示测试通过,如果不一致表示测试失败。mocha本身是不包括断言库的,所以必须引入第三方断言库的,目前比较受欢迎的断言库有 should.js, expect.js, chai.
should.js BDD风格
expect.js expect风格的断言
chai expect(), assert() 和 should的断言
Mocha默认使用的是BDD的风格。expect和should都是BDD的风格,二者使用相同的链式语言来组织断言的,但不同在于他们初始化断言的方式,expect使用
构造函数来创建断言对象实例,而should通过为 Object.prototype新增方法来实现断言(should不支持IE),expect直接指向 chai.expect,
should则是 chai.should();
我们需要在项目中安装 chai, 如下命令:(配合mocha使用,本文只单独介绍chai语法)
1 |
npm install --save-dev chai |
所有的测试用例(it块)都应该含有一句或多句断言,是编写测试用例的关键,Mocha本身不包含断言,断言是由断言库来实现的,因此需要先引入断言库。
如下代码:
1 |
var expect = require('chai').expect; |
上面代码是引用 chai 断言库,使用的是 expect断言风格。
如下是一些常用的比较;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
// equal 相等或不相等 expect(4 + 5).to.be.equal(9); expect(4 + 5).to.be.not.equal(10); expect('hello').to.equal('hello'); expect(42).to.equal(42); expect(1).to.not.equal(true); expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' }); expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' }); // above 断言目标的值大于某个value,如果前面有length的链式标记,则可以用来判断数组长度或者字符串长度 expect(10).to.be.above(5); expect('foo').to.have.length.above(2); expect([ 1, 2, 3 ]).to.have.length.above(2); 类似的还有least(value)表示大于等于;below(value)表示小于;most(value)表示小于等于 // 判断目标是否为布尔值true(隐式转换) expect('everthing').to.be.ok; expect(1).to.be.ok; expect(false).to.not.be.ok; expect(undefined).to.not.be.ok; expect(null).to.not.be.ok; // true/false 断言目标是否为true或false expect(true).to.be.true; expect(1).to.not.be.true; expect(false).to.be.false; expect(0).to.not.be.false; // null/undefined 断言目标是否为null/undefined expect(null).to.be.null; expect(undefined).not.to.be.null; expect(undefined).to.be.undefined; expect(null).to.not.be.undefined; // NaN 断言目标值不是数值 expect('foo').to.be.NaN; expect(4).not.to.be.NaN; // 判断类型大法(可以实现上面的一些例子):a/an expect('test').to.be.a('string'); expect({ foo: 'bar' }).to.be.an('object'); expect(foo).to.be.an.instanceof(Foo); expect(null).to.be.a('null'); expect(undefined).to.be.an('undefined'); expect(new Error).to.be.an('error'); expect(new Promise).to.be.a('promise'); // 包含关系:用来断言字符串包含和数组包含。如果用在链式调用中,可以用来测试对象是否包含某key 可以混着用。 expect([1,2,3]).to.include(2); expect('foobar').to.contain('foo'); expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo'); // 判断空值 expect([]).to.be.empty; expect('').to.be.empty; expect({}).to.be.empty; // match expect('foobar').to.match(/^foo/); // exist 断言目标既不是null也不是undefined var foo = 'hi' , bar = null, baz; expect(foo).to.exist; expect(bar).to.not.exist; expect(baz).to.not.exist; // within断言目标值在某个区间范围内,可以与length连用 expect(7).to.be.within(5,10); expect('foo').to.have.length.within(2,4); expect([ 1, 2, 3 ]).to.have.length.within(2,4); // instanceOf 断言目标是某个构造器产生的事例 var Tea = function (name) { this.name = name; } , Chai = new Tea('chai'); expect(Chai).to.be.an.instanceof(Tea); expect([ 1, 2, 3 ]).to.be.instanceof(Array); // property(name, [value]) 断言目标有以name为key的属性,并且可以指定value断言属性值是严格相等的,此[value]参数为可选,如果使用deep链式调用,可以在name中指定对象或数组的引用表示方法 // simple referencing var obj = { foo: 'bar' }; expect(obj).to.have.property('foo'); expect(obj).to.have.property('foo', 'bar');// 类似于expect(obj).to.contains.keys('foo') // deep referencing var deepObj = { green: { tea: 'matcha' }, teas: [ 'chai', 'matcha', { tea: 'konacha' } ] }; expect(deepObj).to.have.deep.property('green.tea', 'matcha'); expect(deepObj).to.have.deep.property('teas[1]', 'matcha'); expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha'); // ownproperty 断言目标拥有自己的属性,非原型链继承 expect('test').to.have.ownProperty('length'); // throw 断言目标抛出特定的异常 var err = new ReferenceError('This is a bad function.'); var fn = function () { throw err; } expect(fn).to.throw(ReferenceError); expect(fn).to.throw(Error); expect(fn).to.throw(/bad function/); expect(fn).to.not.throw('good function'); expect(fn).to.throw(ReferenceError, /bad function/); expect(fn).to.throw(err); expect(fn).to.not.throw(new RangeError('Out of range.')); // satisfy(method) 断言目标通过一个真值测试 expect(1).to.satisfy(function(num) { return num > 0; }) |
expect 官网API(http://chaijs.com/api/bdd/)