基础概念和简单 API
TDD 模式
TDD(Test Driven Development): 测试驱动开发. 大致来说, 是在 Developer 开发之前,先写test case, 然后再来实现业务逻辑,写完之后再跑一遍测试用例, 看能否通过, 添加新功能, 也是现加测试用例, 然后新功能实现后, 再跑一次所有的测试用例.
接口执行顺序
- suiteSetup: 所有测试执行前执行一次
- setup: 每个测试执行前执行
- test: 具体的测试执行代码
- teardown: 每个测试执行完后执行一次
- suiteTeardown: 所有测试执行完后执行一次
Test Case 测试用例结构
- Setup: 准备好环境和数据
- Execution: 执行测试
- Validation: 验证结果
- Cleanup: 现场恢复
BDD 模式
BDD(Behavior Driven Development):行为驱动开发,BDD 旨在消除 TDD 过程中可能造成的问题,更注重功能本省而非单纯的测试用例运行结果。
主要 API
BDD 主要有两个 api:
- describe(name,fn):定义一组测试
- it(name,fn): 定义一项测试
describe('proxy', function() {
it('proxy data 1', function(done) {
this.timeout(1000);
assert.ok(true, 'fail');
});
//嵌套
describe('child1', function() {});
//只测试某一组
describe.only('testc1', function() {});
//跳过某一组测试
describe.skip('testc1', function() {});
});
only和skip可以用在describe上, 也可以用在it上.
BDD Hook
在整个测试周期中, mocha 提供了一组 hook:
- before: 所有测试之前
- after: 所有测试之后
- beforeEach: 每个测试之前
- afterEach: 每个测试之后
hook中的异步处理类似于it.
异步测试
以 BDD 的接口为例, 异步代码的测试,有回调和 Promise 两种方式:
- 回调
descibe('Array',function(){
if('shoule correct',function(done){
setTimeout(done,1000);
})
})
如果 done()执行的时候有参数,如 done('错误'), 那么 mocha 判定测试不通过。 你也可以直接传入一个 Error 对象到 done 函数中,如 done(new Error('fail'))
- promise
describe('Array', function() {
it('should correct', function() {
return Promise.resolve();
});
});
如果it 函数的返回值是一个promise, 将被是为是一个异步测试。并且根据promise的fullfill状态来决定测试是否通过。
箭头函数
mocha 不提倡使用箭头函数, 因为it,describe都是绑定 mocha context 执行的, 才箭头函数中无法获取 mocha context, 会报错.
describe('Array', () => {
it('shoule correct', done => {
this.timeout(1000); // can not read property timeout of undefind
});
});
命令行参数
这里简单的介绍一下常用的命令行参数, 认识即可, 具体使用的时候参考文档是最靠谱的:
--reporter,-R: 指定测试报告的格式,可以是tag,spec(默认),dot等等--growl,-G: 将测试结果显示在桌面--watch,-w: 监视指定的测试脚本, 一旦脚本发生变化, 就运行 mocha--bail,-b: 一旦一个测试用例没有通过,就停止执行后面的测试--grep, -g: 指定执行特定的次测试用例--invert, -i: 只运行不符合条件的测试脚本.使用如下:mocha --grep "1 加 1" --invert--compilers: 指定测试脚本的转码器--timeout, -t: 指定每个测试用例最多执行的时间,默认是 2000ms, 用该参数指定超时时间.--slow, -s: 高亮超过指定时间的测试用例,默认是 75ms
可以将命令行参数放在项目test目录下的mocha.opts文件中, 把命令行参数写在里面:
--reporter tap
--recursive
--growl
断言
mocha 没有自己的断言库, 所以可以使用第三方的断言,比如 node 的assert,chai等, 只要程序抛出一个错误, mocha 就会认为其测试不通过。
asset 断言
常用的asset断言函数(node 内置)
assert.fail(String|Error): 抛出一个 AssertionError,如果参数是一个 Error,则抛出一个 Errorassert.ifError(any): 只要 any, 不等于 undefined|null,就抛出 anyassert.ok(value[,message]): 测试 value 是否为 truthyassert.equal(actual,expected[,message]) | assert.notEqual(actual,expected[,message]): 对 actual 和 expected 执行==比较assert.strictEqual(),assert.notStrictEqual: 对 actual 和 expcted 执行===比较assert.deepStrictEqual(),assert.notDeepStrictEqual(): 测试是否深度全等,执行的是===比较。
chai 断言
chai 作为第三方的断言库, 支持 TDD 和 BDD 两种风格的测试, 其中 BDD 的风格有两种:expect和should. 本节不准备全面的介绍所有的 API 接口, 而选取了expect相关的风格接口. expect接口使用构造函数来创建断言对象实例, 而should通过Object.prototype新增方法来实现断言, 不支持IE. 除此之外, expect指向对象, should指向一个函数.
var chai = require('chai'),
expect = chai.expect,
should = chai.should();
语言链, 不提供测试能力, 只为了可读性:
to,be,been,is,that,which,and,has,have,with,at,of,same
常用断言链:
.not: 否定断言, 不推荐, 尽量使用期待断言, 而非期待断言.deep: 其后的断言深度但不严格相等.own: 其后的断言中的继承属性被忽略..nested: 其后的断言可以使用./[], 不可与own连用.ordered: 要求顺序.any: 至少有一个.all: 全部包含.lengthOf: 长度匹配.match: 正则匹配.string: 包含所给的字串.keys: 包含所给键.members: 数组成员相同.oneOf: 期待目标数组的成员.change: 断言改变的值.increase: 断言增长的值.decrease: 断言减少的值