assert 模块还可以检查程序抛出消息 是否正确。throws 调用中的第二个参数是一个正则表达式,表示要在错误消息中检查文本 requires
function throwsTest(cb) { assert.throws(todo.add, /requires/); testsCompleted++; }运行测试
测试已经定义好了,接下来要在测试文件中添加运行这些测试的代码,下面的代码会运行前面的定义的所有测试,然后输出完成的测试数量。
deleteTest(); addTest(); throwsTest(); doAsyncTest(() => { console.log(`Completed ${testsCompleted} tests`); })如果测试成功了,脚本会告诉你以完成的测试数量。要防止某个测试出问题,可以追踪测试的开始和结束时间。比如说,某个测试可能没能执行到断言的地方。
使用 Node 自带的 assert 模块时,每个测试用例中都要包含很多套路化的代码用以设置测试(比如删除所有事项),追踪测试进程(’已完成‘计数器)。这些套路化的代码会占用编写测试用例的时间和精力。如果能把这些工作交给专用的框架,让你的精力都放在业务员逻辑的测试上就更好。接下来用 Mocha,了解一下如何使用这个第三方单玉测试框架让 工作变得更加轻松。
MochaMocha 是个流行的测试框架,很容易上手,尽管 Mocha 默认是 BDD 风格的。但也可以用在 TDD 风格的测试中。Mocha 具有很多特性,包括全局变量泄露检测和客户端测试。
全局变量泄露测试
一般应该不需要整个程序范围内全都可读的全局变量,并且按照编程最佳实践来说,要尽量少用全局变量。但在 ES5中,一不小心就创建了一个全局变量来,只要在声明变量时忘记写 关键字 var ,这个变量就是全局变量了。Mocha 能够发现这种不小心创建出来的全局变量泄露,如果你创建了全局变量,它会在测试时抛出错误。如果你想禁用全局泄露检查,可以运行 mocha 命令时加上 --ignored-leaks 选项。此外,如果要指明要使用的几个全局变量,可以把它们放在 --globals 后面,用逗号隔开。
Mocha 测试默认使用 BDD 风格的函数定义和设置,这些函数包括 describe、it、before、after、beforeEach和 afterEach,另外,Mocha 也有 TDD 接口,用 suite 代替 describe,test代替 it,setup 代替 before ,teardown 代替 after。
用 Mocha测试 Node 程序
初始化 package.json,定义 scripts:
"scripts": { "test": "mocha" },安装依赖:
npm i -S mocha测试会放在 test 目录下。Mocha 默认使用 BDD 接口,Mocha 测试的基本结构
// test/memdb.js const memdb = require('..'); describe('memdb', () => { describe('.saveSync(doc)', () => { it('should save the document', () => { }); }); });Mocha 也支持 TDD 和 qunit 以及 exports 风格的接口,下面是一个例子
module.exports = { 'memdb':{ '.saveSync(doc)':{ 'should save the document':()=>{ } } } }这些接口提供的功能是一样的,依然用的是默认的 BDD 接口,下面是第一个测试
const memdb = require('..'); const assert = require('assert'); describe('memdb', () => { describe('.saveSync(doc)', () => { it('should save the document', () => { const pet = { name: 'Tobi' }; memdb.saveSync(pet); const ret = memdb.first({ name: 'Tobi' }); assert(ret == pt); }); }); });添加 saveSync 功能
const db = []; exports.saveSync = (doc) => { db.push(doc); } exports.first = (obj) => { return db.filter(doc => { for (let key in obj) { if (doc[key] != obj[key]) { return false; } } return true; }).shift(); }describe块被称为测试套件,表示一组相关的测试,它是一个函数,第一个参数是测试套件的名称,第二个参数是一个实际执行的函数。
it块被称为测试用例,表示一个单独的测试,是测试的最小单位,也是一个函数,第一个参数是测试用例的名字,第二个参数是一个实际执行的函数。
所有的测试用例都应该含有一句或多句的断言,它是编写测试用例的关键,断言功能由断言库来实现。
用 Mocha挂钩定义设置和清理逻辑
BDD 接口 beforeEach()、afterEach()、before()和 after()接受回调,可以用来定义设置和清理逻辑。
const memdb = require('..'); const assert = require('assert'); describe('memdb', () => { beforeEach(() => { memdb.clear(); }); describe('.saveSync(doc)', () => { it('should save the document', () => { const pet = { name: 'Tobi' }; memdb.saveSync(pet); const ret = memdb.first({ name: 'Tobi' }); assert(ret == pet); }); }); describe('.first(obj)', () => { it('should return the first matching doc', () => { const tobi = { name: 'Tobi' }; const loki = { name: 'Loki' }; memdb.saveSync(tobi); memdb.saveSync(loki); let ret = mendb.first({ name: 'Tobi' }); assert(ret == tobi); ret = memdb.first({ name: 'Loki' }); assert(ret == loki); }); }); it('should return null when no doc matches', () => { const ret = mendb.first({ name: 'Manny' }); assert(ret == null); }); });