chai使用指南

概述

chai 是一款辅助 TDD 测试驱动开发, BDD 行为驱动开发 的断言库。

有关 TDD 和 BDD,可参考:
开发人员看测试之TDD和BDD
TDD 已死?让我们再聊聊 TDD
BDD敏捷开发入门与实战

chai 的 TDD 模块只包含 assert 一种, BDD 模块包含 except, should 两种。

配置

  • chai.config.includeStack = false,错误输出中是否包含堆栈信息
  • chai.config.showDiff = true,是否显示 diff
  • chai.config.truncateThreshold = 40,错误输出中 actual, expexted 打印字符串上限???

api手册

TDD测试

assert

类似 node 的同名模块。

1
2
3
4
5
6
7
8
9
var assert = require('chai').assert
, foo = 'bar'
, beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };

assert.typeOf(foo, 'string'); // without optional message
assert.typeOf(foo, 'string', 'foo is a string');
assert.equal(foo, 'bar', 'foo equal `bar`');
assert.lengthOf(foo, 3, 'foo`s value has a length of 3');
assert.lengthOf(beverages.tea, 3, 'beverages has 3 types of tea');

apis

  • assert(expression, message),参数 expression 为待测试的语句
  • .fail(actual, expected, [message], [operator]),operator 为操作(默认为 !=)
  • .ifError(object),校验真值时抛出错误
  • .isOk/isNotOk/isTrue/isNotTrue/isFalse/isNotFalse/isNull/isNotNull/isNaN/isNotNaN/
    isUndefined/isDefined/isFunction/isNotFunction/isObject/isNotObject/isArray/isNotArray/
    isString/isNotString/isNumber/isNotNumber/isFinite/isBoolean/isNotBoolean(object, [message])
  • .exists/notExists(value, [message]),校验 value 不是 null 或 undefined
  • .typeOf/notTypeOf(value, type, [message]) 类型校验
  • .instanceOf/notInstanceOf(object, constructor, [message])
  • .match/notMatch(value, regexp, [message])
  • .equal/notEqual/strictEqual/notStrictEqual/deepEqual/notDeepEqual(actual, expected, [message]),’==’, ‘===’ 或 深度相等
  • .isAbove/isAtLeast/isBelow/isAtMost(valueToCheck, valueToBeAbove, [message]),以操作符 ‘>’, ‘>=’, ‘<’, ‘<=’ 校验
  • .operator(val1, operator, val2, [message]),’>’, ‘<’ 操作符校验
  • .closeTo(actual, expected, delta, [message]),actual 在 expected - delta, expected + delta 之间
  • .approximately(actual, expected, delta, [message]),同上
  • .changes/doesNotChange/increases/doesNotIncrease/decreases/
    doesNotDecrease(function, object, property, [message]),校验函数执行时是否改变对象属性
  • .changesBy/changesButNotBy/ncreasesBy/increasesButNotBy/decreasesBy/
    doesNotDecreaseBy/decreasesButNotBy(function, object, property, delta, [message]),校验属性数值改变 + delta
  • .lengthOf(object, length, [message]),校验字符串或数组的长度
  • .isExtensible/isNotExtensible/isSealed/isNotSealed/isFrozen/isNotFrozen(object)
  • .isEmpty/isNotEmpty(target),校验对象、数组、字符串、Map、Set非空
  • .oneOf(inList, list, [message])
  • .include/notInclude/deepInclude/notDeepInclude/nestedInclude/notNestedInclude/
    deepNestedInclude/notDeepNestedInclude/ownInclude/notOwnInclude/
    deepOwnInclude/notDeepOwnInclude(haystack, needle, [message]),校验是否包含数组项,子字符串,或者对象属性的截取。deep 为深度匹配,nest 以分隔符 . 或者 [] 校验嵌套属性,own 校验是否自有属性
  • sameMembers/notSameMembers/sameDeepMembers/notSameDeepMembers/
    sameOrderedMembers/notSameOrderedMembers/
    sameDeepOrderedMembers/notSameDeepOrderedMembers(set1, set2, [message]),校验 set 是否有相同的成员。orderd 顺序相同
  • .includeMembers/notIncludeMembers/includeDeepMembers/notIncludeDeepMembers/
    includeOrderedMembers/notIncludeOrderedMembers/
    includeDeepOrderedMembers/notIncludeDeepOrderedMembers(superset, subset, [message])
  • .property/notProperty/nestedProperty/notNestedProperty(object, property, [message])
  • .propertyVal/notPropertyVal/deepPropertyVal/notDeepPropertyVal/
    notNestedProperty/notNestedPropertyVal/
    deepNestedPropertyVal/notDeepNestedPropertyVal(object, property, value, [message])
  • .hasAnyKeys/hasAllKeys/containsAllKeys/doesNotHaveAnyKeys/
    doesNotHaveAllKeys/hasAnyDeepKeys/hasAllDeepKeys/
    containsAllDeepKeys/doesNotHaveAnyDeepKeys/doesNotHaveAllDeepKeys(object, [keys], [message])
  • .throws/doesNotThrow(fn, [errorLike/string/regexp], [string/regexp], [message]),校验函数 fn 将抛出指定类型及文案的错误

TDD测试 - except, should

except

提供链式调用。

1
2
3
4
5
6
7
8
var expect = require('chai').expect
, foo = 'bar'
, beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };

expect(foo).to.be.a('string');
expect(foo).to.equal('bar');
expect(foo).to.have.lengthOf(3);
expect(beverages).to.have.property('tea').with.lengthOf(3);

should

增强了 Object.property 功能,因此需先显示调用 chai.should 函数。

1
2
3
4
5
6
7
8
var should = require('chai').should() //actually call the function
, foo = 'bar'
, beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };

foo.should.be.a('string');
foo.should.equal('bar');
foo.should.have.lengthOf(3);
beverages.should.have.property('tea').with.lengthOf(3);

语言链修饰符

语言链修饰符用于增强代码的可读性,包含 to, be, been, isthat, and, has, have, with, at, of, same

apis

  • not 将断言置否,即否值满足断言,如 expect(function () {}).to.not.throw();
  • deep 深比较,如 expect({a: 1}).to.deep.equal({a: 1});
  • nested 嵌套属性,以 . 或 [] 分割,如 expect({a: {b: [‘x’, ‘y’]}}).to.have.nested.property(‘a.b[1]’);
  • own 如 expect({a: 1}).to.have.own.property(‘a’);
  • ordered 顺序比较,如 expect([1, 2]).to.have.ordered.members([1, 2]).but.not.have.ordered.members([2, 1]);
  • any/all 如 expect({a: 1, b: 2}).to.not.have.any.keys(‘c’, ‘d’);
  • .a/an(type[, msg]) 如 expect({a: 1}).to.be.an(‘object’);
  • .include(val[, msg]) 如 expect(‘foobar’).to.include(‘foo’);
  • .ok/true/false/null/undefined/NaN/exist/empty/arguments/finite 如 expect(arguments).to.be.arguments;
  • .eql(obj[, msg]) 如 expect({a: 1}).to.eql({a: 1}).but.not.equal({a: 1});
  • .above/least/below/most(n[, msg]) 如 expect(1).to.be.at.least(2);
  • .within(start, finish[, msg]) 如 expect(2).to.be.within(1, 3);
  • .instanceof(constructor[, msg]) 如 expect({a: 1}).to.not.be.an.instanceof(Array);
  • .property(name[, val[, msg]]) 如 expect({x: {a: 1}}).to.have.deep.property(‘x’, {a: 1});
  • .ownPropertyDescriptor(name[, descriptor[, msg]]) 如 expect({a: 1}).to.have.ownPropertyDescriptor(‘a’);
  • .lengthOf(n[, msg]) 如 expect([1, 2, 3]).to.have.lengthOf(3);
  • .match(re[, msg]) 如 expect(‘foobar’).to.match(/^foo/);
  • .string(str[, msg]) 包含子字符串,如 expect(‘foobar’).to.not.have.string(‘taco’);
  • .keys(key1[, key2[, …]]) 如 expect({a: 1, b: 2}).to.have.all.keys(‘a’, ‘b’);
  • .throw([errorLike], [errMsgMatcher], [msg]) 校验函数必须抛出错误,如 expect(badFn).to.throw();
  • .respondTo(method[, msg]) 校验对象是否有某方法,可以是继承的,如 expect(new Cat()).to.respondTo(‘meow’);
  • .itself 自有属性,如 expect(Cat).itself.to.respondTo(‘hiss’).but.not.respondTo(‘meow’);
  • .satisfy(matcher[, msg]) 校验是否匹配 matcher,如 expect(1).to.satisfy(function(num) { return num > 0; });
  • .closeTo(expected, delta[, msg]) 校验值在 expected - delta ~ expected + delta 范围内,如 expect(1.5).to.be.closeTo(1, 0.5);
  • .members(set[, msg]) 如 expect([1, 2, 3]).to.have.members([2, 1, 3]);
  • .oneOf(list[, msg]) 如 expect(1).to.be.oneOf([1, 2, 3]);
  • .change(subject[, prop[, msg]]) 执行函数后,引起对象或其属性改变,如 expect(addDot).to.change(myObj, ‘dots’);
  • .increase(subject[, prop[, msg]]) 值增加
  • .decrease(subject[, prop[, msg]]) 值减少
  • .by(delta[, msg]) 如 expect(addTwo).to.increase(myObj, ‘val’).by(2);
  • .extensible/sealed/frozen 对象可扩展性
  • .fail(actual, expected, [message], [operator]),operator 为操作(默认为 !=)