理想的情况下,测试用例不会共享状态,要让 memdb 达到这一状态,只需要在 index.js 中实现 .clear 方法来移除所有的文档就可以了。
exports.clear = () => { db.length = 0; }测试异步逻辑
为了演示异步测试,需要做一些改动,将 saveSync 函数加一个会在短暂延迟之后执行的回调(用来模拟某中异步操作)作为可选的参数:
exports.saveSync = (doc, cb) => { db.push(doc); if (cb) { setTimeout(() => { cb(); }, 1000); } }只要给定义测试逻辑函数添加一个参数,就可以把 Mocha 测试用例定义为异步的。这个参数通常被命名为 done,下面的代码中演示了如何给异步方法 .save() 写测试用例。
describe('asyncronous .saveSync(doc)', () => { it('should save the document', (done) => { // 保存文档 const pet = { name: 'Tobi' }; memdb.saveSync(pet, () => { // 用第一个文档调用回调 const ret = memdb.first({ name: 'Tobi' }); assert(ret == pet); // 告诉Mocha 这个测试用例完成了 done(); }); }); });这个规则适用于所有挂钩,比如给 beforeEach() 挂钩一个清理数据库的回调,Mocha 可以等它调用后再继续,如果调用 done()时它的第一个参数是个错误,Mocha会报告这个错误,并将这个挂钩或测试用例标记为失败:
beforeEach((done) => { memdb.clear(done); });Mocha 的非并行测试
Mocha的测试不是并行测试的,而是一个接一个地测试,虽然这样执行慢,但写起来更容易。Mocha不会让测试运行太长时间,一个测试默认不超过 2000毫秒,超过这个时长会被当做失败的测试。如果有运行时间长的测试,可以用 --timeout 指定一个更大的数值。
不过说到并行的执行测试的框架有一个叫做 Vows的。
Vows跟很多单元测试框架比,在Vows 下写的测试代码结构更加强,Vows想让测试更容易理解和维护。
Vows 用它自己的BDD 属于定义测试结构。按Vows 的定义,一个测试套件中包含一个或多个批次。可以把批次当做是一组相互关联的情境,或者要测试的概念领域。批次和上下文是并行运行的。上下文中可能包含主题、一个或多个誓约,以及/或者一或多个先关联的情境(内部情况也是并行运行的)。主题是跟情境相关的测试逻辑。誓约是对主题结果的测试。
套件---批次---情境-----主题 |----誓约 |----情境Vows 跟 Mocha 一样,是专门用来做自动化程序测试的。它们的差别主要体现在风格和并行性上,Vows 测试有特定的结构和术语。
先初始化,并安装依赖
npm init -y npm i -S -g vows修改 package.json test属性
"scripts": { "test": "vows test/*.js" }用 Vows 测试程序逻辑
在 Vows 中,既可以运行包含测试逻辑的脚本来触发测试,也可以用 vows 命令行测试运行器。下面这个例子是个独立的测试脚本,用了待办事项程序核心逻辑测试中的一个。
下面的代码创建一个批次,在这个批次中定义了一个情景,情景中定义了一个主题和一个誓约。注意它在主题如何使用回调处理一般逻辑,如果主题不是异步的,可以直接返回值,不用通过回调。
// test/todo-test.js const vows = require('vows'); const assert = require('assert'); const Todo = require('../todo'); // 批次 vows.describe('Todo').addBatch({ // 情景 'when adding an item': { // 主题 topic: () => { const todo = new Todo(); todo.add('Feed my cat'); return todo; }, // 誓约 'it should exist in my todos': (er, todo) => { assert.equal(todo.length, 1); } } }).export(module); // todo.js class Todo { constructor() { this.todos = []; } add(item) { if (!item) throw new Error('Todo.prototype.add requires an item'); this.todos.push(item); } deleteAll() { this.todos = []; } get length() { return this.todos.length; } doAsync(cb) { setTimeout(cb, 2000, true); } } module.exports = Todo;Vows 提供了完备的测试方案,但仍然可以用别的断言库将不同测试库的功能混合搭配到一起.另外还有一个叫做 Chai的断言库,它可以代替 assert 模块。
ChaiChai 是个流行的断言库,有三个接口:should、expect 和 assert。下面的代码中用到了 assert ,其看起来就像是 Node 自带的 assertion 模块,但它还有用来比较对象、数组和它们的属性的工具。比如用 typeof比较类型,用 property检查某个对象是否有我们想要的属性。
const chai = require('chai'); const assert = chai.assert; const foo = 'bar'; const tea = { flavors: ['char', 'earl grey', 'pg tips'] }; assert.typeOf(foo, 'string'); assert.equal(foo, 'bar'); assert.lengthOf(foo, 3); assert.property(tea, 'flavors'); assert.lengthOf(tea.flavors, 3);