测试模块及其应用程序
为了减少上线到生产环境下,程序有某些BUG影响用户使用,必须测试所写的代码,可以使用人工手动检查,但是这样效率太低了,可能测试功能单一、简单的代码可行,但是一旦需要大量数据测试,那最好还是编写用来测试的代码让测试过程实现自动化。目的是创建覆盖全部代码的一些列测试,包括运行的主要情形和边缘情形。
一、应用测试运行工具
首先需要一种方式来定义测试,然后需要找到一个工具去运行测试代码。
有很多测试工具,本文选取node-tap
,选择他有几点原因:简单,很容易就支持异步测试,并且输出格式是基于某个标准的。
使用npm
安装它:
npm install tap --save-dev
但是最好呢,在package.json文件中应该这么写:
"devDependencies": {
"tap": "*"
}
这样的意思是,在开发模式下使用这个模块,即当程序上线到生产环境之后,就不需要这个模块了。
当要上线的时候,可以使用-production
选项跳过安装devDependencies中声明的模块。
npm install -production
编写测试
一般会在项目目录中额外新建一个目录来存放测试脚本,一般命名为 tests。
获得test
构造函数:
const test = require('tap').test;
然后就可以定义一个测试了,需要提供一个测试名和一个包含测试代码的函数:
test('addition of 2 and 2 works', (t) => {
t.equal(2+2, 4, "2+2 should be 4");
t.end();
})
上面的代码中,声明了一个名为“addition of 2 and 2 works”的测试,然后向其传递了一个包含测试代码的函数,同时函数接收一个参数 t,该参数包含面相测试的控制对象,利用该对象可以测试是否符合期望。
显式地结束测试也非常重要,Node-tap 支持异步测试,即如果进行IO操作,测试在测试函数返回之后仍然会运行。只有在测试上调用 end 方法的时候,才会结束测试。
二、断言测试模块
测试需要一种验证方式,用来验证结果和你所期望的代码效果是否一致,因此前面的例子用到了node-tap内置的断言函数,目前可以使用Node内置的assert
模块。
2.1 使用断言模块
导入:
const assert = require('assert');
每个断言函数都会设置一个期望,如果期望条件不满足,就会抛出一个异常。
首先,可以测试值是否为真:
const a = true;
assert(a, "a is not true");
测试变量后面可以跟一个当测试失败时提供的显示消息,上述例子中判断了a是否为真。
assert可以按两种方式测试相等性:浅和深。浅相等性只是对提供的两个对象进行测试,而不会测试这两个对象中内嵌对象的相等性。相反,深相等性递归测试所有嵌套的对象。浅相等性通常用来比较标量对象,例如字符串和数字,而深相等性通常用于比较两个对象。
浅测试:
assert.equal(a, 10, "a =/= 10")
这个操作符和==
判断是一样的,那么可以知道下面的断言是通过的:
assert.equal("10", 10);
还可以用不等断言:
assert.notEqual();
还有严格模式:
assert.strictEqual('10', 10); // 失败,因为和 === 一样
但是下面是有效的:
assert.notStrictEqual('10', 10);
在浅测试中,两个对象的引用必须指向同一个对象,相等性断言才会有效:
assert.equal( {a:1} , {a:1} ); // 失败
这两个对象看起来一样,但在内存中却不是一样的对象,如果想要比较属性,那么就要用到深比较:
assert.deepEqual();
从Node 0.7开始,还可以用它来比较正则表达式:
assert.deepEqual(/a/ig, /a/gi);
深比较仅仅验证的是对象的可枚举属性,如果两个对象有不同的原型,但是他们的所有可枚举属性是相同的,那么就会判断一样。
2.2 使用 Node-Tap 中的断言函数
可以使用 .ok()
和 .notOk()
测试是否为真:
test('test', function(t){
t.ok(1,"1 is true");
t.notOk(0, "0 is false");
t.end();
})
还可以用.equal
测试相等性。
在测试两个对象的时候,可以使用等价性测试:
test('equal', function(t){
const a = {
a: 1,
b: 2
}
t.equivalent(a, {b:2,a:1});
t.end();
})
还可以测试对象的相似性:
a = { a:1 , b:2 };
t.similar(a, {a:1});
// 对于数字和字符串同样有效
测试对象类型:
t.type(1, "Number");
// 判断对象是继承自这个构造函数
t.type(a, Object);